A complete boilerplate/starter template for setting up Application Performance Monitoring (APM) with Express.js and the Elastic Stack. This repository provides a ready-to-use setup for monitoring Node.js applications in development and production environments.
- Pre-configured Express.js server with Elastic APM agent
- Sample endpoints for testing different monitoring scenarios
- Error handling and performance tracking
- Request logging and middleware
- Elasticsearch: 3-node cluster for data storage
- Kibana: Web interface for data visualization
- APM Server: Collects and processes application performance data
- Docker Compose: One-command deployment
graph TB
subgraph "External Access"
USER[("π€ User")]
BROWSER[("π Browser")]
end
subgraph "Express.js Application"
APP["π± Express App<br/>index.js<br/>Port: 3000"]
APM_AGENT["π APM Agent<br/>elastic-apm-node"]
end
subgraph "Elastic Stack"
APM_SERVER["π APM Server<br/>Port: 8200"]
subgraph "Elasticsearch Cluster"
ES01["π ES01<br/>Master Node<br/>Port: 9200"]
ES02["π ES02<br/>Data Node"]
ES03["π ES03<br/>Data Node"]
end
KIBANA["π Kibana<br/>Port: 5601"]
SETUP["βοΈ Setup Service<br/>Certificates & Passwords"]
end
subgraph "Data Storage"
CERTS[("π Certificates<br/>Volume")]
DATA1[("πΎ ES01 Data<br/>Volume")]
DATA2[("πΎ ES02 Data<br/>Volume")]
DATA3[("πΎ ES03 Data<br/>Volume")]
KIBANA_DATA[("π Kibana Data<br/>Volume")]
end
%% User connections
USER --> APP
BROWSER --> KIBANA
%% Application connections
APP --> APM_AGENT
APM_AGENT --> APM_SERVER
%% APM Server connections
APM_SERVER --> ES01
%% Kibana connections
KIBANA --> ES01
%% Setup connections
SETUP --> ES01
SETUP --> CERTS
%% Elasticsearch cluster connections
ES01 <--> ES02
ES02 <--> ES03
ES03 <--> ES01
%% Data storage connections
ES01 --> DATA1
ES02 --> DATA2
ES03 --> DATA3
KIBANA --> KIBANA_DATA
ES01 --> CERTS
ES02 --> CERTS
ES03 --> CERTS
- Express App sends APM data to APM Server via the elastic-apm-node agent
- APM Server processes and stores data in the Elasticsearch cluster
- Elasticsearch cluster consists of 3 nodes (es01, es02, es03) for high availability
- Kibana connects to the cluster to visualize APM data and metrics
- Setup service handles initial certificate generation and password configuration
- Docker volumes persist data and certificates across container restarts
Could we use just 1 node? Yes! A single Elasticsearch node would work perfectly for basic APM monitoring and development.
Why use 3 nodes then? This boilerplate uses a 3-node cluster to provide:
- High Availability: If one node fails, the cluster continues running
- Fault Tolerance: Data is replicated across nodes, preventing data loss
- Load Distribution: Query and indexing load is distributed across nodes
- Scalability: Easy to add more nodes as your application grows
- Mirror Production: Test your APM setup in a cluster environment
- Performance Testing: Understand how your monitoring performs under load
- Cluster Behavior: Experience Elasticsearch cluster dynamics (master election, shard allocation, etc.)
- ES01: Master-eligible node (handles cluster management) + Data node
- ES02: Data node (stores and indexes APM data)
- ES03: Data node (stores and indexes APM data)
π‘ For Simple Development: You can easily scale down to 1 node by removing es02 and es03 from docker-compose.yml and updating the cluster configuration.
- Docker & Docker Compose installed
- Node.js 16+ (for running the Express app locally)
- 4GB+ RAM available for Elasticsearch cluster
git clone <repository-url>
cd elastic-apm-express-boilerplate
npm install
# Copy environment file
cp .env.example .env
# Start Elasticsearch, Kibana, and APM Server
docker-compose up -d
# Wait for services to be ready (2-3 minutes)
docker-compose ps
# Start the Express server with APM monitoring
node index.js
- Express App: http://localhost:3000
- Kibana: http://localhost:5601
- Elasticsearch: http://localhost:9200
- APM Server: http://localhost:8200
The Express application includes 5 pre-built endpoints for testing APM monitoring:
Endpoint | Purpose | What it monitors |
---|---|---|
GET / |
Basic endpoint | Response time, throughput |
GET /error |
Error generation | Error tracking, stack traces |
GET /async |
Async operations | Promise handling, async performance |
GET /cpu-intensive |
CPU load testing | CPU usage, response time under load |
GET /db-simulation |
Database simulation | Database query performance, spans |
- Username:
elastic
- Password:
elastic123
- Open Kibana: http://localhost:5601
- Login with credentials above
- Go to Observability β APM
- Initial State: You'll see "Welcome to Elastic Observability!" until the Express app connects
- Auto-Detection: Once your Express app runs and sends data, the welcome screen disappears (within ~1 minute)
- View your
express-apm-demo
service automatically
π Auto-Setup: APM integration is pre-configured. No manual setup needed - just start the Express app and it will be detected automatically.
- Service overview: Response times, throughput, error rates
- Transactions: Detailed view of each endpoint
- Errors: Stack traces and error details
- Metrics: CPU, memory, and system metrics
- Traces: Distributed tracing (useful for microservices)
The APM agent is configured in index.js
:
const apm = require('elastic-apm-node').start({
serviceName: 'express-apm-demo',
serverUrl: 'http://localhost:8200',
environment: 'development',
captureBody: 'all'
});
- HTTP-only setup (no SSL) for easy development
- Default passwords included
- Authentication enabled but simplified
π For Production
- Change all default passwords
- Enable HTTPS/SSL certificates
- Configure proper network security
- Use environment-specific configurations
βββ docker-compose.yml # Elastic Stack configuration
βββ index.js # Express app with APM integration
βββ package.json # Dependencies and scripts
βββ .env.example # Environment template
βββ .gitignore # Git ignore rules
βββ README.md # This file
# Check Docker resources
docker system df
# View service logs
docker-compose logs -f
# Restart everything
docker-compose down -v
docker-compose up -d
- Ensure APM Server is running:
docker-compose ps
- Check Express app is connecting: Look for APM logs in console
- Verify Kibana APM plugin is enabled
- Generate some traffic to the endpoints