A full-stack distributed application combining Express.js REST API, Temporal.io workflow orchestration, OpenTelemetry observability, and Docker containerization with comprehensive monitoring.
- Express.js REST API - HTTP endpoints for triggering workflows
- Temporal Workflow Orchestration - Durable, reliable workflow execution
- OpenTelemetry Metrics - Custom activity performance tracking
- Docker Containerization - Production-ready deployment
- Prometheus & Grafana - Real-time monitoring and visualization
- PostgreSQL Persistence - Workflow state storage
┌─────────────┐ HTTP ┌─────────────┐ gRPC ┌─────────────┐ │ Express │ ─────────► │ Temporal │ ─────────► │ Worker │ │ Server │ │ Server │ │ Process │ │ (Port 3000) │ ◄───────── │ (Port 7233) │ ◄───────── │ │ └─────────────┘ Response │ │ Results └─────────────┘ │ │ │ PostgreSQL │ │ (Port 5433) │ └─────────────┘ ▲ │ OTLP gRPC (4317) ▼ ┌─────────────┐ Pull ┌─────────────┐ Query ┌─────────────┐ │ OTEL │ ◄───────── │ Prometheus │ ─────────► │ Grafana │ │ Collector │ (8889) │ (Port 9090) │ │ (Port 3001) │ │ (4317/4318) │ │ │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ - Quick Start
- API Endpoints
- Workflow Execution
- Metrics & Monitoring
- Development
- Deployment
- Architecture Details
- Docker & Docker Compose
- Node.js 18+
- npm or pnpm
- Clone and install dependencies:
git clone <repository-url> cd express-temporal npm install- Setup environment:
cp .env.example .env # Edit .env with your configuration- Start infrastructure:
# Start all services (Temporal, PostgreSQL, Prometheus, etc.) docker-compose -f docker/docker-compose.yml up -d- Start the application:
# Development mode with auto-restart npm run dev # Or production mode npm start- Test the application:
# Health check curl http://localhost:3000/ # Trigger a greeting workflow curl -X POST http://localhost:3000/greet \ -H "Content-Type: application/json" \ -d '{"name": "World"}' # Trigger a farewell workflow curl -X POST http://localhost:3000/farewell \ -H "Content-Type: application/json" \ -d '{"name": "World"}'GET /Returns server status.
POST /greet Content-Type: application/json { "name": "John Doe" }Triggers a greeting workflow and returns workflow metadata.
POST /farewell Content-Type: application/json { "name": "John Doe" }Triggers a farewell workflow and returns workflow metadata.
The application uses Temporal.io for reliable workflow orchestration:
- Client Request → Express receives HTTP request
- Workflow Start → Temporal server creates durable workflow
- Task Distribution → Work assigned to appropriate task queue
- Activity Execution → Worker processes individual activities
- Metrics Collection → Performance metrics recorded
- Result Return → Workflow completion with response
- GreetWorkflow - Generates personalized greetings
- FarewellWorkflow - Generates personalized farewells
- Activity Execution Count - Total activity executions by type
- Activity Execution Latency - Performance timing histograms
- Worker Identity - Which worker processed each activity
- Workflow ID - Links activities to specific workflow instances
- Temporal UI: http://localhost:8080 (Workflow management)
- Prometheus: http://localhost:9090 (Metrics querying)
- Grafana: http://localhost:3001 (Visualization dashboards)
# Find activities by worker sum by (activity_type, worker_identity) (activity_execution_total{worker_identity="123@hostname"}) # Find highest latency activities histogram_quantile(0.95, sum(rate(activity_execution_latency_milliseconds_bucket[5m])) by (le, activity_type, worker_identity, workflow_id)) ├── server.js # Express application ├── temporal/ # Temporal workflows & workers │ ├── worker.js # Worker process │ ├── src/workflows/ # Workflow definitions │ └── config/ # Temporal configuration ├── metrics/ # Custom metrics ├── docker/ # Container configurations ├── instrumentation.mjs # OpenTelemetry setup └── PRESENTATION.md # Detailed architecture docs Core Stack:
- Express.js (4.18.2) - Web framework
- Temporal.io SDK (1.13.0) - Workflow orchestration
- OpenTelemetry (0.57.0) - Observability
- PostgreSQL - Data persistence
Monitoring:
- Prometheus - Metrics collection
- Grafana - Visualization
- OpenTelemetry Collector - Metrics aggregation
Development:
- Nodemon - Auto-restart
- Winston - Logging
- Docker Compose - Local infrastructure
# Application PORT=3000 NODE_ENV=development # Temporal TEMPORAL_ADDRESS=localhost:7233 GREET_QUEUE=greet-queue # OpenTelemetry OTEL_SERVICE_NAME=express-temporal-service OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # Database (for Docker services) POSTGRES_USER=temporal POSTGRES_PASSWORD=password# Build and start all services docker-compose -f docker/docker-compose.yml up -d # Scale worker instances docker-compose up -d --scale express-app=3 # View logs docker-compose logs -f express-app # Stop all services docker-compose down- Horizontal Scaling: Multiple worker instances per task queue
- Database: Use managed PostgreSQL with read replicas
- Monitoring: Configure alerts and dashboards
- Security: Network isolation and authentication
For comprehensive architecture documentation including:
- Detailed workflow execution flow
- Complete metrics pipeline from SDK to Prometheus
- Docker service configurations
- Scaling strategies
- Troubleshooting guides
See ARCHITECTURE.md for the complete technical deep-dive.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
ISC License - see LICENSE file for details.
Worker Connection Failed:
docker-compose ps # Check service status docker-compose logs temporal # Check Temporal logsMetrics Not Appearing:
docker-compose logs otel-collector # Check collector logs curl http://localhost:9090/targets # Check Prometheus targetsWorkflow Stuck:
docker-compose logs express-app # Check worker logs docker-compose exec temporal-admin-tools tctl workflow list # List workflowsFor detailed troubleshooting, see the ARCHITECTURE.md troubleshooting section.
