Try it free
Write faster with AI writing tools
WriterPilots gives you 10+ free AI writing tools — blog writer, email writer, paraphraser, grammar fixer and more. Free to try, no credit card needed.
Try Blog Writer → Paraphraser Summarizer Grammar Fixer
AI Writing Tools

Onboarding Path: Build and Deploy a Production-Ready Node.js Microservice

March 20, 2026 · 10 min read · 7 views

Onboarding Path: Build and Deploy a Production-Ready Node.js Microservice

One-line learning outcome: Ship a small, tested, containerized Node.js microservice with CI/CD and basic observability.

Estimated total time: 10–14 hours (split across modules — suitable for 1–3 day onboarding or spread over a week)

Prerequisites: Comfortable with JavaScript/TypeScript basics, Git, command line, and HTTP concepts. Familiarity with Docker is helpful but not required.


Path overview (module-by-module)

  1. Module 1 — Project Setup & Git Workflow (1.0 hr) — difficulty: Easy
  2. Module 2 — API Design & Implementation (Express + TypeScript) (3.0 hrs) — difficulty: Medium
  3. Module 3 — Tests & Contract Verification (1.5 hrs) — difficulty: Medium
  4. Module 4 — Containerization & Local Deployment (1.5 hrs) — difficulty: Medium
  5. Module 5 — CI/CD Pipeline (1.5 hrs) — difficulty: Medium
  6. Module 6 — Observability & Health (1.5 hrs) — difficulty: Medium
  7. Mini project & wrap-up (1.0 hr) — difficulty: Medium

Module 1 — Project Setup & Git Workflow

Objective: Create a repository scaffold with TypeScript, ESLint, prettier, and a reproducible dev script.

Narrative: A consistent project layout and Git workflow reduces onboarding overhead. We'll initialize a repo, add standard configs, and enforce linting & formatting on commits.

Hands-on lab (commands & expected outputs)

# create project

mkdir orders-service && cd orders-service

npm init -y

npm install -D typescript ts-node-dev eslint prettier husky lint-staged

npx tsc --init

# expected: tsconfig.json created

# add sample package.json scripts (dev, build, start)

# set up husky pre-commit to run lint-staged

Exercises

  1. Initialize the repo and add a src/index.ts that logs "service started". Run with npm run dev.
  2. Add ESLint + Prettier and configure lint-staged to format .ts files on commit.
  3. Optional harder: Add a GitHub Actions workflow that runs lint and TypeScript typecheck on pull request.

Mentor tip: Start with a minimal working setup; add rules only if they catch recurring issues.


Module 2 — API Design & Implementation (Express + TypeScript)

Objective: Implement a simple REST API for orders (CRUD), with request validation and typed controllers.

Narrative: Build a focused API endpoint set so the rest of the onboarding path has a concrete product to test, deploy, and observe.

Hands-on lab

# install server deps

npm install express express-validator cors

npm install -D @types/express

# src/app.ts

import express from 'express';
const app = express();
app.use(express.json());
let orders: { id: string; item: string }[] = [];
app.get('/orders', (req, res) => res.json(orders));
app.post('/orders', (req, res) => {
const id = String(Date.now());
const order = { id, item: req.body.item };
orders.push(order);
res.status(201).json(order);
});
export default app;
# src/server.ts
import app from './app';
app.listen(3000, () => console.log('Listening on 3000'));
# expected: server responds to GET /orders and POST /orders returning JSON

Exercises

  1. Add GET /orders/:id that returns 404 for missing ids.
  2. Validate POST /orders body to require a non-empty item. Return 400 on invalid input.
  3. Harder: Split controllers, services, and add a simple in-memory repository interface with dependency injection-friendly design.

Mentor tip: Emphasize small, testable functions over large handlers. Keep request validation near endpoints.


Module 3 — Tests & Contract Verification

Objective: Add unit and integration tests for handlers and API contracts.

Narrative: Tests protect refactors and serve as executable documentation for new hires.

Hands-on lab

# install test libs

npm install -D jest ts-jest supertest @types/jest

npx ts-jest config:init

# sample test (tests/orders.test.ts)

import request from 'supertest';
import app from '../src/app';
describe('orders API', () => {
it('creates and lists orders', async () => {
const res = await request(app).post('/orders').send({ item: 'coffee' });
expect(res.status).toBe(201);
const list = await request(app).get('/orders');
expect(list.body.length).toBeGreaterThan(0);
});
});
# run: npm test
# expected: tests pass

Exercises

  1. Write unit tests for validation logic returning 400 on invalid payloads.
  2. Mock the repository to test service logic in isolation.
  3. Harder: Add contract tests (Pact or schema tests) to validate the API surface.

