Billing guide

Local postgresql

Local PostgreSQL with Docker Compose

The Billing Rails Compose file starts an isolated PostgreSQL 17 service for local development and tests. It does not share the root repository’s boo-mcp-test-db container.

Defaults:

The password is a development default, not a production credential. Choose any password override before the volume is initialized for the first time. The host port may be changed on any start. For example:

BILLING_POSTGRES_PORT=55441 BILLING_POSTGRES_PASSWORD='another-local-password' \
  docker compose -f docker-compose.yml up -d --wait postgres

PostgreSQL stores the role password in the named volume. Merely changing BILLING_POSTGRES_PASSWORD on a later start does not rotate that password and makes the healthcheck use credentials that PostgreSQL does not recognize. To rotate it without deleting data:

  1. Run docker compose -f docker-compose.yml exec postgres psql -U billing -d postgres.

  2. At the psql prompt, run \password billing, enter the new value twice, then run \q.

  3. Start Compose with the same new BILLING_POSTGRES_PASSWORD. Compose may replace the service container, but it keeps billing-rails-local_postgres_data.

Do not put the new password in SQL, shell history, source files, or documentation.

Start and initialize

From billing_rails:

docker compose -f docker-compose.yml up -d --wait postgres

On first initialization, the container creates both databases and loads the checked-in db/structure.sql into each. Initialization scripts run automatically only when the named volume is new. It also records the Rails environment (development or test) and the structure fingerprint so Rails’ protected-environment and schema checks remain active. The script is safe to invoke manually because it leaves a nonempty public schema unchanged and does not claim that an existing schema matches the current structure file.

If an older billing-rails-local_postgres_data volume lacks billing_rails_test, or contains an empty development or test database, recover it without deleting the volume:

docker compose -f docker-compose.yml exec -T postgres \
  /docker-entrypoint-initdb.d/10-create-test-database.sh

This creates the missing test database, loads db/structure.sql only into an empty public schema, and restores the known Rails environment marker. It does not migrate or overwrite a populated database. For later schema changes, use the repository’s migration workflow and PostgreSQL schema guide.

Check service state and readiness without changing it:

docker compose -f docker-compose.yml ps
docker compose -f docker-compose.yml exec postgres \
  pg_isready -U billing -d billing_rails_development

Run the application and tests

bin/test-local defaults to this persistent service: loopback port 55440, user billing, password billing-local-only. The application server still needs the explicit environment below. If you chose a different local password, export it for tests too. A legacy test instance can be selected with explicit BILLING_DB_PORT, BILLING_DB_USER and BILLING_DB_PASSWORD overrides; it must have the current schema before running tests.

export BILLING_DB_HOST=127.0.0.1
export BILLING_DB_PORT=55440
export BILLING_DB_USER=billing
export BILLING_DB_PASSWORD=billing-local-only

bin/rails server
sh bin/test-local test/services/billing/pricing_test.rb

Use the host port and password supplied to Compose when overriding either default.

Stop without deleting data

docker compose -f docker-compose.yml stop

docker compose -f docker-compose.yml down removes the service container and network while keeping the named volume. Deleting billing-rails-local_postgres_data permanently deletes both local Billing Rails databases and is intentionally outside this routine setup workflow.