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
97%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Passed
No known issues
Translate the user's casual request into rigorous architecture: no one-line ALTER TABLE, no silent JSONB dump, no duplicate column.
Also triggered at the end of a mermaid-diagram-review when the user accepts the counter-proposal.
Invoke postgres-schema-introspection for the target table and its immediate neighbors (incoming + outgoing FKs). Specifically:
Search .specify/memory/schema-change-log.md for prior decisions about this entity or this attribute. If a prior decision exists, cite it. Don't re-litigate settled questions.
Walk all five options every time. Per option emit one sentence each for "could fit" and "doesn't fit" / "best because". End with "Recommended: Option X because…".
| # | Placement | Best when |
|---|---|---|
| A | New column on existing table | intrinsic, single value, queried often |
| B | JSONB key in metadata | optional, tenant-specific, never in joins; forbidden for price / stock / totals / FK / business-critical |
| C | EAV row | tenants define open-ended attributes |
| D | New related 1:1/1:N table | own lifecycle, multiple values, own permissions |
| E | Different entity | user's mental model misaligned (color → variant, expiration → lot, selling price → pricing rule) |
Produce this table — fill every row, write N/A explicitly when inapplicable. Rows marked (if relevant) may be omitted only when genuinely not applicable to the change:
| Concern | Detail |
|---|---|
| Incoming FKs | |
| Outgoing FKs | |
| Indexes touched | |
| RLS policies | |
| Outbox events | |
| Neo4j projection | |
| Tenant uniqueness | |
| Existing data shape | |
| Module ownership | |
| Compliance | |
| API surface | |
| Read patterns (if relevant) | |
| Write patterns (if relevant) |
Templates (CREATE INDEX CONCURRENTLY, never table rewrites):
-- P1 Expand: brief AccessExclusiveLock + ShareUpdateExclusiveLock
ALTER TABLE <t> ADD COLUMN <c> <type>;
CREATE INDEX CONCURRENTLY idx_<t>_<c> ON <t> (tenant_id, <c>);
-- P2 Backfill: row-level only; loop 5,000-row batches, sleep 100 ms
WITH batch AS (
SELECT id FROM <t> WHERE <c> IS NULL AND id > $last
ORDER BY id LIMIT 5000
)
UPDATE <t> SET <c> = <expr> WHERE id IN (SELECT id FROM batch);
-- P3 Cutover: in-place index → constraint upgrade, no rewrite
ALTER TABLE <t> ADD CONSTRAINT uq_<t>_<c>
UNIQUE USING INDEX idx_<t>_<c>;
-- P4 Contract: brief AccessExclusiveLock for revalidation
ALTER TABLE <t> ALTER COLUMN <c> SET NOT NULL;
ALTER TABLE <t> DROP COLUMN <old>;Rollback per phase: drop the new column/constraint/index. P4 dropped column needs a pre-P4 backup to restore.
One sentence per test. Specify tenant, RLS case, race condition concretely.
| Type | Verifies |
|---|---|
| Unit | pure logic on the new attribute |
| Integration | schema + queries against the new column |
| Tenant isolation | RLS positive + negative bypass attempts |
| Migration | apply + rollback against production-like data |
| Projection sync | outbox → Neo4j idempotency on replay |
| Concurrency | relevant race (e.g. two writers, lost-update) |
| Idempotency | duplicate-request handling under retry |
Name (or version-bump on existing), JSON-Schema payload delta, consumer impact (Neo4j worker? analytics? notifications?), replay idempotency story.
Draft (do not commit) the .specify/memory/schema-change-log.md entry in
that file's format. Show it to the user.
Any deviation from defaults (missing FK, no RLS, JSONB for a critical field,
destructive migration, cross-module reach) → invoke adr-drafting. Refuse
to produce final migration SQL until ADR is Proposed.
## Inventory of the affected area
## Five-placement analysis
## Recommended placement
## Blast radius
## Migration plan
## Test surface
## Eventing & projection delta
## Pending change-log entry
## ADR needed?A complete walk-through (desired_sell_price on pricing_rules — all nine
steps with full SQL, blast radius, tests, event delta, change-log entry)
lives in EXAMPLE-PRICING.md.
docs
skills
adr-drafting
commerce-database-architecture
graph-rag-boundary-review
mermaid-diagram-review
outbox-and-eventing-design
postgres-schema-introspection
schema-evolution-workflow