Skip to content
Latchkey

CI/CD for a NestJS + Prisma + Postgres App with GitHub Actions

Lint, migrate Prisma, run e2e tests on Postgres, build, and ship NestJS.

NestJS with Prisma and Postgres is a common Node backend stack. This recipe applies Prisma migrations to a Postgres service container, runs unit and e2e tests, then builds and containerizes the app.

What the pipeline does

  • install deps with npm ci
  • apply migrations with prisma migrate deploy
  • lint with eslint
  • run unit and e2e tests
  • build with nest build and containerize

The workflow

The Postgres service backs Prisma during migrations and e2e tests. DATABASE_URL points at the service; nest build emits dist for the container.

.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:16
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: nest
        ports: ["5432:5432"]
        options: >-
          --health-cmd "pg_isready" --health-interval 10s
          --health-timeout 5s --health-retries 5
    env:
      DATABASE_URL: postgresql://postgres:postgres@localhost:5432/nest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npx prisma migrate deploy
      - run: npm run lint
      - run: npm test
      - run: npm run test:e2e
      - run: npm run build

Caching and speed

cache: npm restores installs and the Prisma engines cache. e2e suites that touch a real Postgres take time, so running on cheaper managed runners such as Latchkey $0.0025/min at 2 vCPU against $0.006 GitHub-hosted keeps PRs fast, and auto-retry covers a flaky database start or registry blip.

Deploying

Build a Docker image from dist and push it to your registry, then deploy to ECS, Kubernetes, or a Node host. Run prisma migrate deploy against production as a pre-release step before routing traffic.

Making this reliable in CI

  • Pin every tool version. An unpinned toolchain turns a runner image update into a build break on unchanged code.
  • Cache what is expensive to produce, and key the cache to the tool version so a restore across a version boundary cannot poison the build.
  • Assert on the produced artifact rather than on the command succeeding.
  • Set an explicit timeout so a hung step fails fast instead of consuming the whole job budget.

Key takeaways

  • Back Prisma with a Postgres service so migrations and e2e tests are real.
  • Run prisma migrate deploy before tests in CI and before traffic in prod.
  • nest build emits dist that you containerize for deploy.

Frequently asked questions

CI/CD for a NestJS + Prisma + Postgres App with GitHub Actions?
NestJS with Prisma and Postgres is a common Node backend stack. This recipe applies Prisma migrations to a Postgres service container, runs unit and e2e tests, then builds and containerizes the app.
The workflow?
The Postgres service backs Prisma during migrations and e2e tests. DATABASE_URL points at the service; nest build emits dist for the container.
Caching and speed?
cache: npm restores installs and the Prisma engines cache. e2e suites that touch a real Postgres take time, so running on cheaper managed runners such as Latchkey $0.0025/min at 2 vCPU against $0.006 GitHub-hosted keeps PRs fast, and auto-retry covers a flaky database start or registry blip.
Deploying?
Build a Docker image from dist and push it to your registry, then deploy to ECS, Kubernetes, or a Node host. Run prisma migrate deploy against production as a pre-release step before routing traffic.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card