πŸš€ Deploying a Node.js Product API on Kubernetes with MongoDB



This content originally appeared on DEV Community and was authored by Manthan Ankolekar

Modern apps need to scale effortlessly while staying resilient. Kubernetes (K8s) has become the go-to platform for orchestrating containerized apps, ensuring scalability, self-healing, and portability.

In this guide, we’ll build and deploy a Node.js Product API with MongoDB on Kubernetes. You’ll learn how to containerize the app, define Kubernetes manifests, and enable auto-scaling.

🧩 What We’re Building

  • A Node.js + Express REST API with CRUD for products
  • MongoDB database with Mongoose ODM
  • Dockerized application
  • Kubernetes resources: Deployment, Service, Ingress, Secrets
  • Horizontal Pod Autoscaler (HPA) for auto-scaling
  • Ingress Controller for external access

Here’s the flow:

Client β†’ Ingress β†’ Service β†’ Pod(s) running Node.js API β†’ MongoDB
                   ↑
                HPA scales pods dynamically

📁 Project Structure

nodejs-kubernates/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ config/db.js          # MongoDB connection
β”‚   β”œβ”€β”€ controllers/          # Business logic
β”‚   β”œβ”€β”€ models/product.model.js
β”‚   β”œβ”€β”€ routes/product.routes.js
β”‚   β”œβ”€β”€ middlewares/          # Error handling, validation
β”‚   └── server.js             # Express entry point
β”œβ”€β”€ k8s/
β”‚   β”œβ”€β”€ deployment.yaml       # App Deployment
β”‚   β”œβ”€β”€ service.yaml          # ClusterIP Service
β”‚   β”œβ”€β”€ ingress.yaml          # Ingress (exposes API)
β”‚   β”œβ”€β”€ secret.yaml           # MongoDB credentials
β”‚   └── hpa.yaml              # Auto-scaling config
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ docker-compose.yml        # Local dev
└── package.json

📝 Step 1 β€” Build the Node.js Product API

The Product schema:

const productSchema = new mongoose.Schema({
  name: { type: String, required: true, trim: true },
  description: { type: String, default: '' },
  price: { type: Number, required: true, min: 0 },
  inStock: { type: Boolean, default: true }
}, { timestamps: true });

CRUD endpoints are exposed at /api/products.
Example request:

curl -X POST http://localhost:5000/api/products \
  -H "Content-Type: application/json" \
  -d '{"name":"Laptop","price":999.99,"inStock":true}'

📦 Step 2 β€” Containerize with Docker

Dockerfile:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["node", "src/server.js"]

Build and run locally:

docker build -t nodejs-kubernates .
docker run -p 5000:5000 \
  -e MONGO_URI=mongodb://host.docker.internal:27017/product-api \
  nodejs-kubernates

☸ Step 3 β€” Kubernetes Manifests

Deployment (deployment.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: product-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: product-api
  template:
    metadata:
      labels:
        app: product-api
    spec:
      containers:
        - name: product-api
          image: <REGISTRY>/nodejs-kubernates:latest
          ports:
            - containerPort: 5000
          env:
            - name: MONGO_URI
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: MONGO_URI

Service (service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: product-api-svc
spec:
  selector:
    app: product-api
  ports:
    - port: 80
      targetPort: 5000
  type: ClusterIP

Ingress (ingress.yaml)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: product-api-ingress
  annotations:
    kubernetes.io/ingress.class: alb
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: product-api-svc
                port:
                  number: 80

Secrets (secret.yaml)

apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
data:
  MONGO_URI: <base64-encoded-uri>

Encode your Mongo URI:

echo -n "mongodb://user:pass@host:27017/product-api" | base64

HPA (hpa.yaml)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: product-api-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: product-api
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

🚀 Step 4 β€” Deploy to Kubernetes

  1. Push your Docker image to a registry (DockerHub, AWS ECR, GCP Artifact Registry).
  2. Apply manifests:
kubectl apply -f k8s/
  1. Check status:
kubectl get pods
kubectl get svc
kubectl get ingress
  1. Access the API:
curl http://<INGRESS-HOST>/api/products

📊 Step 5 β€” Scaling & Monitoring

  • HPA automatically scales pods between 2–10 based on CPU/memory usage.
  • Liveness & Readiness probes ensure only healthy pods receive traffic.
  • Logging & Monitoring: Add Prometheus + Grafana, or pipe logs to ELK/CloudWatch.

🔒 Production Considerations

  • Use managed MongoDB (Atlas, DocumentDB).
  • Enable TLS/HTTPS for ingress (cert-manager + Let’s Encrypt).
  • Store secrets in Kubernetes Secrets or external vaults.
  • Define resource requests & limits for predictable scaling.
  • Add a CI/CD pipeline to build, push, and deploy automatically.

🎯 Conclusion

You’ve just deployed a Node.js Product API on Kubernetes with:
✅ Dockerized app
✅ Kubernetes Deployment, Service & Ingress
✅ Secrets for sensitive data
✅ Auto-scaling with HPA

This setup provides a strong foundation for microservices in production.

🔗 GitHub Repository: manthanank/nodejs-kubernates
🧑‍💻 Author: Manthan Ankolekar


This content originally appeared on DEV Community and was authored by Manthan Ankolekar