How to Use a Throwaway Database Per Job in GitHub Actions
A service container is created fresh for each job and torn down when the job finishes, so every job already gets an isolated, throwaway database.
Each job that declares a services: database gets its own container instance. Matrix legs and parallel jobs never share state, which makes the database effectively disposable: create the schema, run, and let the runner discard it.
Steps
- Declare the database under the job
services:block. - Create the schema (migrate) at the start of the job.
- Do no cleanup; the container is destroyed when the job ends.
Workflow
.github/workflows/ci.yml
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3] # each shard gets its own fresh postgres
services:
postgres:
image: postgres:16
env: { POSTGRES_PASSWORD: postgres, POSTGRES_DB: app_test }
ports: [5432:5432]
options: --health-cmd "pg_isready -U postgres" --health-interval 10s --health-retries 5
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/app_test
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx prisma migrate deploy
- run: npm test -- --shard=${{ matrix.shard }}/3Gotchas
- Within a single job, all steps share the same database; use separate jobs or schemas to isolate parallel test workers.
- Because the container is discarded, never rely on data persisting to a later job; pass artifacts or re-seed instead.
Related guides
How to Parallelize Tests With Separate Schemas in GitHub ActionsRun test shards in parallel against one Postgres service in GitHub Actions by giving each worker its own sche…
How to Spin Up a Postgres Service for Tests in GitHub ActionsRun a real Postgres alongside your GitHub Actions tests using a service container with a pg_isready health ch…
How to Choose a Database Container vs a Service in GitHub ActionsDecide between a GitHub Actions service container and a manually run docker container for your CI database, w…