Go Back

Apr 17, 2025

Custom Servers and Advanced API Integrations

we’ll cover custom server setups, integrating with external APIs, and advanced API route patterns.

Custom Servers and Advanced API Integrations

1. When to Use a Custom Server

Next.js uses a built-in Node.js server for API routes and SSR. You might opt for a custom server when you need:

2. Creating a Custom Express Server

  1. Install Express:

    npm install express
  2. Create server.js at project root:

    const express = require('express');
    const next = require('next');
    const dev = process.env.NODE_ENV !== 'production';
    const app = next({ dev });
    const handle = app.getRequestHandler();
    
    app.prepare().then(() => {
      const server = express();
    
      // Custom middleware
      server.use((req, res, next) => {
        console.log(`${req.method} ${req.url}`);
        next();
      });
    
      // Legacy URL redirect
      server.get('/old-path', (req, res) => {
        return res.redirect(301, '/new-path');
      });
    
      // Let Next.js handle all other routes
      server.all('*', (req, res) => handle(req, res));
    
      const port = process.env.PORT || 3000;
      server.listen(port, () => {
        console.log(`> Ready on http://localhost:${port}`);
      });
    });
  3. Adjust package.json scripts:

    {
      "scripts": {
        "dev": "node server.js",
        "start": "NODE_ENV=production node server.js"
      }
    }

3. Fastify Integration for Performance

  1. Install Fastify:

    npm install fastify fastify-express
  2. Setup in server.js:

    const fastify = require('fastify')({ logger: true });
    const next = require('next');
    const app = next({ dev: process.env.NODE_ENV !== 'production' });
    const handle = app.getRequestHandler();
    
    app.prepare().then(() => {
      fastify.register(require('fastify-express')).after(() => {
        fastify.use((req, res, next) => {
          // Example: rate limiting header
          res.setHeader('X-Ratelimit-Limit', '100');
          next();
        });
    
        // Custom endpoint
        fastify.get('/api/status', async (request, reply) => {
          return { status: 'OK', time: new Date() };
        });
    
        fastify.all('/*', (req, res) => handle(req, res));
      });
    
      fastify.listen(3000, (err) => {
        if (err) throw err;
        console.log('> Server running on http://localhost:3000');
      });
    });

4. Advanced API Route Patterns

Beyond basic handlers, leverage dynamic route grouping:

5. Integrating External APIs

6. Webhooks and Background Tasks

With a custom server and advanced API patterns, you can tailor Next.js to resiliently handle complex routing, integrate diverse services, and support real-time workflows. In Next Article, we’ll explore analytics, A/B testing, and personalization.