Skip to content

Anujsup/elastic-apm-express-boilerplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Express.js + Elastic APM Boilerplate

One-command observability stack for Node.js — Elasticsearch · Kibana · APM Server · Docker Compose

License: MIT Node.js Express Docker Elastic Stack Stars

Stop spending hours wiring up APM from scratch. This boilerplate gives you a fully configured Express.js application with Elastic APM instrumentation, a production-grade 3-node Elasticsearch cluster, Kibana dashboards, and APM Server — all running locally with a single docker-compose up.

Clone it, run two commands, and you'll have live traces, error tracking, and performance metrics in Kibana within minutes.


Table of Contents


What is this?

This is a ready-to-use starter template that integrates:

  • An Express.js 5 application pre-wired with the elastic-apm-node agent
  • A complete Elastic Stack (Elasticsearch + Kibana + APM Server) running via Docker Compose
  • 5 demo endpoints that exercise different APM monitoring scenarios (errors, async ops, CPU load, DB spans)

You get the full observability pipeline — from your Node.js app all the way to Kibana dashboards — with zero manual configuration.


Who is it for?

You are... This repo helps you...
A Node.js developer new to APM Learn Elastic APM without fighting setup
A backend engineer evaluating observability tools Get a working reference implementation fast
A DevOps / Platform engineer Use as a base for onboarding teams to Elastic observability
A student / learner Understand how distributed tracing and APM work end-to-end

What's Included

Express.js Application with APM Integration

  • Pre-configured Express.js server with elastic-apm-node agent
  • 5 sample endpoints for testing different monitoring scenarios
  • Centralized error handling with automatic APM error capture
  • Request logging middleware and randomized latency for realistic traces

Complete Elastic Stack (Docker Compose)

  • Elasticsearch: 3-node cluster for high-availability data storage
  • Kibana: Web UI for APM dashboards and data visualization
  • APM Server: Receives and processes performance data from your app
  • Setup service: Automates certificate generation and initial passwords

Quick Start

Prerequisites

  • Docker & Docker Compose installed
  • Node.js 16+ (for running the Express app locally)
  • 4 GB+ RAM available for the Elasticsearch cluster

1. Clone and install

git clone https://github.com/Anujsup/elastic-apm-express-boilerplate.git
cd elastic-apm-express-boilerplate
npm install

2. Start the Elastic Stack

# Copy environment file
cp .env.example .env

# Start Elasticsearch, Kibana, and APM Server
docker-compose up -d

# Wait 2–3 minutes for services to be healthy
docker-compose ps

3. Start the Express application

node index.js

4. Access the services

Service URL
Express App http://localhost:3000
Kibana (APM UI) http://localhost:5601
Elasticsearch http://localhost:9200
APM Server http://localhost:8200

Auto-Setup: APM integration is pre-configured. No manual setup in Kibana — just start the Express app and your express-apm-demo service appears automatically within ~1 minute.


Test Endpoints

Hit these endpoints to generate APM data across different monitoring scenarios:

Endpoint Scenario What APM captures
GET / Basic request Response time, throughput
GET /error Error generation Error tracking, stack traces
GET /async Async/Promise flow Promise handling, async spans
GET /cpu-intensive CPU-bound work CPU usage, slow transaction detection
GET /db-simulation Database operation Custom DB span, query latency
# Quick smoke test — hit all endpoints
curl http://localhost:3000/
curl http://localhost:3000/async
curl http://localhost:3000/cpu-intensive
curl http://localhost:3000/db-simulation
curl http://localhost:3000/error   # intentional error

Architecture Overview

graph TB
    subgraph "External Access"
        USER[("User")]
        BROWSER[("Browser")]
    end

    subgraph "Express.js Application"
        APP["Express App\nindex.js\nPort: 3000"]
        APM_AGENT["APM Agent\nelastic-apm-node"]
    end

    subgraph "Elastic Stack"
        APM_SERVER["APM Server\nPort: 8200"]
        
        subgraph "Elasticsearch Cluster"
            ES01["ES01\nMaster Node\nPort: 9200"]
            ES02["ES02\nData Node"]
            ES03["ES03\nData Node"]
        end
        
        KIBANA["Kibana\nPort: 5601"]
        SETUP["Setup Service\nCertificates & Passwords"]
    end

    subgraph "Data Storage"
        CERTS[("Certificates\nVolume")]
        DATA1[("ES01 Data\nVolume")]
        DATA2[("ES02 Data\nVolume")]
        DATA3[("ES03 Data\nVolume")]
        KIBANA_DATA[("Kibana Data\nVolume")]
    end

    USER --> APP
    BROWSER --> KIBANA
    APP --> APM_AGENT
    APM_AGENT --> APM_SERVER
    APM_SERVER --> ES01
    KIBANA --> ES01
    SETUP --> ES01
    SETUP --> CERTS
    ES01 <--> ES02
    ES02 <--> ES03
    ES03 <--> ES01
    ES01 --> DATA1
    ES02 --> DATA2
    ES03 --> DATA3
    KIBANA --> KIBANA_DATA
    ES01 --> CERTS
    ES02 --> CERTS
    ES03 --> CERTS
