Platform Comparison

Unchained vs MedusaJS

A technical deep-dive comparing two open-source e‑commerce engines. GraphQL-first vs REST-first, MongoDB vs PostgreSQL, EUPL vs MIT — and the built-in features that set them apart.

Unchained
GraphQL
Plugins
MongoDB
vs
MedusaJS
REST
Modules
PostgreSQL
Architecture

Architecture at a Glance

Two open-source engines, two fundamentally different approaches to building e‑commerce backends.

Unchained
GraphQL API
Plugin System
PaymentsDeliveryMessagingWarehousing
MongoDB
+ PostgreSQL via FerretDB
28 independent NPM packages
MedusaJS
REST API
+ GraphQL via module
Module System
ServicesRepositoriesSubscribers
PostgreSQL
Monorepo module architecture
Comparison

Feature-by-Feature Comparison

Side-by-side breakdown of capabilities across core, built-in features, enterprise, and infrastructure.

FeatureUnchainedMedusaJS
Core
LicenseEUPL (Copyleft)MIT
Primary APIGraphQL-firstREST-first
DatabaseMongoDBPostgreSQL
LanguageNode.js + TypeScriptNode.js + TypeScript
Built-in Features
Subscriptions / EnrollmentsYesPlugin required
Quotations / RFQYesNo
Event TicketingYesNo
Product CatalogYesYes
Order ManagementYesYes
Payment IntegrationsYesYes
Enterprise
B2B FeaturesAdvancedBasic
MCP / AI IntegrationYesNo
OCSF Audit TrailYesNo
WebAuthn / PasskeysYesNo
Infrastructure
Docker-nativeYesYes
Horizontal ScalingStatelessStateless
NPM Packages28 packagesMonorepo modules
API Design

GraphQL vs REST

Unchained exposes a GraphQL API by default, letting you fetch exactly the data you need in a single request. MedusaJS uses REST endpoints, often requiring multiple round-trips for the same data.

Unchained — Single GraphQL Query
storefront.ts
// Single GraphQL query — products with variants, pricing & stock
const { data } = await client.query({
  query: gql`
    query Products($limit: Int) {
      products(limit: $limit) {
        _id
        texts { title description }
        simulatedPrice(currency: "CHF") {
          price { amount currency }
        }
        catalogChildren {
          _id
          texts { title }
          simulatedStocks { quantity }
        }
      }
    }
  `,
  variables: { limit: 10 }
});
MedusaJS — Multiple REST Calls
storefront.ts
// Multiple REST calls required for the same data
const products = await fetch('/store/products?limit=10')
  .then(r => r.json());

// For each product, fetch variants separately
const variants = await Promise.all(
  products.map(p =>
    fetch(`/store/products/${p.id}/variants`)
      .then(r => r.json())
  )
);

// Prices require another endpoint
const prices = await fetch('/store/pricing/calculate', {
  method: 'POST',
  body: JSON.stringify({
    product_ids: products.map(p => p.id),
    currency_code: 'chf'
  })
}).then(r => r.json());

// Stock levels from inventory module
const stock = await fetch('/admin/inventory-items')
  .then(r => r.json());

Type Safety

GraphQL schemas provide compile-time type checking and auto-generated TypeScript types for every query.

Fewer Round-Trips

Fetch products, variants, prices, and stock in one request instead of chaining multiple REST calls.

Introspection

The schema is self-documenting. Tools like GraphQL Playground let you explore the entire API interactively.

Database

Database Architecture

Different storage engines reflect different trade-offs: schema flexibility vs relational integrity.

MongoDB (Unchained)

  • Flexible document schemas — embed variants, prices, and metadata directly inside product documents
  • Schema-less evolution — add fields without migrations
  • Horizontal scaling with native sharding
  • PostgreSQL compatible via FerretDB when DB is not a choice

PostgreSQL (MedusaJS)

  • ACID transactions for every write
  • Normalized relational model with strong referential integrity
  • Mature ecosystem of extensions (PostGIS, pg_trgm, etc.)
  • JOIN-based queries across orders, products, and customers
Extensibility

Plugin & Module System

Both platforms are extensible, but they take different architectural approaches to customization.

Both Follow DDD Principles

Both engines apply domain-driven design with the Open/Closed Principle, layered architecture, adapters & factories, and dependency inversion. The core patterns are similar — the differences lie in naming and implementation details.

Unchained: Adapter-Based Plugins

Each concern (payments, delivery, messaging, warehousing) has a clearly defined adapter interface. Swap providers by registering a different adapter — no core changes required.

MedusaJS: Service/Repository Pattern

Uses services, repositories, and subscribers. Modules are organized in a monorepo and extend the core through dependency injection and lifecycle hooks.

boot.ts
import { startPlatform } from '@unchainedshop/platform';
import { stripePayments } from '@unchainedshop/plugins';

await startPlatform({
  modules: {
    // Adapter-based plugin system
    payments: {
      adapters: [stripePayments],
    },
    delivery: {
      adapters: [postDelivery],
    },
    messaging: {
      adapters: [sendgridMessaging],
    },
    warehousing: {
      adapters: [customWarehouse],
    },
  },
});
Enterprise

Built-in Enterprise Features

Features that Unchained ships natively — no plugins, no third-party services, no extra cost.

Subscriptions & Enrollments

Recurring billing, membership management, and enrollment workflows built into the core engine.

Quotations & RFQ

B2B negotiation workflows with request-for-quote, approval chains, and custom pricing per customer.

Event Ticketing

Apple Wallet and Google Wallet passes, QR code generation, and check-in management out of the box.

MCP Server

Native AI assistant integration via the Model Context Protocol. Let AI agents browse products, manage carts, and place orders.

OCSF Audit Trail

Compliance-grade logging following the Open Cybersecurity Schema Framework for full operational transparency.

WebAuthn / Passkeys

Passwordless authentication with biometric and hardware key support. FIDO2-compliant and phishing-resistant.

Ready to Build with Unchained?

Start building your next e‑commerce project on a GraphQL-first, enterprise-ready platform licensed under the EUPL.

EUPL LicenseGraphQL APIMongoDBSwiss-Made