Table of Contents

Architecture

Commerce is one deployable: a single ASP.NET Core application containing nine domains and seven modules, over one database. There are no microservices and no message broker. That is a decision, not a stage it has not reached yet.

  • Deployables 1 API, 1 migrator
  • API surfaces 4, authenticated differently
  • Domains 9
  • Modules 7
  • Databases 1, with 12 EF contexts

Commerce Core

  • Commerce's own code
  • Trader Core — framework, not ours
  • External service
  • Data
  • Caller, outside Commerce
  • owns a database context
Callers
Storefrontbrowser, per user
Admin UIback office
Upstream systemsERP, middleware
External integratorsthird parties
Entry points — the route prefix decides the scheme, the scope and the error shape
/authCookie ⇄ Entra OIDC
/api/uiCookie session · scoped
/api/adminCookie + policy
/api/integrationBearer JWT
/api/publicAPI key · rate limited
Commerce Core
Host — the only executable in the request path
Controllers
Brokerscross-domain composition
Auth pipeline
Customer scope
Rate limiting
Error shaping
Domains — each owns a slice of the business, and its data
Tradingbasket, orders
Catalogueproducts, search
Pricingprice lists, promotions
Inventorystock, reservations
Customeraccounts, ledger
Authenticationusers, sessions, tokens
Fulfilmentshipping, routing
Taxrates, calculation
Cmscontent
Modules — capabilities domains share
Coreentity conventions
BusinessCentralERP client
Paymentproviders, surcharge
Notificationstemplated email
SiteConfigurationsettings, locations
AddressAutoCompletelookup
Honeybeeproduct enrichment
Cross-cutting — provided by Trader Core
Settings
Caching
Event queue
Background engines
Auditing
Query criteria
Key sequences
Roles
External services — called out to
Business Centralthe ERP
Entra External IDidentity
Azure AI Searchproduct search
Communication Servicesemail
Stripe · PayWaycard payment
Google Placesaddress lookup
Honeybeeproduct data
Data
One SQL database12 EF contexts, one per data owner
Queue tableasync work, same transaction
Search indexAzure AI Search, fed from a SQL view

Twelve blocks carry a ◆ — nine domains and three modules — and those are the twelve database contexts. Everything grey is framework rather than product, which is the distinction the next two sections are about.

Three rules hold it together

Rule 1

References point one way

Host → domain → module. Never back up, and never sideways: a domain does not reference another domain. Enforced by the project graph, so breaking it is a compile error rather than a code-review argument.

Rule 2

Composition happens at the edge

A basket needs pricing, tax, stock, freight and the catalogue. Rather than let one domain reach into four others, a broker in the host assembles the answer — so domains stay ignorant of each other.

Rule 3

Parts are discovered, not registered

Adding a domain is adding a project and a class. Startup finds it by reflection and the migrator picks up its database context through the same bootstrap. No central file to edit, so nobody collides in one.

Together these are what make a domain a unit you can clone. That is the whole productisation bet: the second client should add domains and configuration, not fork the codebase.

What is Trader Core, and what is ours

The grey blocks above. Commerce uses Trader Core as a framework but does not take all of it — each surface is an owned choice, which matters when you are reading unfamiliar code and wondering where a behaviour comes from.

Taken from Trader Core The module structure and discovery pattern · settings · caching · the durable event queue · background engines · key sequences · query criteria · the EF context base
Commerce's own Authentication and session · the HTTP pipeline and its four surfaces · cross-domain composition · every domain model
Deliberately not used The Essentials.Api meta-package, and with it Trader Core's authentication, authorization and context providers

That last row surprises people. The host re-implements Trader Core's two bootstrapping methods itself rather than inheriting the meta-package, precisely so that authentication could be Commerce's own. It is not an oversight, and adding the meta-package back would quietly replace the auth model.

Entry points

Four API surfaces on one host — the UI API, the back office API, the integration API and the public API — at /api/ui, /api/admin, /api/integration and /api/public, plus /auth for sign-in. The route prefix decides everything: which scheme authenticates the caller, whether the request is scoped to one customer, what shape responses take, and what a failure looks like on the wire.

Only /api/ui is scoped. Everywhere else runs unscoped by design — an integration endpoint upserting stock for every customer has no single customer to be scoped to. The same split reaches all the way down into how queries are filtered.

API surfaces compares the four side by side and gives each one a page.

Go deeper

Authentication A cookie session in front of Entra External ID, the four schemes, and why the browser never holds a token
API surfaces The four doors in, and how each behaves differently
Database One database, twelve contexts, the conventions every entity inherits, and why it is not one database per domain
Patterns The eleven ideas that recur, and when to reach for each
Decisions What was chosen, what was rejected, and why. Planned.