Skip to content

Latest commit

History

439 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Production-Grade Proxy Server

A config-driven HTTP proxy with enterprise-grade observability, security, and reliability—purpose-built for internal API gateways.

Node.jsLicensePRs Welcomenpm versionnpm downloads


Why This Exists

The Problem

You need a proxy that:

  • ✅ Routes requests intelligently (not just round-robin)
  • ✅ Validates requests before they hit your backend
  • ✅ Rate limits abusive clients
  • ✅ Fails gracefully when upstreams are down
  • ✅ Gives you deep observability (not just access logs)
  • ✅ Can be configured by non-engineers

Nginx/HAProxy: Fast but config is cryptic, no custom logic
Kong/Tyk: Powerful but heavyweight, complex to operate
Roll your own: Easy to start, hard to make production-ready

This Proxy

A middle ground: production-ready proxy in Node.js with:

  • Config-driven routing (YAML, not code)
  • Built-in security (SSRF protection, rate limiting, auth)
  • Deep observability (structured logs, Prometheus metrics, correlation IDs)
  • Reliability patterns (circuit breakers, retries, timeouts)
  • Developer-friendly (JavaScript, not Lua or C++)

dashboard

When to Use This

✅ Good Fit

  • Internal API gateway for microservices
  • Development/staging proxy with observability
  • Custom routing logic that's easier in JavaScript than Nginx config
  • Request transformation (header manipulation, body validation)
  • Team has Node.js expertise

❌ Not a Good Fit

  • Public-facing edge proxy (use Nginx/Cloudflare)
  • Ultra-high throughput (> 10K req/sec per instance)
  • Ultra-low latency (P99 < 5ms required)
  • Service mesh (use Istio/Linkerd)

What Makes This Production-Ready

Most "proxy tutorials" stop at forwarding requests. This goes further:

🔒 Security

  • SSRF Protection: Block access to cloud metadata, private IPs
  • Authentication: API key validation (HMAC-SHA256)
  • Rate Limiting: Token bucket with Redis backend
  • Input Validation: Header sanitization, payload size limits
  • Allow-list: Deny by default, explicit upstream allow-list

See full threat model →

