A production-grade reverse proxy and API gateway written from scratch in Go. Handles 10,000-24,000+ requests per second with P99 latency under 15ms, supporting HTTP/REST and gRPC upstream routing with dynamic load balancing, rate limiting, circuit breaking, service discovery, and comprehensive observability.
- HTTP & gRPC Reverse Proxying: Forward requests to multiple upstream services.
- Dynamic Routing & Config: YAML-based configuration with hot-reload support.
- Load Balancing: Round-robin and least-connections strategies.
- Circuit Breaker: Closed/Open/Half-Open state machine for fault isolation.
- Health Checking: Background polling to detect unhealthy upstreams.
- Rate Limiting: Redis-backed token bucket with atomic Lua scripts. Supports global rate limits and stress-testing bypass tokens.
- Service Discovery: Dynamic upstream discovery via Hashicorp Consul and etcd.
- API Key Authentication: Middleware for protecting endpoints with API keys.
- Prometheus Metrics: 10+ metric types for comprehensive monitoring.
- Grafana Dashboard: Pre-built, auto-provisioned dashboards with 10+ panels for live visualization.
- Structured Logging: JSON logs with request tracing.
- Admin UI: Beautiful React-based dashboard (using Nivo charts) for real-time system inspection, route management, and upstream health monitoring.
- Caddy Integration: Used as an edge reverse proxy and for SSL termination.
- Docker Compose: Full local development environment.
- Optimized Containers: Uses
scratchbase images and stripped binaries for minimal footprint. - Graceful Shutdown: Connection draining with configurable timeout.
- CI/CD & VPS: Automated VPS deployment, CI/CD pipeline, and benchmark scripts included.
- Throughput: 10,000-24,000+ requests per second (verified via extensive k6 load testing).
- Concurrent Users: Sustains 3,000+ Virtual Users (VUs) simultaneously without degradation.
- Latency: P99 < 15ms (without upstream delay).
- Rate Limit Overhead: < 1ms per request (Redis RTT).
Clients (k6 / wrk / curl)
│
▼
┌──────────────────────────────┐
│ Caddy (SSL) │
└──────────────┬───────────────┘
▼
┌──────────────────────────────┐
│ API Gateway (Go) │
│ ┌──────────────────────┐ │
│ │ Middleware Chain │ │
│ │ Recovery → RequestID│ │
│ │ → Auth → Logging │ │
│ │ → Metrics → RateLmt │ │
│ │ → Proxy │ │
│ └──────────────────────┘ │
└──────────────────────────────┘
│ │
┌────┴────┐ ┌────┴─────┐
│ Upstreams│ │ Redis │
│ A, B, C,D│ │(RateLimit│
└─────────┘ └──────────┘
│ │
┌───────────────┐ ┌──────────┐
│ Prometheus │ │ Consul / │
│ + Grafana │ │ etcd │
└───────────────┘ └──────────┘
- Go 1.22+
- Node.js (for Admin UI)
- Docker & Docker Compose
- Make
# Start all services (gateway + backends + Redis + Prometheus + Grafana)
make run-all
# Gateway: http://localhost:8080
# Admin UI: http://localhost:9090
# Grafana: http://localhost:3000 (admin/admin)
# Prometheus: http://localhost:9091# Start only infrastructure (Redis, Prometheus, Grafana, Consul)
make run-infra
# Build and run gateway locally
make run-gateway
# Start backend services
make run-backends# Build the gateway binary
make build
# Run all tests
make test
# Generate coverage report
make coverage
# Run linter
make lintWe use k6 for realistic, concurrent load testing and wrk for raw throughput analysis. Note that a bypass header (X-Stress-Test-Token) can be configured to bypass rate limits during testing.
# Run k6 basic load test (requires gateway running)
make bench-basic
# Run wrk for raw throughput testing
wrk -t12 -c400 -d30s http://localhost:8080/api/v1/users├── cmd/gateway/ # Gateway entry point
├── internal/
│ ├── config/ # Configuration loading & validation
│ ├── proxy/ # HTTP & gRPC reverse proxy
│ ├── router/ # Route matching & dispatch
│ ├── middleware/ # Middleware chain (Auth, RequestID, Logging, Metrics, RateLimit)
│ ├── loadbalancer/ # Round-robin & least-connections LB
│ ├── healthcheck/ # Background health polling
│ ├── metrics/ # Prometheus instrumentation
│ ├── ratelimit/ # Redis-backed token bucket
│ ├── circuitbreaker/ # State machine for fault isolation
│ ├── discovery/ # Consul and etcd service discovery providers
│ └── admin/ # Admin API server & handlers
├── examples/
│ └── backends/ # Example/Mock microservices for testing
├── admin-ui/ # React admin UI (Vite + Nivo Charts)
├── configs/ # Configuration files
├── scripts/ # Testing (k6, stress) and helper scripts
├── deploy/ # Deployment files
│ ├── Dockerfile # Gateway container image (scratch base)
│ ├── docker-compose.yml # Full stack composition
│ └── prometheus/ # Monitoring configs
└── Makefile # Build automation
Override YAML config values with environment variables:
GATEWAY_PORT=8080
GATEWAY_ADMIN_PORT=9090
REDIS_ADDR=localhost:6379
REDIS_PASSWORD=secret
GATEWAY_LOG_LEVEL=debug
TEST_API_KEY=my-secret-api-key
STRESS_TEST_BYPASS_TOKEN=super-secret-bypass
STRESS_TEST_BYPASS_HEADER=X-Stress-Test-TokenSee .env.example for all supported variables.
Define routes, upstream groups, rate limits, and load balancing strategies:
routes:
- path: /api/v1/users
upstream_group: user-service
load_balancer: round-robin
rate_limit:
requests_per_second: 100
burst: 20
upstream_groups:
- name: user-service
upstreams:
- url: http://service-a:8081
- url: http://service-b:8082
health_check:
path: /health
interval: 5s
timeout: 2sThe admin server runs on port 9090 and provides:
GET /admin/api/stats # Aggregated gateway stats
GET /admin/api/routes # All configured routes
GET /admin/api/upstreams # Upstream groups & health
GET /admin/api/circuit-breakers # Circuit breaker states
POST /admin/api/circuit-breakers/:id/reset # Force reset breaker
POST /admin/api/config/reload # Hot reload configuration
GET /admin/health # Admin server health
All metrics exposed at GET /metrics in Prometheus format:
gateway_requests_total- Total requests by route/method/statusgateway_request_duration_seconds- Request latency histogramgateway_upstream_request_duration_seconds- Upstream call latencygateway_rate_limited_total- Rejected requestsgateway_circuit_breaker_state- Circuit breaker state per upstreamgateway_circuit_breaker_trips_total- Times circuit openedgateway_upstream_health- Upstream health statusgateway_active_connections- Active connections per upstreamgateway_redis_operation_duration_seconds- Redis operation latency
Four test services to verify gateway functionality:
- Service A (port 8081): Fast REST service (~1ms response)
- Service B (port 8082): Slow REST service (50ms delay, 5% errors)
- Service C (port 9000): gRPC Echo service
- Service D (port 8083): REST service for least-connections testing
MIT