Deployment and Ops: Docker Compose, Kubernetes, Helm
This guide shows how to run the rate limiter with Redis and MongoDB in Docker Compose or Kubernetes, and how to size Redis, MongoDB, and TTL for stable production behavior.
Prerequisites
- A built rate-limiter service image (local or in a registry)
- Redis 7.x and MongoDB 6.x or 7.x (managed or self-hosted)
- Access to your
application.yamlfor rate-limit settings - Network access between the app and Redis/MongoDB
Docker Compose deployment
Step 1: Build the application image
If you run the service from source, build a local image so Compose can start the app container.
docker build -t rate-limiter-app:local .This assumes you run the command from the backend project that contains the Dockerfile. If you already publish an image, skip this step and set the app.image value in the compose file to your registry image.
Step 2: Create a compose.yaml
Use this minimal stack for Redis, MongoDB, and the rate limiter.
version: "3.8"
services:
redis:
image: redis:7.2
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: ["redis-server", "--appendonly", "yes"]
mongodb:
image: mongo:7
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: rate_limiter_db
volumes:
- mongo_data:/data/db
app:
image: rate-limiter-app:local
ports:
- "8080:8080"
environment:
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: "6379"
SPRING_DATA_MONGODB_URI: mongodb://admin:password@mongodb:27017/rate_limiter_db
depends_on:
- redis
- mongodb
volumes:
redis_data:
mongo_data:The redis service enables AOF persistence for durability. mongodb stores persistent overrides from /api/config/v2. The app service reads Redis and MongoDB connection settings from environment variables. Change the MongoDB credentials if you run this in any shared environment.
Step 3: Start the stack
docker compose up -dThis brings up Redis, MongoDB, and the rate limiter. If the app cannot connect, check the service names and environment variables first.
Step 4: Verify health and headers
curl -s http://localhost:8080/actuator/health
curl -i http://localhost:8080/api/testThe health endpoint should report status: UP with redis and db components. The rate-limited endpoint should include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-ResetOn headers.
Kubernetes deployment
Step 1: Create a deployment and service
This example uses environment variables for Redis and MongoDB connectivity. Replace rate-limiter-app:local with your registry image.
apiVersion: v1
kind: Secret
metadata:
name: rate-limiter-secrets
type: Opaque
stringData:
MONGO_URI: mongodb://admin:password@mongodb:27017/rate_limiter_db
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rate-limiter
spec:
replicas: 2
selector:
matchLabels:
app: rate-limiter
template:
metadata:
labels:
app: rate-limiter
spec:
containers:
- name: rate-limiter
image: rate-limiter-app:local
ports:
- containerPort: 8080
env:
- name: SPRING_REDIS_HOST
value: redis
- name: SPRING_REDIS_PORT
value: "6379"
- name: SPRING_DATA_MONGODB_URI
valueFrom:
secretKeyRef:
name: rate-limiter-secrets
key: MONGO_URI
---
apiVersion: v1
kind: Service
metadata:
name: rate-limiter
spec:
selector:
app: rate-limiter
ports:
- port: 8080
targetPort: 8080The Secret keeps your MongoDB URI out of the Deployment spec. The Deployment runs two replicas and uses service discovery for Redis and MongoDB. If you use managed Redis or MongoDB, set SPRING_REDIS_HOST and SPRING_DATA_MONGODB_URI to those endpoints instead.
Step 2: Apply and verify
kubectl apply -f rate-limiter.yaml
kubectl port-forward svc/rate-limiter 8080:8080After port-forwarding, hit http://localhost:8080/actuator/health and a rate-limited endpoint to verify headers and connectivity.
Helm packaging
Step 1: Create values.yaml
If you package the service as a Helm chart, these values cover the core settings.
image:
repository: rate-limiter-app
tag: "1.0.0"
env:
SPRING_REDIS_HOST: redis-master
SPRING_REDIS_PORT: "6379"
SPRING_DATA_MONGODB_URI: mongodb://admin:password@mongo:27017/rate_limiter_db
rateLimit:
redis:
ttl: 600000Map image.repository and image.tag to your registry. The env values pass Redis and MongoDB configuration into the container. The rateLimit.redis.ttl value should be wired into your application.yaml or ConfigMap, depending on how your chart templates configuration.
Step 2: Install or upgrade
helm upgrade --install rate-limiter ./chart -f values.yamlThis command assumes a chart at ./chart. If your chart lives elsewhere, adjust the path or use a chart repository URL.
Redis and Mongo sizing and TTL guidance
Redis is the primary limiter for throughput and memory. The numbers below are approximate and based on the data structures used by each algorithm.
| Algorithm | Redis ops per request | Approx Redis state per IP + endpoint | Example for 10k IPs |
|---|---|---|---|
| Token Bucket | 3 | ~150 bytes | ~1.5 MB |
| Leaky Bucket | 3 | ~150 bytes | ~1.5 MB |
| Fixed Counter | 3 | ~50 bytes | ~0.5 MB |
| Sliding Window Log | 4 | ~50 bytes per request in window | ~50 MB at 100 req/min |
Sliding Window Log stores one entry per request in the rolling window. Memory scales with request volume, not just with number of clients. If you allow large limits (thousands per minute), expect high Redis memory use and consider Token Bucket or Fixed Counter for those endpoints.
MongoDB size depends on the number of override documents you store. Each document includes IP, endpoint, tier, algorithm, parameters, and timestamps. Expect small documents, but measure actual size with db.rate_limit_config.stats() in your environment.
TTL guidance depends on the algorithm:
rate-limit:
redis:
ttl: 600000Token Bucket and Leaky Bucket use this TTL to expire idle keys. Fixed Counter uses windowSize as its TTL. Sliding Window Log sets TTL to 2 * windowTime inside the Lua script to ensure cleanup after the last request. A common starting point for rate-limit.redis.ttl is 10 minutes; increase it if your clients are idle for long periods and you want to preserve state.
What to verify
You should have a running service that can reach Redis and MongoDB, and you should see X-RateLimit-* headers on rate-limited endpoints. Verify health via /actuator/health, verify limit behavior with a simple curl loop, and confirm that overrides stored in MongoDB affect matching requests.