🎯 Reliability

  • Circuit Breakers: Stop hitting failing upstreams
  • Retries: Exponential backoff with jitter
  • Timeouts: Request, connection, DNS, header, idle
  • Backpressure: Reject when overloaded (don't OOM crash)
  • Connection Pooling: Reuse TCP connections

See traffic control docs →

📊 Observability

  • Structured Logs: JSON logs with correlation IDs
  • Metrics: Prometheus-compatible (RPS, latency histograms, error rates)
  • Health Checks: Liveness, readiness, deep health
  • Tracing: Request flow across services (correlation IDs)
  • Real-Time Metrics: NATS JetStream streaming with SSE
  • Metrics Database: PostgreSQL storage for historical analysis
  • Admin Dashboard: React-based UI with live metrics visualization

See observability docs →

⚙️ Operability

  • Config Hot Reload: Update routes without restart
  • Graceful Shutdown: Drain connections before exit
  • Error Handling: Fail fast on bad config (don't serve traffic)
  • Kubernetes-Ready: Health probes, resource limits, signals
  • Admin UI: Web-based management console
  • Webhook System: Event-driven notifications with retry logic
  • Database-Backed Config: PostgreSQL for routes, API keys, webhooks

Quick Start

1. Install

git clone https://github.com/tapas100/flexgate-proxy.git
cd flexgate-proxy
npm install

2. Setup Database

# Install PostgreSQL (if not already installed)
brew install postgresql # macOS# or
sudo apt-get install postgresql # Linux# Create database
createdb flexgate
# Run migrations
psql -d flexgate -f migrations/001_initial_schema.sql
psql -d flexgate -f migrations/002_migration_tracking.sql
psql -d flexgate -f migrations/003_requests_table.sql
psql -d flexgate -f migrations/004_webhook_deliveries.sql
psql -d flexgate -f migrations/005_update_webhook_deliveries_schema.sql
psql -d flexgate -f migrations/006_fix_webhook_deliveries_fk.sql
psql -d flexgate -f migrations/008_ai_incident_tracking.sql

3. Setup NATS JetStream (for real-time metrics)

# Using Docker
docker run -d --name nats-jetstream \
-p 4222:4222 -p 8222:8222 \
nats:latest -js
# Or using Podman
podman run -d --name flexgate-nats \
-p 4222:4222 -p 8222:8222 -p 6222:6222 \
-v ~/flexgate-data/nats:/data:Z \
nats:2.10-alpine -js -sd /data

4. Environment Variables

# Copy example .env
cp .env.example .env
# Edit .env with your settings
DATABASE_URL=postgresql://localhost/flexgate
DATABASE_USER=flexgate
DATABASE_PASSWORD=your-password
REDIS_URL=redis://localhost:6379
NATS_URL=nats://localhost:4222
PORT=3000

5. Configure Routes

# config/proxy.ymlupstreams:
- name: "example-api"url: "https://api.example.com"timeout: 5000retries: 3routes:
- path: "/api/*"upstream: "example-api"auth: requiredrateLimit:
max: 100windowMs: 60000security:
allowedHosts:
- "api.example.com"blockedIPs:
- "169.254.169.254"# AWS metadata

6. Build Admin UI

cd admin-ui
npm install
npm run build
cd ..

7. Run with Docker/Podman (Recommended)

Simple one-command startup:

# Start all services (FlexGate, PostgreSQL, Redis, NATS, Prometheus, Grafana, HAProxy)
npm run start:all
# Check status
npm run status
# Stop all services
npm run stop:all
# Restart all services
npm run restart:all

What it does:

  • ✅ Starts 8 containers (PostgreSQL, Redis, NATS, 2× FlexGate apps, HAProxy, Prometheus, Grafana)
  • ✅ Waits for all services to be healthy
  • ✅ Verifies port accessibility
  • ✅ Shows access URLs and status

Access Points:

See full management guide →

8. Run Without Docker (Local Development)

# Development
npm run dev
# Production
npm start

9. Access Admin UI

# Open in browser
open http://localhost:3000/dashboard
# Available pages:# http://localhost:3000/dashboard - Real-time metrics# http://localhost:3000/routes - Route management# http://localhost:3000/webhooks - Webhook configuration# http://localhost:3000/logs - Audit logs# http://localhost:3000/settings - System settings

10. Test the Proxy

curl http://localhost:3000/api/users

🎨 Features Overview

🖥️ Admin UI

Modern React-based dashboard for managing your proxy:

  • 📊 Real-Time Dashboard: Live metrics with SSE streaming

    • Request rate, latency percentiles (P50, P95, P99)
    • Success/error rates, status code distribution
    • Auto-refreshing charts and gauges
  • 🛣️ Route Management: Visual interface for proxy routes

    • Create, edit, delete routes without config files
    • Enable/disable routes on-the-fly
    • Configure rate limits and circuit breakers per route
  • 🔑 API Key Management: Secure access control

    • Generate and revoke API keys
    • Set expiration dates and permissions
    • Usage tracking per key
  • 🪝 Webhook Configuration: Event-driven notifications

    • Subscribe to proxy events (errors, rate limits, circuit breaker trips)
    • Configure retry logic and backoff strategies
    • Monitor webhook delivery status
  • 📝 Audit Logs: Complete activity history

    • Track all configuration changes
    • User actions and system events
    • Searchable and filterable logs

See Admin UI docs →

🖥️ Command-Line Interface (CLI)

Powerful CLI for automation, CI/CD, and headless operation:

  • 🤖 AI Incident Tracking: Complete incident management from terminal

    • List, filter, and search incidents
    • View detailed incident information with recommendations
    • Create incidents from AI events
    • Record decisions and action outcomes
    • View analytics and ROI metrics
    • Export data (JSON/CSV)
    • Real-time monitoring (watch mode)
  • ⚙️ Configuration Management: Manage FlexGate from command line

    • Initialize and configure settings
    • Import/export configurations
    • Test database and Redis connections
    • Health checks and diagnostics
  • 🔄 Automation-Friendly: Built for scripting and integration

    • JSON output for parsing
    • Exit codes for success/failure
    • CI/CD pipeline integration
    • Slack/webhook notifications
    • Prometheus alert integration

Quick Examples:

# List open critical incidents
flexgate ai incidents --status OPEN --severity CRITICAL
# Show incident details
flexgate ai show evt_abc123
# Create incident and add recommendation
flexgate ai create --type LATENCY_ANOMALY --severity WARNING
flexgate ai recommend evt_abc123 --action RESTART_SERVICE --confidence 0.9
# View analytics dashboard
flexgate ai analytics --days 30
# Watch for new incidents in real-time
flexgate ai watch
# Export incidents to CSV
flexgate ai export --format csv --output incidents.csv
# Initialize FlexGate configuration
flexgate init --interactive
# Test connections
flexgate db test
flexgate redis test
flexgate health

See full CLI docs →

⚡ Real-Time Metrics (NATS JetStream)

High-performance streaming metrics powered by NATS JetStream:

  • Server-Sent Events (SSE): Real-time metric updates
  • Message Persistence: Historical metrics storage
  • Scalable Architecture: Handle millions of events
  • Event Consumers: Durable consumers for reliability
  • Multiple Streams: Separate METRICS and ALERTS channels

Endpoints:

  • GET /api/stream/metrics - Real-time metrics SSE stream
  • GET /api/stream/alerts - Real-time alerts SSE stream
  • GET /api/metrics - HTTP polling fallback

📊 Database-Backed Metrics

PostgreSQL storage for comprehensive analytics:

  • Request Logging: Every proxy request recorded

    • Method, path, status code, response time
    • Upstream, client IP, user agent
    • Request/response sizes, correlation IDs
  • Metrics Aggregation: Pre-computed summaries

    • Hourly, daily, weekly rollups
    • Percentile calculations (P50, P95, P99)
    • Error rate trends and availability metrics
  • Data Retention: Configurable retention policies

    • Auto-cleanup of old data
    • Partitioning for performance
    • Efficient indexing for fast queries

🪝 Webhook System

Event-driven architecture for integrations:

Supported Events:

  • request.error - Failed requests
  • rate_limit.exceeded - Rate limit violations
  • circuit_breaker.opened - Circuit breaker trips
  • upstream.failure - Upstream service failures
  • auth.failure - Authentication failures

Features:

  • Automatic Retries: Exponential backoff with jitter
  • Delivery Tracking: Monitor success/failure rates
  • Custom Headers: Authentication, signatures
  • Payload Filtering: Subscribe to specific events
  • HMAC Signatures: Webhook payload verification

See Webhooks docs →


Architecture

┌─────────────┐
│ Client │
└──────┬──────┘
│ HTTP/HTTPS
▼
┌──────────────────────────────────────────────┐
│ FlexGate Proxy Server │
│ ┌────────────────────────────────┐ │
│ │ 1. Authentication (API Keys) │ │
│ │ 2. Rate Limiting (Redis) │ │
│ │ 3. Request Validation │ │
│ │ 4. Circuit Breaker Check │ │
│ │ 5. Route Resolution │ │
│ │ 6. Metrics Recording │ │
│ └────────────────────────────────┘ │
└─────────────┬────────────────────────────────┘
│
▼
┌─────────────────────┐
│ Infrastructure │
│ ┌────────────┐ │
│ │ PostgreSQL │ │ ← Config, Metrics, Logs
│ └────────────┘ │
│ ┌────────────┐ │
│ │ Redis │ │ ← Rate Limits, Cache
│ └────────────┘ │
│ ┌────────────┐ │
│ │ JetStream │ │ ← Real-time Streams
│ └────────────┘ │
└─────────────────────┘
│

┌─────────────────────────────────────┐ │ Backend Services │ │ ┌─────────┐ ┌─────────┐ │ │ │ API A │ │ API B │ │ │ └─────────┘ └─────────┘ │ └─────────────────────────────────────┘


---
## Performance
| Metric | Value | Comparison |
|--------|-------|------------|
| **Throughput** | 4.7K req/sec | Nginx: 52K (11x faster) |
| **P95 Latency** | 35ms | Nginx: 8ms (4x faster) |
| **P99 Latency** | 52ms | Nginx: 12ms (4x faster) |
| **Memory** | 78 MB | Nginx: 12 MB (6x smaller) |
| **Proxy Overhead** | ~3ms | (14% of total latency) |
**Why slower than Nginx?**
- Node.js (interpreted) vs C (compiled)
- Single-threaded vs multi-threaded
- GC pauses
**Why use it anyway?**
- Custom logic in JavaScript (not Nginx config)
- Better observability
- Shared code with backend
- Faster development
[**See full benchmarks →**](benchmarks/README.md)
---
## Configuration
### Minimal Example
```yaml
# config/proxy.yml
upstreams:
- name: "backend"
url: "http://localhost:8080"
routes:
- path: "/*"
upstream: "backend"

Full Example

# Global settingsproxy:
port: 3000timeout: 30000maxBodySize: "10mb"# Securitysecurity:
allowedHosts:
- "api.example.com"
- "*.internal.corp"blockedIPs:
- "169.254.169.254"
- "10.0.0.0/8"auth:
type: "apiKey"header: "X-API-Key"# Rate limitingrateLimit:
backend: "redis"redis:
url: "redis://localhost:6379"global:
max: 1000windowMs: 60000# Upstreamsupstreams:
- name: "primary-api"url: "https://api.primary.com"timeout: 5000retries: 3circuitBreaker:
enabled: truefailureThreshold: 50openDuration: 30000
- name: "fallback-api"url: "https://api.fallback.com"timeout: 10000# Routesroutes:
- path: "/api/users/*"upstream: "primary-api"auth: requiredrateLimit:
max: 100windowMs: 60000
- path: "/api/batch/*"upstream: "primary-api"auth: requiredtimeout: 120000rateLimit:
max: 10windowMs: 60000# Logginglogging:
level: "info"format: "json"sampling:
successRate: 0.1errorRate: 1.0

See full config reference →


API Reference

Health Endpoints

GET /health

Basic health check.

{
"status": "UP",
"timestamp": "2026-01-29T10:30:45.123Z",
"version": "1.0.0"
}

GET /health/live

Kubernetes liveness probe.

{
"status": "UP",
"timestamp": "2026-01-29T10:30:45.123Z"
}

GET /health/ready

Kubernetes readiness probe.

{
"status": "UP",
"checks": {
"database": "UP",
"redis": "UP",
"jetstream": "UP"
}
}

Metrics Endpoints

GET /api/metrics

Get current metrics (HTTP polling).

{
"summary": {
"totalRequests": 12543,
"avgLatency": "23.45",
"errorRate": "0.0012",
"availability": "99.9988",
"p50Latency": "18.00",
"p95Latency": "45.00",
"p99Latency": "67.00"
},
"requestRate": {
"name": "Request Rate",
"data": [
{ "timestamp": "2026-01-29T13:00:00.000Z", "value": "234.5" }
],
"unit": "req/s"
},
"statusCodes": [
{ "code": 200, "count": 12000 },
{ "code": 404, "count": 543 }
]
}

GET /api/stream/metrics

Real-time metrics stream (SSE).

event: connected
data: {"type":"connected","clientId":"abc123"}
event: message
data: {"summary":{"totalRequests":12543,...},"timestamp":"2026-01-29T13:00:00.123Z"}
event: message
data: {"summary":{"totalRequests":12544,...},"timestamp":"2026-01-29T13:00:05.456Z"}

GET /api/stream/alerts

Real-time alerts stream (SSE).

event: message
data: {"type":"circuit_breaker.opened","upstream":"api-backend","timestamp":"..."}

Route Management

GET /api/routes

List all routes.

[
{
"id": 1,
"path": "/api/users",
"upstream": "https://api.example.com",
"methods": ["GET", "POST"],
"enabled": true,
"rateLimit": { "requests": 100, "window": "60s" },
"circuitBreaker": { "enabled": true, "threshold": 5 }
}
]

POST /api/routes

Create a new route.

{
"path": "/api/products",
"upstream": "https://products.example.com",
"methods": ["GET"],
"rateLimit": { "requests": 50, "window": "60s" }
}

PUT /api/routes/:id

Update a route.

DELETE /api/routes/:id

Delete a route.

Webhook Management

GET /api/webhooks

List all webhooks.

POST /api/webhooks

Create a webhook subscription.

{
"url": "https://your-app.com/webhook",
"events": ["request.error", "rate_limit.exceeded"],
"enabled": true,
"maxRetries": 3,
"initialDelay": 1000,
"backoffMultiplier": 2
}

DELETE /api/webhooks/:id

Delete a webhook.

Log Endpoints

GET /api/logs

Get audit logs with pagination.

{
"logs": [
{
"id": 1,
"timestamp": "2026-01-29T13:00:00.123Z",
"level": "info",
"message": "Route created",
"metadata": { "routeId": 5, "path": "/api/users" }
}
],
"total": 1234,
"page": 1,
"pageSize": 10
}

GET /prometheus-metrics

Prometheus-compatible metrics endpoint.

http_requests_total{method="GET",route="/api/users",status="200"} 12543
http_request_duration_ms_bucket{route="/api/users",le="50"} 12000
http_request_duration_ms_sum{route="/api/users"} 295430
http_request_duration_ms_count{route="/api/users"} 12543

Deployment

Podman (Recommended)

For high-performance production deployments (>10K req/sec), use HAProxy + Podman:

# Quick start with Makefile
make build # Build container image
make start # Start all services
make stats # View HAProxy dashboard# Or use podman-compose directly
podman-compose up -d
# Access services# HAProxy: http://localhost:8080# Stats: http://localhost:8404/stats (admin/admin)# Prometheus: http://localhost:9090# Grafana: http://localhost:3001 (admin/admin)

Features:

  • HAProxy data plane (>10K req/sec, <10ms latency)
  • Rate limiting: 1000 requests per 10 seconds per IP
  • Circuit breaker: automatic health checks every 2s
  • Load balancing across 2+ backend instances
  • Prometheus metrics + Grafana dashboards
  • Rootless, daemonless container runtime

📘 See haproxy/README.md for complete HAProxy documentation📘 See haproxy/PODMAN_SETUP.md for Podman setup guide

Standalone (Development)

For development or testing without HAProxy:

# Build image
npm run podman:build
# Run standalone
podman run -d -p 3000:3000 \
-v $(pwd)/config:/app/config:Z \
-e NODE_ENV=production \
localhost/flexgate-proxy:latest

Kubernetes

apiVersion: apps/v1kind: Deploymentmetadata:
name: flexgate-proxyspec:
replicas: 3selector:
matchLabels:
app: flexgate-proxytemplate:
metadata:
labels:
app: flexgate-proxyspec:
containers:
- name: proxyimage: flexgate-proxy:latestports:
- containerPort: 3000resources:
limits:
memory: "256Mi"cpu: "500m"requests:
memory: "128Mi"cpu: "250m"livenessProbe:
httpGet:
path: /health/liveport: 3000initialDelaySeconds: 10periodSeconds: 10readinessProbe:
httpGet:
path: /health/readyport: 3000initialDelaySeconds: 5periodSeconds: 5env:
- name: NODE_ENVvalue: "production"
- name: REDIS_URLvalueFrom:
secretKeyRef:
name: proxy-secretskey: redis-url

See deployment guide →


Monitoring

Grafana Dashboard

When running via npm run start:all (Podman stack), Grafana is available at http://localhost:3001 (admin/admin).

Dashboard includes:

  • Request rate (by route, status)
  • Latency percentiles (P50, P95, P99)
  • Error rate
  • Circuit breaker state
  • Rate limit hits

Alerts

Prometheus alert rules are in infra/prometheus/alerts.yml.

# Prometheus alertsgroups:
- name: proxyrules:
- alert: HighErrorRateexpr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05for: 2mlabels:
severity: criticalannotations:
summary: "Proxy error rate > 5%"
- alert: HighLatencyexpr: http_request_duration_ms{quantile="0.99"} > 1000for: 5mlabels:
severity: warningannotations:
summary: "P99 latency > 1s"

Security

SSRF Protection

security:
allowedHosts:
- "api.example.com"blockedIPs:
- "169.254.169.254"# AWS metadata
- "169.254.170.2"# ECS metadata
- "fd00:ec2::254"# AWS IPv6 metadata
- "10.0.0.0/8"# Private network
- "127.0.0.0/8"# Localhost

Authentication

security:
auth:
type: "apiKey"header: "X-API-Key"keys:
- key: "client-a-key-sha256-hash"name: "Client A"
- key: "client-b-key-sha256-hash"name: "Client B"

Rate Limiting

rateLimit:
perRoute:
- path: "/api/expensive/*"max: 10windowMs: 60000message: "This endpoint is heavily rate limited"

See threat model →


What This Proxy is NOT

❌ Not This✅ Use Instead
CDN / Edge cacheCloudflare, Fastly
Service meshIstio, Linkerd
Raw performance proxyNginx, HAProxy, Envoy
Public-facing API gatewayKong, Tyk, AWS API Gateway
Load balancerHAProxy, AWS ALB

When to Replace This

Consider switching to Nginx/Envoy when:

  1. Throughput > 10K req/sec per instance needed
  2. P99 latency < 10ms required
  3. No custom logic needed (pure reverse proxy)
  4. Team lacks Node.js expertise

Failure Modes

Upstream Down

Circuit breaker opens → Fast-fail with 503
↓
Retry every 30s (half-open state)
↓
If success → Circuit closes

Proxy Overloaded

Queue fills → Backpressure kicks in
↓
Reject low-priority routes
↓
Sample logging aggressively
↓
If still overloaded → Reject all with 503

Redis Down

Rate limiter falls back to local state
↓
Less accurate (per-instance limits)
↓
But service stays up

Config Error

Config validation fails → Startup blocked
↓
Old config still serving (hot reload)
↓
Alert fires → Engineer fixes config

Key principle: Fail closed, degrade gracefully


Documentation


CI/CD

FlexGate uses Jenkins (not GitHub Actions) for all build, test, and publish pipelines.

TriggerPipeline
Push to mainLint → Type-check → Test → Build → npm publish
Merge PR into mainSame as above

The full pipeline is defined in Jenkinsfile at the repo root.

Jenkins credentials required:

  • NPM_TOKEN — npm publish token (add under Jenkins → Manage Credentials)

See .github/WORKFLOWS.md for full Jenkins setup instructions.


Contributing

We welcome contributions! Please see CONTRIBUTING.md.

Development Setup

git clone https://github.com/tapas100/flexgate-proxy.git
cd flexgate-proxy
npm install
# Run tests
npm test# Run in dev mode (with hot reload)
npm run dev
# Lint
npm run lint
# Benchmarks
npm run benchmark

Roadmap

✅ Completed

  • Admin UI: Web UI for config management (React + Material-UI)
  • Real-Time Metrics: NATS JetStream with SSE streaming
  • Webhooks: Event-driven notifications with retry logic
  • Database Storage: PostgreSQL for config and metrics
  • API Key Auth: HMAC-SHA256 authentication
  • Circuit Breakers: Per-route circuit breaking
  • Rate Limiting: Redis-backed token bucket
  • Metrics Recording: Request logging to database
  • Prometheus Metrics: Prometheus-compatible endpoint at /prometheus-metrics

🚧 In Progress

  • OAuth 2.0 / OIDC: Social login for Admin UI
  • OpenTelemetry: Distributed tracing integration

📋 Planned

  • mTLS Support: Mutual TLS to backends
  • GraphQL Federation: GraphQL proxy support
  • WebAssembly Plugins: Custom logic in Wasm
  • gRPC Support: Proxy gRPC services
  • Service Mesh: Kubernetes integration with sidecars
  • Multi-tenancy: Isolated environments per tenant

License

MIT © Tapas M


Acknowledgments

Inspired by:


Support


Built with ❤️ for the backend engineering community

About

A production-grade edge proxy with security, traffic control, and observability, built for modern cloud-native systems.

Topics

Resources

Code of conduct

Stars

1 star

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages