Home/Blog/Backend Development
Backend DevelopmentBackend Development

Building Scalable Microservices with Node.js and Docker

Gaurav Bhatia|January 10, 2025|6 min read
API Gateway
G

Gaurav Bhatia

Software Architect

Node.jsDockerMicroservicesKubernetes

Microservices architecture has become the standard for building scalable, maintainable applications. In this guide, we'll walk through the key concepts and practical implementation of microservices using Node.js and Docker.

Why Microservices?

Monolithic applications work well for small teams, but as your application grows, a monolith becomes harder to maintain, deploy, and scale. Microservices solve this by breaking your application into small, independent services.

Key Benefits

  • Independent deployment — deploy each service separately without affecting others
  • Technology flexibility — use the right tool for each service
  • Fault isolation — a failure in one service doesn't bring down the entire system
  • Team autonomy — different teams can own different services

Building Your First Microservice

Let's build a simple product catalog service using Node.js and Express.

import express from 'express';
import { Pool } from 'pg';

const app = express();
const pool = new Pool({
  host: process.env.DB_HOST,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
});

app.get('/api/products', async (req, res) => {
  const { rows } = await pool.query('SELECT * FROM products');
  res.json(rows);
});

app.get('/api/products/:id', async (req, res) => {
  const { rows } = await pool.query(
    'SELECT * FROM products WHERE id = $1',
    [req.params.id]
  );
  if (rows.length === 0) return res.status(404).json({ error: 'Not found' });
  res.json(rows[0]);
});

app.listen(3001, () => console.log('Product service running on port 3001'));

Containerizing with Docker

Each microservice gets its own Docker container:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3001
CMD ["node", "dist/index.js"]

Orchestrating with Kubernetes

In production, Kubernetes manages your containers:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: product-service
  template:
    metadata:
      labels:
        app: product-service
    spec:
      containers:
      - name: product-service
        image: product-service:latest
        ports:
        - containerPort: 3001
        env:
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: db-secrets
              key: host

Best Practices

  • Service boundaries — design services around business capabilities
  • API versioning — version your APIs from day one
  • Health checks — every service should expose a /health endpoint
  • Centralized logging — use tools like ELK stack for log aggregation
  • Circuit breakers — handle failures gracefully with patterns like circuit breakers

Microservices aren't a silver bullet, but when applied correctly, they can dramatically improve your ability to scale both your application and your team.

Building scalable backend systems is a core part of custom software development. If you are planning a microservices architecture, talk to our team about the right approach for your project.

Build software that fits your business

Our custom software development guide covers planning, architecture, and choosing the right partner.

Get a custom software estimate