Skip to content

Step 7 — A database

About 30 minutes. Branch: step-7.

The one new idea: you declare a need, and the platform provisions it.

Two lines

appmecca.yaml @ step-7
database:
  enabled: true

That is your entire side of the arrangement. On the next deploy the platform creates a Postgres database, creates a user scoped to it, and injects into every container of this app:

DATABASE_URL     the whole connection string
DB_HOST  DB_PORT  DB_NAME  DB_USER  DB_PASSWORD

You never choose a password, never see one, and never put one in the repository.

The connection budget

database:
  enabled: true
  max_connections: 5

The database is shared. The platform adds up what every app has declared and refuses a deploy that would overcommit it.

That makes this number load-bearing in an unusual way: it is not a limit imposed on you, it is your declaration of intent, and it is what stops one app's bad afternoon from becoming everyone's. Declare what you will actually hold.

Migrations run in the start command

There is no "run this once before the deploy" hook. Your container has to be able to bring itself up from nothing — so backend/entrypoint.sh waits for the database, migrates, and then becomes the server:

echo "waiting for the database…"
# … bounded retry …
echo "running migrations…"
python -m app.migrate

echo "starting uvicorn…"
exec uvicorn app.main:app --host 0.0.0.0 --port 8000

Three properties make that safe, and all three are worth copying:

  • Bounded wait. The database may still be coming up. Retry a limited number of times, then fail loudly. Never loop forever — a container that hangs looks identical to one that is slow.
  • Idempotent. Every replica runs this, and every redeploy runs it again. app/migrate.py records what it has applied and takes an advisory lock, so two replicas starting together take turns instead of colliding.
  • exec at the end. It replaces the shell with uvicorn, so signals reach the server directly and the platform can stop it cleanly.

Deploy and look

mecca app redeploy tally -b tutorial
mecca logs tally --type container -b tutorial

Now --type container has something in it — your app's own output:

database is up
applying 001_items.sql
migrations up to date (1 applied)
starting uvicorn…

Redeploy and watch it say 0 applied. That is idempotency, demonstrated.

mecca debug

mecca debug tally -b tutorial

One dump: configured variables, recent errors, per-service health, resolved URLs, and — the useful part — which environment variables the container actually received. When something you configured is not happening, this is where an absence becomes visible.

If it didn't work

Symptom Try Usually
DATABASE_URL is not set mecca debug tally database.enabled missing or misspelled — see step 4
Deploy fails after 60s mecca logs tally --type container The wait loop gave up; read what it printed
A migration failed same It ran and the SQL is wrong. The transaction rolled back; fix and redeploy
Deploy refused before it started mecca queue diagnose <id> The connection budget. Lower max_connections

Reset to the reference

git fetch upstream && git reset --hard upstream/step-7 && git push --force origin tutorial

Next: Step 8 — Environment variables