Exercise 1: Deployment Configuration for the Blog API — Possible Solution =========================================================================== .env.example (committed): # Runtime: the app connects through the pooler DATABASE_URL="postgresql://USER:PASSWORD@POOLER_HOST:6432/blog" # CLI: migrations connect directly to the database DIRECT_URL="postgresql://USER:PASSWORD@DB_HOST:5432/blog" PORT=3000 .gitignore: .env .env.* !.env.example node_modules/ dist/ generated/ prisma config file: import "dotenv/config"; import { defineConfig, env } from "prisma/config"; export default defineConfig({ schema: "prisma/schema.prisma", migrations: { path: "prisma/migrations", seed: "tsx prisma/seed.ts" }, datasource: { url: env("DIRECT_URL") }, }); lib/prisma.ts: import { PrismaClient } from "../generated/prisma/client"; import { PrismaPg } from "@prisma/adapter-pg"; const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL, max: Number(process.env.DB_POOL_MAX ?? 7), connectionTimeoutMillis: 5_000, }); export const prisma = new PrismaClient({ adapter }); package.json: "scripts": { "build": "prisma generate && tsc", "release": "prisma migrate deploy", "start": "node dist/server.js" } Which process uses which URL: - The running app (npm start) only uses DATABASE_URL, through the PrismaPg adapter, so all request traffic goes via the pooler. - The CLI (npm run release, db pull, migrate status) reads the config file and uses DIRECT_URL. Migrations need a direct connection, because poolers in transaction mode can break the session features migrations rely on. - Without a pooler, both variables can simply hold the same URL. WHY THIS WORKS AS AN ANSWER ------------------------------ Secrets never enter the repository, but the names of every required variable are documented. The generated client is treated as build output and recreated by the build script. Build, release and start are separate steps, so the platform can run migrations exactly once before starting the new version — and each step connects in the way that suits it.