Back to Blog
Tutorial10 min read2026-06-29

How to Deploy a Fastify API to Production

Fastify is the high-throughput, low-overhead Node framework. Here's a production deploy with schema validation, structured logging, graceful shutdown, health checks, and a managed Postgres.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Why Fastify for production APIs

Fastify earns its name — it's one of the fastest Node.js web frameworks, with first-class JSON schema validation and a plugin architecture that scales to large apps without becoming spaghetti. It also has excellent built-in logging via Pino. Let's deploy a production-grade Fastify service.

Step 1: A Fastify app with schema validation

Schema validation isn't optional in production — it's your first line of defense and a free performance boost (Fastify compiles schemas to fast serializers).

// app.js
import Fastify from 'fastify';

export function build() {
  const app = Fastify({ logger: true });

  app.get('/health', async () => ({ status: 'ok' }));

  app.post('/users', {
    schema: {
      body: {
        type: 'object',
        required: ['name', 'email'],
        properties: { name: { type: 'string' }, email: { type: 'string', format: 'email' } },
      },
    },
  }, async (req) => createUser(req.body));

  return app;
}

Step 2: Bind to $PORT and listen on all interfaces

// server.js
import { build } from './app.js';
const app = build();
const port = Number(process.env.PORT) || 3000;
await app.listen({ port, host: '0.0.0.0' });

The host: '0.0.0.0' is essential inside containers — the default localhost won't accept external traffic.

Step 3: Graceful shutdown

Fastify's close() drains connections. Wire it to SIGTERM:

for (const sig of ['SIGTERM', 'SIGINT']) {
  process.on(sig, async () => {
    await app.close();
    process.exit(0);
  });
}

Step 4: Wire a managed Postgres

Use the official @fastify/postgres plugin, which manages a pool for you. It reads a connection string — DATABASE_URL, injected by PandaStack when you attach a managed PostgreSQL:

import fastifyPostgres from '@fastify/postgres';

app.register(fastifyPostgres, { connectionString: process.env.DATABASE_URL });

app.get('/users/:id', async (req) => {
  const { rows } = await app.pg.query('SELECT * FROM users WHERE id = $1', [req.params.id]);
  return rows[0];
});

Set the pool max below your tier's connection limit (50 free, 300 Pro, 1000 Premium).

Step 5: Structured logging

Fastify uses Pino, which emits JSON logs to stdout — perfect for the platform's live log view. In production, set the log level via env:

const app = Fastify({ logger: { level: process.env.LOG_LEVEL || 'info' } });

Keep logs as JSON in production (don't use pino-pretty), so they're parseable downstream.

Step 6: Containerize

FROM node:20.18-slim
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

Or skip the Dockerfile and let PandaStack's buildpacks auto-detect Node — both work.

Step 7: Deploy

Connect your repo and push:

git push origin main

The build runs in a rootless BuildKit K8s Job pod, the image ships to Artifact Registry, and Helm deploys it with live logs streaming. Add a custom domain for automatic SSL, set env vars in the dashboard, and you're live.

Step 8: Scaling and health

  • Fastify is single-threaded per process; add replicas for throughput rather than one giant instance.
  • Your /health endpoint lets the orchestrator manage rollout and readiness.
  • On the free tier the app scales to zero on spot nodes (cold start after idle); paid tiers stay warm.

Production checklist

  • [ ] JSON schema validation on all routes with bodies
  • [ ] Binds to $PORT on 0.0.0.0
  • [ ] Graceful app.close() on SIGTERM
  • [ ] @fastify/postgres pool sized to tier limits
  • [ ] JSON (non-pretty) Pino logs in production
  • [ ] /health endpoint

References

  • [Fastify documentation](https://fastify.dev/docs/latest/)
  • [@fastify/postgres](https://github.com/fastify/fastify-postgres)
  • [Pino logger](https://getpino.io/)
  • [Fastify — validation and serialization](https://fastify.dev/docs/latest/Reference/Validation-and-Serialization/)

---

Fastify gives you speed, validation, and great logging with very little boilerplate. Deploy one to PandaStack's [free tier](https://dashboard.pandastack.io), attach a managed Postgres, and let DATABASE_URL wire itself in — 5 web services and a database at $0/mo.

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also