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.

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 independentMonorepo 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
class="code-comment">// 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
class="code-comment">// Multiple REST calls required for the same data
const products = await fetch('/store/products?limit=10')
  .then(r => r.json());

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

class="code-comment">// 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());

class="code-comment">// 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 relational guarantees are needed

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.

Unchained: Adapter-Based Plugins

Unchained uses an adapter pattern where each concern (payments, delivery, messaging, warehousing) has a clearly defined interface. Swap providers by registering a different adapter — no core changes required. Each of the 28 NPM packages can be installed independently.

MedusaJS: Service/Repository Pattern

MedusaJS uses a module-based architecture with 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: {
    class="code-comment">// 28 independent NPM packages
    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