How mailgun/gubernator works
Purpose and Entry Points
Gubernator is a Go-based, distributed, stateless rate-limiting service and embeddable library. Clients supply rate-limit configuration on each request; nodes keep active bucket state in memory and distribute ownership across a cluster. The primary server binary is cmd/gubernator/main.go; related operational binaries are cluster tooling in cmd/gubernator-cluster/main.go, a CLI in cmd/gubernator-cli/main.go, and health checking in cmd/healthcheck/main.go.
Public API and Transport Boundary
The API contract is defined in gubernator.proto, with generated Go gRPC and HTTP/gRPC-Gateway bindings in gubernator_grpc.pb.go and gubernator.pb.gw.go. gubernator.go implements public rate-limit and health operations. Clients can use gRPC directly or HTTP endpoints translated by grpc-gateway; generated Python bindings under python/gubernator/ support Python consumers.
Request Routing and Cluster Ownership
Each rate-limit key is assigned to a cluster member via consistent/replicated hashing, so requests reach a single coordinating owner:
• replicated_hash.go
• region_picker.go
• cluster/cluster.go
A receiving node evaluates locally owned limits or forwards work to the owner through peer RPC clients in peer_client.go. Peer protocol definitions and generated stubs are peers.proto and peers_grpc.pb.go. This ownership boundary lets nodes scale horizontally without Redis or memcached.
Rate-Limit Evaluation and State
Core evaluation selects token-bucket or leaky-bucket behavior and handles request options such as batching, global behavior, Gregorian intervals, reset, and draining. The algorithm and service orchestration are centered in:
• algorithms.go
• gubernator.go
• interval.go
In-memory state is maintained through cache abstractions in cache.go and lrucache.go. The service is normally diskless, but store.go exposes Loader/Store interfaces for embedders that need startup/shutdown or ongoing persistence.
Batching, Replication, and Global Limits
Workers batch compatible peer-bound requests for throughput, then dispatch and reconcile responses; this is implemented in workers.go and coordinated from gubernator.go. Optional globally distributed rate limits use eventually consistent sharing rather than strict single-node handling, with global coordination in global.go. These modes trade latency, throughput, and consistency while retaining the same client API.
Membership and Discovery
Cluster membership is abstracted behind discovery implementations. Nodes can discover peers from etcd, Kubernetes, or round-robin DNS:
• etcd.go
• kubernetes.go
• dns.go
memberlist.go and daemon.go manage peer lifecycle and server operation. Configuration is environment-driven or loaded from a config file via config.go and flags.go; networking and TLS boundaries are handled by net.go and tls.go.
Runtime, Deployment, and Observability
The service runs as a Go process, containerized by Dockerfile, and can be deployed standalone, as a sidecar, or embedded as a library. Kubernetes deployment artifacts include contrib/k8s-deployment.yaml and Helm templates in contrib/charts/gubernator/templates/deployment.yaml; an AWS ECS service-discovery example is under contrib/aws-ecs-service-discovery-deployment/. Prometheus metrics and OpenTelemetry instrumentation are represented by grpc_stats.go, docs/prometheus.md, and docs/tracing.md.
Main entry points: gubernator.go Rate-limit service · gubernator.pb.gw.go gRPC / HTTP transport · main.go Server binary · replicated_hash.go Key ownership
Components 18
API & Clients
- gRPC / HTTP transport · Serves gRPC and grpc-gateway HTTP requests.
gubernator.pb.gw.go - Rate-limit API contract
gubernator.proto - Python bindings
Rate Limit Service
- Rate-limit service · Implements public rate-limit and health operations.
gubernator.go - Bucket algorithms · Evaluates token and leaky buckets plus request options.
algorithms.go - Interval handling · Supports Gregorian intervals and reset timing.
interval.go - In-memory bucket state · Holds active rate-limit buckets on each node.
lrucache.go - Optional persistence · Loader and Store interfaces allow state persistence.
store.go - Peer request batching · Batches compatible remote requests and reconciles responses.
workers.go - Global limits · Shares distributed global-limit state with eventual consistency.
global.go
Cluster & Ownership
- Key ownership · Maps each rate-limit key to a coordinating member.
replicated_hash.go - Peer RPC client · Forwards work to the owning node.
peer_client.go - Membership lifecycle · Maintains peers and server lifecycle.
memberlist.go - Discovery providers · Supports etcd, Kubernetes, and DNS discovery.
etcd.go
Runtime & Operations
- Server binary
cmd/gubernator/main.go - Configuration · Environment and file-driven server configuration.
config.go - Metrics & tracing · Exports Prometheus metrics and OpenTelemetry signals.
grpc_stats.go - Kubernetes deployment
contrib/k8s-deployment.yaml
Connections 19
- Rate-limit API contract → gRPC / HTTP transport: generates bindings
- Python bindings → gRPC / HTTP transport: calls
- Server binary → Configuration: loads
- Server binary → gRPC / HTTP transport: starts
- gRPC / HTTP transport → Rate-limit service: dispatches
- Rate-limit service → Bucket algorithms: evaluates through
- Bucket algorithms → Interval handling: uses
- Rate-limit service → In-memory bucket state: reads and updates
- Optional persistence → In-memory bucket state: loads or stores
- Rate-limit service → Key ownership: routes key by
- Key ownership → Peer RPC client: selects remote owner
- Rate-limit service → Peer request batching: queues remote work
- Peer request batching → Peer RPC client: dispatches batches
- Rate-limit service → Global limits: coordinates optional limits
- Membership lifecycle → Key ownership: supplies member set
- Discovery providers → Membership lifecycle: finds peers
- Server binary → Membership lifecycle: runs cluster node
- gRPC / HTTP transport → Metrics & tracing: emits telemetry
- Kubernetes deployment → Server binary: deploys