Appearance
Schema overview + ERD
The entire data layer is Supabase (Postgres). The DDL across these pages is a reference starting point, not final migrations — adjust types/indexes during implementation, but keep the keys, constraints, and the idempotency / double-entry guarantees.
The two threads
Everything is keyed on two ids:
correlation_id— the one-ID-per-transaction thread that ties a rail notification →transactions→journals→ledger_entries→ settlement.process_id— the transaction / settlement id used for idempotency together withcategory(unique (process_id, category)).
Two sources of truth, never confused
journals = source of truth for money (only successful, captured financial events). transactions = source of truth for attempts/analytics (every outcome, incl. declined / failed / pending / expired). Joined on correlation_id. See Ingestion & analytics.
Entity-relationship diagram
Table map
| Group | Tables | Page |
|---|---|---|
| Ledger core | accounts, journals, ledger_entries | Ledger tables |
| Config | fee_rules, finances_config, balance_snapshots | Config tables |
| Ingestion & analytics | transaction_events, transactions | Ingestion & analytics |
| Operator / registry | merchants, rails, webhooks, webhook_deliveries, operators, audit_log | Operator tables |
| Settlement | settlements, settlement_runs, settlement_merchant_config | Settlement reports · orchestration |
| Checkout | checkout_config | Hosted Checkout |
Idempotency is enforced structurally — see the idempotency model.