CtrlK
BlogDocsLog inGet started
Tessl Logo

g14wxz/commerce-database-architect

Database architecture skills, docs, and rules for high-demand multi-tenant commerce platforms (PostgreSQL source of truth, Neo4j as derived GraphRAG projection, transactional outbox, RLS-based tenant isolation). Includes live schema introspection workflow via Postgres MCP.

97

Quality

97%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

event-catalog.mddocs/

Domain Event Catalog

This is the source of truth for every domain event the platform emits. Adding a new event or bumping an event version requires a PR review against this file. Consumers (Neo4j projection workers, analytics, notifications) read this catalog for schema validation.


Conventions

  • Naming: <Aggregate><PastTenseVerb>OrderConfirmed, never ConfirmOrder (that's a command, not an event).
  • Versioning: event_version SMALLINT starting at 1. Bump on any breaking payload change. Old version is published in parallel for one deploy cycle, then retired.
  • Owner: exactly one module emits each event.
  • Replay safety: every event must be safe to redeliver. Consumers track last_processed_id per event type in consumer_offsets.

Standard envelope

Every event payload is wrapped in this envelope:

{
  "event_id": "01J9...",
  "event_type": "OrderConfirmed",
  "event_version": 1,
  "tenant_id": 42,
  "aggregate_type": "Order",
  "aggregate_id": 9182,
  "aggregate_public_id": "ord_01J9...",
  "occurred_at": "2026-05-03T14:22:11.123Z",
  "trace_id": "01J9...",
  "actor": { "type": "user", "id": 123 },
  "payload": { /* event-specific shape below */ }
}

Tenancy

TenantCreated (v1) — owner: tenancy

{
  "name": "Acme Bakery",
  "slug": "acme-bakery",
  "plan": "growth",
  "primary_contact_email": "owner@acme.example"
}

Triggers projection: Neo4j Tenant node, analytics dim_tenant row.


Catalog

ProductCreated (v1) — owner: catalog

{
  "sku": "BAG-001",
  "name": "Sourdough Loaf 800g",
  "brand_id": 18,
  "category_ids": [3, 12]
}

ProductUpdated (v1) — owner: catalog

Diff-style. Only changed fields are present.

{
  "changed": { "name": "Sourdough Loaf 1000g" },
  "previous": { "name": "Sourdough Loaf 800g" }
}

ProductDeleted (v1) — owner: catalog

Soft delete event. Hard delete events are reserved for compliance flows.

{ "deleted_at": "2026-05-03T14:22:11Z", "reason": "discontinued" }

VariantCreated (v1) — owner: catalog

VariantUpdated (v1) — owner: catalog

VariantDeleted (v1) — owner: catalog


Pricing

PriceChanged (v1) — owner: pricing

{
  "product_id": 9182,
  "variant_id": null,
  "price_type": "list",
  "currency": "USD",
  "previous_amount": "12.50",
  "new_amount": "13.00",
  "effective_at": "2026-05-04T00:00:00Z"
}

price_type discriminator: list, compare_at, wholesale, effective.


Inventory

InventoryReserved (v1) — owner: inventory

{
  "reservation_id": 88112,
  "product_id": 9182,
  "variant_id": 33,
  "warehouse_id": 4,
  "quantity": 2,
  "expires_at": "2026-05-03T14:32:11Z",
  "reason": { "type": "order", "order_id": 71001 }
}

InventoryMovementCreated (v1) — owner: inventory

Every balance change emits this. Append-only.

{
  "movement_id": 5412091,
  "product_id": 9182,
  "variant_id": 33,
  "warehouse_id": 4,
  "lot_id": 901,
  "quantity_delta": -2,
  "balance_after": 18,
  "reason": { "type": "order_confirmed", "order_id": 71001 }
}

Ordering

OrderCreated (v1) — owner: ordering

{
  "customer_id": 4501,
  "channel": "web",
  "currency": "USD",
  "subtotal": "26.00",
  "tax": "2.34",
  "total": "28.34",
  "items": [
    { "product_id": 9182, "variant_id": 33, "quantity": 2, "unit_price": "13.00" }
  ]
}

OrderConfirmed (v1) — owner: ordering

OrderCancelled (v1) — owner: ordering

OrderFulfilled (v1) — owner: ordering


Payments

PaymentSucceeded (v1) — owner: payments

{
  "order_id": 71001,
  "provider": "stripe",
  "provider_payment_id": "pi_3ABC...",
  "amount": "28.34",
  "currency": "USD",
  "method": "card"
}

PaymentFailed (v1) — owner: payments

RefundCreated (v1) — owner: payments


Adding a new event

  1. Open a PR adding the event spec to this file.
  2. Confirm exactly one module emits it.
  3. Define the JSON Schema for the payload (link or inline).
  4. List anticipated consumers.
  5. Specify replay safety: idempotent? safe to re-emit?
  6. Bump the consumer's offset-tracking schema if needed.
  7. Add the projection-worker code in the same PR if Neo4j is affected.
  8. Update current-schema-state.md if the change adds an outbox-emitting table.

docs

event-catalog.md

index.md

tile.json