Episode 31 deploys GraphQL to production: deployment platforms like Vercel, Railway, and Render, containerization with multi-stage Docker, Kubernetes deployment with manifests and autoscaling, serverless considerations like cold starts, environment and secrets management, and database migrations.

Code running on your laptop means nothing until it can be deployed to reliable production. Episode 31 covers GraphQL deployment from various angles: managed platforms, containerization, Kubernetes, serverless, and environment management.
We'll compare deployment options, build a multi-stage Docker image, put together Kubernetes manifests, consider serverless cold starts, manage secrets, and run database migrations safely.
To get started quickly, managed platforms remove the infrastructure burden:
A quick Railway deploy is just railway init && railway up.
Choose based on your needs: for full-stack Next.js, Vercel is very natural; for a standalone Node service with a database, Railway and Render simplify a lot.
Multi-stage builds produce small, safe images — one stage for building, one for running:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json bun.lock ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/package.json ./
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
EXPOSE 4000
CMD ["node", "dist/index.js"]docker build -t api-graphql .
docker run -p 4000:4000 --env-file .env.production api-graphqlFor development, Docker Compose runs the whole stack at once:
services:
api:
build: .
ports:
- "4000:4000"
environment:
DATABASE_URL: postgres://user:pass@db:5432/app
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: passFor enterprise scale, Kubernetes manages deployment, scaling, and recovery:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-graphql
spec:
replicas: 3
selector:
matchLabels:
app: api-graphql
template:
metadata:
labels:
app: api-graphql
spec:
containers:
- name: api
image: registry.example.com/api-graphql:1.2.3
ports:
- containerPort: 4000
livenessProbe:
httpGet: { path: /health/live, port: 4000 }
readinessProbe:
httpGet: { path: /health/ready, port: 4000 }The liveness and readiness health checks (episode 24) tell Kubernetes when a container is healthy enough to receive traffic.
Separate configuration from secrets:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-graphql
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-graphql
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70Serverless (Lambda, Cloud Functions) brings automatic scaling benefits, but has trade-offs:
Create per-environment configuration: development, staging, production. Store secrets in a safe place — AWS Secrets Manager, Vault, or the platform's built-in features — and never in the repository. Reference secrets via environment variables at runtime, not hardcoded in code.
Run migrations safely before new traffic is accepted:
npx prisma migrate deployFor zero-downtime deployments, separate the app deployment from the database migration: run the expand migration (adding columns) first, then release the new app, then migrate the contract. This pattern is explained further in episodes 32 and 35.
Key takeaways:
In the next episode, episode 32, you'll learn about CI/CD for GraphQL — setting up pipelines with GitHub Actions and GitLab CI, automated testing, schema checks to block breaking changes, deployment automation with blue-green and canary strategies, code quality gates, and release management with semantic versioning. Deploys will become a safe routine!