Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Running on a server

On your computer the server starts with npm run dev and runs while the terminal is open. On a production server the API must be reachable from outside, restart itself after a crash and shut down cleanly during an update. Three settings take care of this.

The 0.0.0.0 address

By default listen accepts connections only from the same computer (localhost). On a server and in a Docker container you need to listen on all network interfaces — the address 0.0.0.0:

// src/server.js
import { buildApp } from './app.js';
 
const app = buildApp({ logger: true, trustProxy: true });
 
await app.ready();
await app.listen({ port: app.config.PORT, host: '0.0.0.0' });

Now the API answers at the server's IP address. trustProxy: true is needed when nginx sits in front of Fastify: then request.ip holds the client address, not the proxy's.

Graceful shutdown

During an update the process manager sends the SIGTERM signal. If the process exits immediately, requests being handled at that moment are cut off. Add to the end of src/server.js:

// src/server.js
for (const signal of ['SIGINT', 'SIGTERM']) {
  process.on(signal, async () => {
    app.log.info({ signal }, 'Stopping the server');
    await app.close();
    process.exit(0);
  });
}

app.close() stops accepting new connections, waits for current requests and runs the onClose hooks — the database is closed there. Press Ctrl+C in the terminal: the log shows "Stopping the server", and the process exits without errors.

The PM2 process manager

PM2 watches the process: it restarts it after a crash and after a server reboot.

npm install --global pm2
pm2 start npm --name blog-api -- start
pm2 save
pm2 startup

pm2 start runs the npm start script from package.json (with the --env-file flag), pm2 save remembers the process list, and pm2 startup prints a command that turns on autostart after a reboot.

CommandWhat it does
pm2 listProcesses and their state
pm2 logs blog-apiApplication logs
pm2 restart blog-apiRestart after a code update
pm2 stop blog-apiStop

Before launch

  • create .env with the real secrets on the server;
  • install only production dependencies: npm ci --omit=dev;
  • remove pino-pretty from the logger settings;
  • put nginx with HTTPS in front of Fastify.

Common mistake

The server is running, curl http://localhost:3000 works on the server itself, but the API is unreachable from outside. Almost always the cause is listen without host: Fastify listens only on 127.0.0.1. Set host: '0.0.0.0' or pass the address through an environment variable.

Thanks for reading!

Donate to the site — we work hard for you.