Mentor tip: Show how failing tests provide focused debug info—encourage running a single test file during development.


Module 4 — Containerization & Local Deployment

Objective: Create a Dockerfile and run the service locally in a container.

Narrative: Containers make deployments consistent and local testing closer to production.

Hands-on lab

# Dockerfile (multi-stage)

FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json .
RUN npm ci
COPY . .
RUN npm run build
FROM node:18-alpine
WORKDIR /app
COPY --from=build /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
# Build and run
docker build -t orders-service:local .
docker run -p 3000:3000 orders-service:local
# expected: service responds on localhost:3000

Exercises

  1. Build and run the image locally and exercise endpoints with curl.
  2. Optimize the Dockerfile (slim base image, shrink layers) to reduce size.
  3. Harder: Add Docker Compose to run service with a mocked PostgreSQL container.

Mentor tip: Teach how to inspect running containers (docker ps, docker logs) and map ports for easy testing.


Module 5 — CI/CD Pipeline

Objective: Configure a CI pipeline to run lint, tests, build, and publish a container image to a registry.

Narrative: Continuous integration ensures commits are validated; continuous delivery reduces manual steps to deploy.

Hands-on lab

# GitHub Actions workflow (simplified)

name: CI

on: [push, pull_request]

jobs:

build:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v3

- uses: actions/setup-node@v3

with: { 'node-version': '18' }

- run: npm ci

- run: npm test

- run: npm run build

# optional: build and push Docker image

Exercises

  1. Add a workflow that runs on PRs and reports status checks.
  2. Extend the workflow to build and push an image to Docker Hub or GitHub Container Registry on main branch.
  3. Harder: Add a deployment job that triggers Cloud Run or a Kubernetes rollout using a service account.

Mentor tip: Start with a fast feedback loop (lint + tests) before adding slower steps like building images.


Module 6 — Observability & Health

Objective: Add health checks, basic structured logging, and a metrics endpoint.

Narrative: Observability at a minimal level helps on-call triage and gives new hires visibility into system health.

Hands-on lab

# add endpoints

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

app.get('/metrics', (req, res) => res.send('# HELP orders_created_total ...'));

# structured logging example with pino

npm install pino

import pino from 'pino';
const logger = pino();
logger.info({ route: '/orders' }, 'handling request');
# expected: logs emitted as JSON, health endpoint returns status

Exercises

  1. Add a /health endpoint returning 500 when a dependency check fails (simulate dependency).
  2. Integrate a basic Prometheus exporter library and expose simple counters for created orders.
  3. Harder: Configure Fluentd/Logstash local stack or use a SaaS (Datadog, LogDNA) to ship logs.

Mentor tip: Encourage readable logs for humans during dev and structured logs for production analysis.


Mini project & wrap-up

Deliverable: Complete a small PR that implements pagination on GET /orders, includes tests, and passes CI. Deploy a new image to staging and verify /health and /metrics.

Testable checkpoints

  • Repo initializes and npm scripts run (dev, build, test).
  • API responds to CRUD requests locally and in Docker.
  • CI pipeline runs on PR and passes.
  • Health & metrics endpoints are reachable in deployed environment.

Sample solution sketches (kept separate from exercises)

Sketch: Controller functions are thin; business logic lives in a service module with an in-memory repo implementing an interface. Tests stub the repo. Dockerfile uses multi-stage build. CI runs npm ci, npm test, npm run build, and optionally builds/pushes images with a short-lived token.

Assessment rubric

  • Automated checks (0–60): lint (10), tests (30), build (10), Docker image build (10).
  • Manual review (0–40): code organization & readability (10), API design & validation (10), observability (10), CI config & docs (10).

Alternative language implementations & trade-offs

  • Python (FastAPI): faster to write for some; has automatic docs; slower type safety unless using mypy.
  • Go (net/http, Gin): produces single binary, small container images, strong concurrency models; steeper learning curve for newcomers.

Recommended reading & tooling

  • 12 Factor App — best practices for cloud apps
  • Node.js Best Practices repo
  • Tools: Docker, GitHub Actions, Postman/HTTPie, pino, Prometheus/Alertmanager

Common stumbling blocks & debugging hints

  • TypeScript config excludes src by default — ensure tsconfig.json includes your files.
  • Docker context copying node_modules — prefer npm ci in build stage to produce consistent installs.
  • CI caching: cache node_modules between builds to speed up workflows.

Accessibility considerations

  • Document API responses with examples and status codes; include alt text for diagrams.
  • Ensure any demo UI (if added) uses semantic HTML and labels; provide captions for demo videos.

Finish by asking the new hire to pair with a mentor for a 1-hour code walkthrough and a checklist sign-off of the testable checkpoints.

Related Posts