Assembling the machine…
MCH-001 is running
Software architecture, drawn as machines you can run.
Each concept is a 3D machine in your browser. Scroll, and a real request travels through the first one, hexagonal architecture, step by step. Then a switch changes the machine, and you see what the pattern protects you from.
Scroll to run MCH-001
MCH-001 · Place an order
Hexagonal architecture, step by step.
Also called ports and adapters: the business core owns its interfaces and depends on nothing outside it. Scroll, and one order goes through it.
Step 1 / 8 · Place an order
The application starts
Before any request, the configurator creates each adapter and plugs it into its port. Postgres answers OrderRepository: decided here, once, not in the core.
- 0.00 msCONFIGPlaceOrder ← HttpAdapter
- 0.00 msCONFIGOrderRepository ← PostgresAdapter
- 0.00 msCONFIGPaymentGateway ← PaymentProviderAdapter
Step 2 / 8 · Place an order
A request arrives
POST /orders reaches the HTTP adapter. It turns the request into a PlaceOrder command, nothing more.
- 0.00 msREQPOST /orders →
HttpAdapter
- 0.00 msREQPOST /orders →
Step 3 / 8 · Place an order
Through the input port
The adapter calls PlaceOrder, an interface the core owns. The adapter depends on the core, not the other way round.
- 0.05 msREQHttpAdapter →
PlaceOrder (in port)
- 0.05 msREQHttpAdapter →
Step 4 / 8 · Place an order
The core applies the rules
An order needs at least one line and a positive total. Pure business logic: no SQL, no HTTP, no framework.
- 0.06 msRULEorder#1042 lines > 0 OK · total > 0 OK
Step 5 / 8 · Place an order
Out through OrderRepository
The core saves the order through a port it declares. It does not know which storage will answer.
- 0.07 msWRITEOrderRepository.
save(order#1042)
- 0.07 msWRITEOrderRepository.
Step 6 / 8 · Place an order
Postgres answers
The Postgres adapter implements OrderRepository and runs the INSERT. The core never wrote a line of SQL.
- 4.27 msWRITEPostgresAdapter INSERT INTO orders
Step 7 / 8 · Place an order
Payment through PaymentGateway
The core charges the customer through another port. The payment provider is only one adapter behind it.
- 184.28 msREQPaymentGateway.
charge(49.00 EUR) → PaymentProviderAdapter
- 184.28 msREQPaymentGateway.
Step 8 / 8 · Place an order
The response goes back
201 Created. The HTTP adapter turns the result into a response. The core never saw HTTP.
- 184.34 msRESP201 Created order#1042
What if · Step 6 / 8
InMemory answers
Same port, different adapter: a Map answers in a hundredth of a millisecond. Not a single domain file changed.
- 0.08 msWRITEInMemoryAdapter map.
set(1042)
- 0.08 msWRITEInMemoryAdapter map.
What if · Step 6 / 8
The swap breaks the core
InMemory is plugged into OrderRepository, but the core still calls Postgres, now on the bench. Changing storage means editing the domain.
- 4.26 msERROrder domain →
PostgresAdapter · not wired, the core must change
- 4.26 msERROrder domain →
End of the run · 184.34 ms
One request, one machine, every step on the record.
On its own page, MCH-001 plays two more scenarios, a declined payment and an empty order, and lets you flip every switch yourself.
Drawing register
Eight machines on the drawing board.
One is issued each week, and which one comes next is put to a vote on X. Point at a sheet to pull it from the drawer.
Hexagonal architecture
- Scale
- NTS
- Rev
- A
- Source
- A. Cockburn, 2005
| Dwg no. | Title | Family | Status | Rev |
|---|---|---|---|---|
| MCH-001 | Hexagonal architecture | Backend | Issued | A |
| MCH-002 | JavaScript event loop | Frontend | In draft | — |
| MCH-003 | Domain-driven design | Backend | In draft | — |
| MCH-004 | Offline-first sync | Mobile | In draft | — |
| MCH-005 | CQRS and event sourcing | Backend | In draft | — |
| MCH-006 | React rendering | Frontend | In draft | — |
| MCH-007 | Redis cache-aside | Infra | In draft | — |
| MCH-008 | Kafka partitions and consumer groups | Infra | In draft | — |
Legend
Learn to read one machine, and you can read them all.
Every machine is drawn with the same symbols. Here they are on MCH-001, seen from above: point at a note, and its line lights up.
Balloon
A part's number. The same disc marks the part in the scene and its row in the bill of parts: click either, and both light up.
Dimension
A route's modelled latency: here, 4.2 ms from OrderRepository to Postgres.
Flow colour
What travels a pipe: a request, a write, a response or an error.
Arrowhead
Which end depends on the other in source code: here the payment provider adapter depends on PaymentGateway, the port the core declares.
Title block
Code, scale, revision, and the reference the machine was checked against.
General notes
- Latencies are modelled, in milliseconds. They are not measured.
- Every machine is checked against the reference in its title block, and never shows a behaviour the real system does not have.
- The engine steps at a fixed 1/60 s, so a run plays the same on every screen. MCH-001 places an order in 184.34 ms of simulated time.
- Vermillon marks errors and violations, and nothing else.
Build log
Built in public, one machine a week.
The engine, the drawings and the mistakes, posted as they happen.
| Date | Kind | Change |
|---|---|---|
| 12 OCT | SHIP | nightprint.dev is live: a static export on a VPS, republished on every push to main. |
| 12 OCT | PERF | The machine assembles in 1.5 s on first load. Materials compile while the stage is still hidden: no frame over 40 ms once it shows. |
| 12 OCT | UI | The home page runs MCH-001 as you scroll: each note plays its step on one drawing sheet that stays put. |
| 12 OCT | SEO | Every step of every scenario is now plain HTML. Crawlers never see the canvas. |
| 12 OCT | FIX | A what-if switch stalled 166 ms compiling materials. Every route is now mounted up front and fades in: 25 ms. |
| 12 OCT | OPEN | The repo is public on GitHub. Every commit passes lint, types and tests on its own. |
| 12 OCT | FIX | drei <Html> + Strict Mode: 9 React errors per page. Part numbers are now one DOM layer. |
| 12 OCT | UI | The design system went atomic: 25 components, none of them knows the engine. |