Skip to content

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:

  1. 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.

  2. fincrimebank_aml — ADR-024 used fincrime as the SD03 database name. MOD-103 deployed it as bank_aml, consistent with the system domain identifier (SD03 AML Monitoring) and the repo name (bank-aml). The fincrime name was an early working title; bank_aml is 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