ADR-052: Neon database naming — bank_ prefix with snake_case domain abbreviation¶
| Status | Superseded |
| Date | 2026-05-01 |
| Deciders | CTO, Head of Platform Engineering |
| Affects repos | bank-core, bank-kyc, bank-aml, bank-payments, bank-credit, bank-app, bank-platform |
| Superseded by | ADR-064 |
⚠️ This ADR has been superseded by ADR-064.
Status: Accepted — 2026-05-01
Context¶
ADR-024 established Neon serverless Postgres as the database hosting platform with one database per system domain. The database name table in ADR-024 used short unqualified names: core, kyc, fincrime, payments, credit, risk, platform. MOD-103 (the Neon bootstrap module, status: Built) provisioned the databases using a different naming pattern: bank_ prefix followed by a snake_case domain abbreviation: bank_core, bank_kyc, bank_aml, bank_payments, bank_credit, bank_app.
Two differences require explicit correction:
-
bank_prefix — all deployed database names carry the prefix, making it unambiguous that the database is part of the Totara Bank project and avoiding collisions with any other Neon project databases. -
fincrime→bank_aml— ADR-024 usedfincrimeas the SD03 database name. MOD-103 deployed it asbank_aml, consistent with the system domain identifier (SD03 AML Monitoring) and the repo name (bank-aml). Thefincrimename was an early working title;bank_amlis the correct name.
All other decisions in ADR-024 — Neon hosting, ap-southeast-2, single project, branch-per-env, PgBouncer for Lambda connections, one database per system domain — remain in full force and are not changed by this ADR.
Decision¶
Neon database names use the pattern bank_{domain} where {domain} is the snake_case abbreviation matching the system domain identifier:
| Database name | System domain | Repo |
|---|---|---|
bank_core |
SD01 Core Banking | bank-core |
bank_kyc |
SD02 KYC Platform | bank-kyc |
bank_aml |
SD03 AML Monitoring | bank-aml |
bank_payments |
SD04 Payments | bank-payments |
bank_credit |
SD05 Credit | bank-credit |
bank_app |
SD08 App | bank-app |
SD06 (bank-risk-platform) and SD07 (bank-platform) do not own Neon Postgres databases. SD06 uses Snowflake as its primary data store (ADR-046). SD07 (bank-platform) owns the Neon project provisioning (MOD-103) but does not have a dedicated application database — its operational state is stored in DynamoDB and S3 (ADR-025).
Postgres roles (per database)¶
Each database has three Postgres roles provisioned by MOD-103:
| Role pattern | Permissions | Used by |
|---|---|---|
{db}_app_user |
SELECT, INSERT, UPDATE, DELETE on all tables | Lambda application connections (pooled endpoint) |
{db}_migrate_user |
USAGE + CREATE on schema, ALL on tables | Flyway migrations in CI (direct endpoint) |
{db}_readonly |
SELECT on all tables | Read-only analytics consumers, DBA sessions |
Secrets Manager paths¶
Connection credentials are stored in Secrets Manager, not SSM:
bank-neon/{branch}/{database}/{role} — e.g. bank-neon/dev/bank_payments/bank_payments_app_user
SSM paths for connection hosts¶
| SSM path | Value | Used by |
|---|---|---|
/bank/{env}/neon/pooler-host |
PgBouncer endpoint | All Lambda application connections |
/bank/{env}/neon/direct-host |
Non-pooled endpoint | Flyway CI migrations only |
Cross-domain read access — published view contract¶
ADR-024 stated "Cross-domain queries are not permitted inline." This was overly restrictive and is not carried forward. The correct rule, consistent with AP-010 and AP-001 (KISS), is:
A domain may read from another domain's Neon database if and only if the owning domain has published an explicit view contract for that purpose.
A published view contract means:
- The owning module defines a named view in its own schema (e.g. accounts.balance_readable owned by MOD-003 in bank_core).
- The view is documented in the owning module's docs/design/MOD-NNN.md with its column contract and stability guarantee.
- The consuming module reads the view using the owning database's _readonly credential (bank-neon/{env}/bank_core/bank_core_readonly).
- The consuming module's pre-build confirmation lists the view by name and identifies which design doc documents it.
When to use each cross-domain read pattern (AP-001 KISS — simplest correct option wins):
| Pattern | Use when |
|---|---|
| Published DB view (direct read) | Synchronous on-path read where latency matters and no business logic gate is required. Example: balance check before payment execution, account status check before posting. |
| HTTP API call | The owning domain needs to apply logic, log the access, rate-limit, or enforce a security gate. Example: KYC tier lookup with entitlement check. |
| Local cache from CDC / events | Asynchronous or high-frequency read where the consuming domain tolerates eventual consistency and owns the staleness trade-off. Example: AML rule evaluation on posting history. |
What is never permitted: reading from another domain's base tables without a published view contract. Direct table access is an implicit dependency with no governance — the owning domain cannot refactor without breaking consumers it cannot discover.
Consequences¶
Positive:
- The bank_ prefix makes database identity unambiguous when a DBA or monitoring tool lists all Neon databases — no confusion with system databases or other tenants.
- bank_aml aligns the database name with the system domain (SD03), repo name (bank-aml), and EventBridge bus name (bank-aml) — consistent naming across all artefacts for the same domain.
- Removes the fincrime vs bank_aml discrepancy that was causing wiki drift and agent confusion.
Negative: - None. MOD-103 is already deployed with these names; no infrastructure change is required. The correction is documentation-only.
All ADRs
Compiled 2026-05-22 from source/entities/adrs/ADR-052.yaml