Skip to main content

PostgreSQL & Redis

PostgreSQL 17 is the primary state store. Separate Redis 7 authorities back customer sessions and Celery task transport. All three are mandatory for every secure runtime; the local stack ships two isolated Redis containers.

PostgreSQL 17

PostgreSQL stores customers, provider bindings, operations, idempotency records, outbox events, beneficiaries, estimates, mandates, cards, and audit events. Live mode requires PostgreSQL; SQLite remains limited to tests and fake development. Set NEOBANK_DATABASE_URL with the postgresql+psycopg scheme:

Run migrations

Alembic owns schema state. On Compose, a one-shot migrate service runs before the API starts:
On Kubernetes, a pre-install,pre-upgrade hook Job runs alembic upgrade head before the workloads roll (see Kubernetes). The application containers themselves never run migrations — the API and worker instead refuse to start when the database’s migration revision is stale.

Redis 7

The API uses NEOBANK_REDIS_URL for sessions and rate limits. The worker and scheduler use NEOBANK_TASK_QUEUE_URL for the Celery broker and result backend. The task workloads never receive the session Redis URL. The local stack runs both Redis instances with append-only-file persistence (--appendonly yes). Set NEOBANK_REDIS_URL:
Use separate instances or Redis ACL users that cannot read or write each other’s keys. Different database numbers on the same unrestricted Redis identity do not prevent a compromised scheduler from forging customer sessions.

Kubernetes namespace assumption

The Helm NetworkPolicy restricts each workload to its required namespace and port. The defaults assume in-cluster services on standard ports: Override networkPolicy.databaseNamespace, networkPolicy.sessionRedisNamespace, networkPolicy.taskRedisNamespace, or networkPolicy.vaultNamespace if the in-cluster topology differs. Managed external services require additional caller-supplied policies restricted to their exact address ranges. See Kubernetes.

Concurrency test database

The Postgres concurrency test suite runs against a dedicated database named neobank_test — the tests refuse any other database name. Set NEOBANK_TEST_DATABASE_URL and run:
The target fails fast if NEOBANK_TEST_DATABASE_URL is unset, then runs the tests marked integration. Create the neobank_test database in your Postgres instance before invoking it.