README
ΒΆ
Switchboard Gateway
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β βββββββββββ βββββββββββββββ ββββββββββ βββ β
β βββββββββββ ββββββββββββββββββββββββββ βββ β
β βββββββββββ ββ ββββββ βββ βββ ββββββββ β
β βββββββββββββββββββββ βββ βββ ββββββββ β
β βββββββββββββββββββββ βββ βββββββββββ βββ β
β ββββββββ ββββββββ βββ βββ ββββββββββ βββ β
β β
β High-Performance API Gateway β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
One gateway. All your APIs. Complete control.
Switchboard is a lightweight, high-performance API Gateway that sits between your clients and microservices. Authenticate requests, enforce rate limits, cache responses, and route trafficβall with sub-millisecond overhead and zero downtime configuration updates.
Why Switchboard?
You have microservices. You need to:
- Authenticate every request before it hits your backend
- Rate limit abusive clients before they take you down
- Cache responses to reduce load and improve speed
- Route traffic to the right service based on path, method, or host
- Change configuration without restarting anything
Switchboard does all of this. Here's how it works.
π¬ See It In Action: A Complete Walkthrough
Let's say you're building an e-commerce platform with three microservices: Users, Products, and Orders. You want to expose them through a single API endpoint with authentication, rate limiting, and caching.
Here's exactly how you'd set that up with Switchboard.
Step 0: Start Switchboard
# Clone and start everything
git clone https://github.com/saidutt46/switchboard-gateway.git
cd switchboard-gateway
docker-compose up -d
make run
# Gateway runs on :8080, Admin API on :8000
You now have two endpoints:
http://localhost:8080β The Gateway (where clients send requests)http://localhost:8000β The Admin API (where you configure everything)
Step 1: Register Your API Consumers
Consumers are the applications or services that will call your API. Think of them as your API clientsβa mobile app, a partner integration, an internal service.
Every consumer gets tracked, authenticated, and can have individual rate limits.
# Register your mobile app as a consumer
curl -X POST http://localhost:8000/consumers \
-H "Content-Type: application/json" \
-d '{
"username": "mobile-app-ios",
"email": "ios-team@yourcompany.com"
}'
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"username": "mobile-app-ios",
"email": "ios-team@yourcompany.com",
"created_at": "2024-01-15T10:30:00Z"
}
Now generate an API key for this consumer:
curl -X POST http://localhost:8000/consumers/550e8400-e29b-41d4-a716-446655440001/keys \
-H "Content-Type: application/json" \
-d '{"name": "production-key"}'
Response:
{
"id": "key-uuid-here",
"name": "production-key",
"key": "sk_live_a1b2c3d4e5f6..."
}
β οΈ Save this key! It's only shown once. This is what your mobile app will use to authenticate.
Step 2: Define Your Backend Services
Services are your actual microservices. Tell Switchboard where they live.
# User Service
curl -X POST http://localhost:8000/services \
-H "Content-Type: application/json" \
-d '{
"name": "user-service",
"protocol": "http",
"host": "users.internal",
"port": 8001
}'
# Product Service
curl -X POST http://localhost:8000/services \
-H "Content-Type: application/json" \
-d '{
"name": "product-service",
"protocol": "http",
"host": "products.internal",
"port": 8002
}'
# Order Service
curl -X POST http://localhost:8000/services \
-H "Content-Type: application/json" \
-d '{
"name": "order-service",
"protocol": "http",
"host": "orders.internal",
"port": 8003
}'
You now have three services registered. But traffic can't reach them yetβwe need routes.
Step 3: Create Routes to Connect Everything
Routes map incoming requests to backend services. They define which paths go where.
# Route /api/users/* β user-service
curl -X POST http://localhost:8000/routes \
-H "Content-Type: application/json" \
-d '{
"service_id": "<user-service-id>",
"name": "user-routes",
"paths": ["/api/users", "/api/users/:id"],
"methods": ["GET", "POST", "PUT", "DELETE"]
}'
# Route /api/products/* β product-service
curl -X POST http://localhost:8000/routes \
-H "Content-Type: application/json" \
-d '{
"service_id": "<product-service-id>",
"name": "product-routes",
"paths": ["/api/products", "/api/products/:id", "/api/products/:id/reviews"],
"methods": ["GET", "POST", "PUT", "DELETE"]
}'
# Route /api/orders/* β order-service
curl -X POST http://localhost:8000/routes \
-H "Content-Type: application/json" \
-d '{
"service_id": "<order-service-id>",
"name": "order-routes",
"paths": ["/api/orders", "/api/orders/:id"],
"methods": ["GET", "POST"]
}'
Traffic now flows! But anyone can access your API. Let's fix that.
# This works (but shouldn't without auth!)
curl http://localhost:8080/api/users
# β Returns user data
Step 4: Lock It Down with Authentication
Plugins add functionality to your gateway. Let's require API keys for all requests.
curl -X POST http://localhost:8000/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "api-key-auth",
"scope": "global",
"config": {
"key_header": "X-API-Key"
},
"enabled": true,
"priority": 1
}'
Now try accessing without a key:
curl http://localhost:8080/api/users
# β 401 Unauthorized: Missing API key
Use the key we generated earlier:
curl -H "X-API-Key: sk_live_a1b2c3d4e5f6..." http://localhost:8080/api/users
# β 200 OK: Returns user data
β Authentication is live. Only registered consumers with valid keys can access your API.
Step 5: Protect Your Services with Rate Limiting
A single consumer shouldn't be able to hammer your API. Let's add rate limiting.
curl -X POST http://localhost:8000/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "rate-limit",
"scope": "global",
"config": {
"algorithm": "token-bucket",
"limit": 100,
"window": "1m",
"identifier": "consumer_id"
},
"enabled": true,
"priority": 10
}'
Every consumer now gets 100 requests per minute. The response headers tell them their quota:
curl -I -H "X-API-Key: sk_live_a1b2c3d4e5f6..." http://localhost:8080/api/users
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1699123456
Exceed the limit and they get blocked:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
β Rate limiting is live. Your backends are protected from abuse.
Step 6: Speed Things Up with Caching
Product listings don't change every second. Let's cache them.
curl -X POST http://localhost:8000/plugins \
-H "Content-Type: application/json" \
-d '{
"name": "cache",
"scope": "service",
"service_id": "<product-service-id>",
"config": {
"ttl_seconds": 300,
"cache_methods": ["GET"],
"bypass_paths": ["/api/products/flash-sale"]
},
"enabled": true,
"priority": 5
}'
First request hits the backend:
curl -I -H "X-API-Key: ..." http://localhost:8080/api/products
HTTP/1.1 200 OK
X-Cache: MISS
X-Response-Time: 150ms
Second request is served from cache:
curl -I -H "X-API-Key: ..." http://localhost:8080/api/products
HTTP/1.1 200 OK
X-Cache: HIT
X-Cache-TTL: 298
Age: 2
X-Response-Time: 17ms
β Caching is live. Product listings are now 9x faster.
Step 7: The Complete Picture
Here's what you've built:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR CLIENTS β
β Mobile App (iOS) β’ Mobile App (Android) β’ Partner API β
βββββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β
β X-API-Key: sk_live_...
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SWITCHBOARD GATEWAY β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β API Key β β β Rate β β β Cache β β Routeβ
β β Auth β β Limiting β β (Redis) β β
β β (priority 1)β β (priority 10)β β (priority 5) β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β
β Routes: β
β /api/users/* β user-service:8001 β
β /api/products/* β product-service:8002 (cached!) β
β /api/orders/* β order-service:8003 β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββΌββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββ ββββββββββββββ ββββββββββββββ
β Users β β Products β β Orders β
β Service β β Service β β Service β
ββββββββββββββ ββββββββββββββ ββββββββββββββ
Every request now:
- β Authenticates via API key (rejects unauthorized requests)
- β Checks rate limit (protects backends from abuse)
- β Serves from cache if available (reduces latency)
- β Routes to the correct backend service
- β Tracks which consumer made the request
And you can change any of this without restarting. Hot reload updates configuration in under 200ms.
π Performance
Real benchmarks from load testing:
| Metric | Result |
|---|---|
| Throughput | 5,075 req/s sustained |
| Latency (p50) | 4.44ms |
| Latency (p95) | 18.71ms |
| Gateway Overhead | < 2ms |
| Cache HIT | 17ms |
| Rate Limit Check | < 1ms |
| Hot Reload | < 200ms |
| Error Rate | 0% |
β¨ Features at a Glance
| Feature | Description |
|---|---|
| π High Performance | Radix tree routing with O(log n) lookups |
| π€ Consumer Management | Track and manage API clients |
| π Authentication | API Key and JWT support |
| β‘ Rate Limiting | Token Bucket & Sliding Window algorithms |
| πΎ Response Caching | Redis-backed with smart cache keys |
| π Hot Reload | Zero-downtime config updates via Redis pub/sub |
| ποΈ Admin API | Full REST APIβno config files needed |
| π Plugin System | Extensible architecture for custom logic |
| π Structured Logging | JSON logs with request tracing |
| π₯οΈ Admin Dashboard | React UI for visual gateway management |
| π Admin Auth | JWT login with role-based access (admin/viewer) |
π₯οΈ Admin Dashboard
Switchboard includes an Admin UI for managing your gateway visually β configure services, routes, consumers, plugins, and monitor health without touching curl.
# Start everything
docker compose up -d
# Admin UI: http://localhost:4000
# Admin API: http://localhost:8000
# Gateway: http://localhost:8080
Built with React 19, TypeScript, and Tailwind CSS. See admin-ui/ for development setup and testing.
π Available Plugins
| Plugin | What It Does | Scopes |
|---|---|---|
api-key-auth |
Validates API keys from header/query | Global, Service, Route |
jwt-auth |
Validates JWT tokens | Global, Service, Route |
rate-limit |
Enforces request quotas | Global, Service, Route, Consumer |
cache |
Caches responses in Redis | Global, Service, Route |
cors |
Adds CORS headers | Global, Service, Route |
request-logger |
Logs request/response details | Global |
Plugin Priority: Lower number = runs first. Auth should be 1, rate limiting 10, caching 5.
ποΈ Architecture
βββββββββββββββββββ βββββββββββββββββββ
β Admin UI βββββΆβ Admin API β
β (React :4000) β β (Python :8000) β
βββββββββββββββββββ ββββββββββ¬βββββββββ
β CRUD Operations
βΌ
ββββββββββββ βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client βββββΆβ Switchboard Gateway (:8080) β
ββββββββββββ β β
β Request Flow: β
β ββββββββββ ββββββββββ ββββββββββ βββββββββ β
β β Auth βββΆβ Rate βββΆβ Cache βββΆβ Proxy β β
β β Plugin β β Limit β β Plugin β β β β
β ββββββββββ ββββββββββ ββββββββββ βββββββββ β
β β
β Config: Hot-reloaded from PostgreSQL + Redis β
βββββββββββββββββββββββ¬ββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββΌββββββββββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββββ ββββββββββββββ ββββββββββββββ
β Service A β β Service B β β Service C β
ββββββββββββββ ββββββββββββββ ββββββββββββββ
Data Stores:
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β PostgreSQL β β Redis β β Kafka β
β β’ Config β β β’ Cache β β β’ Logs β
β β’ Routes β β β’ Rate β β β’ Events β
β β’ Consumersβ β Limits β β β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
βοΈ Configuration
Environment Variables
| Variable | Default | Description |
|---|---|---|
GATEWAY_PORT |
8080 |
Gateway listen port |
POSTGRES_DSN |
required | PostgreSQL connection string |
REDIS_URL |
redis://localhost:6379/0 |
Redis connection URL |
LOG_LEVEL |
info |
Log level (debug, info, warn, error) |
LOG_FORMAT |
json |
Log format (json, console) |
Example .env
GATEWAY_PORT=8080
POSTGRES_DSN=postgres://switchboard:switchboard@localhost:5432/switchboard?sslmode=disable
REDIS_URL=redis://localhost:6379/0
LOG_LEVEL=info
ENVIRONMENT=production
π Quick Start (TL;DR)
# 1. Start everything
git clone https://github.com/saidutt46/switchboard-gateway.git
cd switchboard-gateway
docker-compose up -d
make run
# 2. Create a consumer + API key
curl -X POST http://localhost:8000/consumers -H "Content-Type: application/json" \
-d '{"username": "my-app"}'
# Note the consumer ID, then:
curl -X POST http://localhost:8000/consumers/<id>/keys -H "Content-Type: application/json" \
-d '{"name": "my-key"}'
# Save the key!
# 3. Create a service
curl -X POST http://localhost:8000/services -H "Content-Type: application/json" \
-d '{"name": "my-backend", "host": "localhost", "port": 3000}'
# 4. Create a route
curl -X POST http://localhost:8000/routes -H "Content-Type: application/json" \
-d '{"service_id": "<service-id>", "paths": ["/api"], "methods": ["GET", "POST"]}'
# 5. Enable auth plugin
curl -X POST http://localhost:8000/plugins -H "Content-Type: application/json" \
-d '{"name": "api-key-auth", "scope": "global", "config": {}, "enabled": true, "priority": 1}'
# 6. Test it!
curl -H "X-API-Key: <your-key>" http://localhost:8080/api
π³ Docker Deployment
Three Docker Packages
Switchboard uses a 3-package architecture for optimal performance and scaling:
| Package | Purpose | Size | Scaling Strategy |
|---|---|---|---|
| Gateway | High-performance traffic routing (Go) | ~20MB | Horizontal (1-100+ instances) |
| Admin API | Configuration management REST API (Python) | ~200MB | Minimal (1-2 instances) |
| Admin UI | React dashboard (nginx) | ~25MB | Minimal (1 instance) |
Deployment Options
Option 1: Docker Compose (Recommended for Development/Testing)
# Start full stack
docker-compose up -d
# View logs
docker-compose logs -f gateway
docker-compose logs -f admin-api
# Check health
curl http://localhost:8080/health # Gateway
curl http://localhost:8000/health # Admin API
open http://localhost:4000 # Admin UI
Option 2: Pull Pre-built Images (Production)
# Pull images
docker pull ghcr.io/saidutt46/switchboard-gateway/gateway:v0.7.0
docker pull ghcr.io/saidutt46/switchboard-gateway/admin-api:v0.7.0
# Run Gateway
docker run -d \
--name switchboard-gateway \
-p 8080:8080 \
-e POSTGRES_DSN="postgresql://user:pass@postgres:5432/switchboard" \
-e REDIS_URL="redis://redis:6379/0" \
ghcr.io/saidutt46/switchboard-gateway/gateway:v0.7.0
# Run Admin API
docker run -d \
--name switchboard-admin-api \
-p 8000:8000 \
-e DATABASE_URL="postgresql://user:pass@postgres:5432/switchboard" \
-e REDIS_URL="redis://redis:6379/0" \
ghcr.io/saidutt46/switchboard-gateway/admin-api:v0.7.0
Option 3: Build Locally
# Build Gateway
make docker-build-gateway
# Build Admin API
make docker-build-admin
# Or build both
make docker-build-all
Environment Variables
Copy the example environment file and customize:
cp .env.example .env
# Edit .env with your configuration
See Configuration section for all available options.
π§ͺ Testing
# Unit tests
make test
# Integration tests
make test-integration
# Load tests
k6 run tests/load/stress.js
# Manual test scripts
./tests/manual/test_admin_api.sh
./tests/manual/test_rate_limit.sh
./tests/manual/test_cache.sh
π Project Structure
switchboard-gateway/
βββ cmd/gateway/ # Gateway entrypoint (Go)
βββ internal/
β βββ cache/ # Response caching
β βββ config/ # Config & hot reload
β βββ database/ # PostgreSQL repository
β βββ plugin/ # Plugin system
β β βββ builtin/ # Built-in plugins (auth, rate-limit, cache, cors, logger)
β βββ proxy/ # Reverse proxy
β βββ ratelimit/ # Rate limiting algorithms
β βββ router/ # Radix tree routing
βββ admin-api/ # Python FastAPI Admin API
βββ admin-ui/ # React Admin Dashboard
β βββ src/
β β βββ api/ # Typed API client layer
β β βββ components/ # UI components (layout, shared, entity forms)
β β βββ hooks/ # TanStack Query hooks
β β βββ pages/ # Route pages (Dashboard, Services, Routes, etc.)
β β βββ lib/ # Utilities (formatters, constants, error parser)
β βββ e2e/ # Playwright e2e tests
β βββ Dockerfile # Multi-stage build (Node -> nginx)
β βββ nginx.conf # SPA serving + API reverse proxy
βββ tests/ # Go test suites + manual scripts
βββ docker-compose.yml # Full development stack (8 services)
βββ schema.sql # Database schema + seed data
πΊοΈ Roadmap
Completed:
- Core Gateway (Proxy, Routing, Config)
- Admin API with full CRUD
- Plugin System
- API Key Authentication
- JWT Authentication
- Rate Limiting (Token Bucket, Sliding Window)
- Response Caching
- Hot Reload
Coming Soon:
- Load Balancing (Round Robin, Weighted, Least Connections)
- Circuit Breaker
- Active Health Checks
- Prometheus Metrics
- Kafka Request Logging
- WebSocket Support
π€ Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
git checkout -b feature/your-feature
make test
git commit -m "feat: your feature"
git push origin feature/your-feature
π License
Apache License 2.0 - see LICENSE for details.
Built for developers who want control without complexity.
β Star this repo if Switchboard helps you!
gvs46
Directories
ΒΆ
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gateway
command
Package main is the entrypoint for the Switchboard API Gateway.
|
Package main is the entrypoint for the Switchboard API Gateway. |
|
internal
|
|
|
cache
Package cache provides response caching functionality for the API Gateway.
|
Package cache provides response caching functionality for the API Gateway. |
|
config
Package config provides application configuration management.
|
Package config provides application configuration management. |
|
database
Package database - Data models
|
Package database - Data models |
|
gateway
Package gateway provides the main gateway logic and config change handling.
|
Package gateway provides the main gateway logic and config change handling. |
|
health
Package health provides health check handlers for the gateway.
|
Package health provides health check handlers for the gateway. |
|
logging
Package logging provides structured logging using zerolog.
|
Package logging provides structured logging using zerolog. |
|
plugin
Package plugin - Chain executor for running plugins in priority order
|
Package plugin - Chain executor for running plugins in priority order |
|
plugin/builtin
Package builtin - API Key Authentication Plugin
|
Package builtin - API Key Authentication Plugin |
|
proxy
Package proxy - Reverse proxy implementation
|
Package proxy - Reverse proxy implementation |
|
ratelimit
Package ratelimit provides rate limiting implementations using Redis.
|
Package ratelimit provides rate limiting implementations using Redis. |
|
router
Package router - Path matching logic using radix tree
|
Package router - Path matching logic using radix tree |