Loading

How it works

  1. Express App instruments every request via the elastic-apm-node agent
  2. APM Agent forwards traces, errors, and metrics to APM Server (port 8200)
  3. APM Server processes and stores the data in the Elasticsearch cluster
  4. Kibana reads from Elasticsearch and renders the APM dashboards
  5. Setup service handles TLS certificate generation on first boot
  6. Docker volumes persist all data across container restarts

Why a 3-Node Cluster?

A single Elasticsearch node works fine for basic development. This boilerplate uses 3 nodes to give you a production-realistic environment:

Benefit Description
High Availability Cluster keeps running if one node fails
Fault Tolerance Data is replicated across nodes — no data loss
Load Distribution Query and indexing load is spread across nodes
Realistic Testing Experience actual cluster behavior: master election, shard allocation

Node roles

  • ES01 — Master-eligible node + data node (cluster management, port 9200)
  • ES02 — Data node (stores and indexes APM data)
  • ES03 — Data node (stores and indexes APM data)

For simple development: Scale down to 1 node by removing es02 and es03 from docker-compose.yml and setting discovery.type: single-node on es01.


Monitoring Setup

Default credentials

Field Value
Username elastic
Password elastic123

Viewing APM data in Kibana

  1. Open http://localhost:5601 and log in
  2. Navigate to Observability → APM
  3. On first visit you'll see the welcome screen — that's normal
  4. Start the Express app and hit a few endpoints
  5. The express-apm-demo service appears automatically within ~1 minute

What you'll see in the APM UI

  • Service overview — response times, throughput, error rates
  • Transactions — per-endpoint breakdown with latency distributions
  • Errors — stack traces with context
  • Metrics — CPU, memory, and Node.js runtime metrics
  • Traces — distributed trace waterfall (span-level detail)

Configuration

APM agent (index.js)

const apm = require('elastic-apm-node').start({
    serviceName: 'express-apm-demo',  // appears as service name in Kibana
    serverUrl: 'http://localhost:8200',
    environment: 'development',
    captureBody: 'all'               // capture request bodies for debugging
});

Environment variables (.env)

Copy .env.example to .env before starting the stack. The file contains:

  • Elasticsearch credentials and cluster name
  • APM Server token configuration
  • Kibana connection settings

Security Notes

For POC / development use (current setup)

  • HTTP only — no SSL/TLS
  • Default passwords (elastic123)
  • Authentication enabled but simplified for local use

Before going to production

  • Rotate all default passwords
  • Enable HTTPS/TLS (certificates are already generated by the setup service)
  • Configure network-level access controls
  • Use environment-specific .env files and secrets management

Project Structure

elastic-apm-express-boilerplate/
├── index.js                # Express app — APM agent + all route handlers
├── docker-compose.yml      # Full Elastic Stack (ES cluster + Kibana + APM Server)
├── package.json            # Node.js dependencies and npm scripts
├── .env.example            # Environment variable template
├── .gitignore
└── README.md

Troubleshooting

Services won't start

# Check available Docker resources
docker system df

# View logs for a specific service
docker-compose logs -f apm-server
docker-compose logs -f es01

# Full reset (removes all volumes and data)
docker-compose down -v
docker-compose up -d

APM data not appearing in Kibana

  1. Confirm APM Server is healthy: docker-compose ps
  2. Check the Express app console for APM connection errors
  3. Hit at least one endpoint to generate a transaction: curl http://localhost:3000/
  4. Wait ~60 seconds — APM data has a small ingestion delay
  5. Verify you're on the Observability → APM page, not Metrics or Logs

Elasticsearch out of memory

Increase Docker memory allocation to at least 4 GB in Docker Desktop → Settings → Resources.


Contributing

Contributions, issues, and feature requests are welcome. Feel free to open an issue or submit a pull request.

Author: Anuj Patil
License: MIT

Releases

No releases published

Packages

 
 
 

Contributors