Bandwidth limiting middleware plugin for Traefik that provides fine-grained control over data transfer rates. This plugin supports per-backend and per-client IP rate limiting with automatic memory management and persistent state storage.
See the forums for further discussion here
# Add to your Traefik static configurationexperimental:plugins:bandwidthlimiter:moduleName: github.com/hhftechnology/bandwidthlimiterversion: v1.0.0
# dynamic.ymlhttp:middlewares:my-bandwidth-limiter:plugin:bandwidthlimiter:defaultLimit: 1048576 # 1 MB/sburstSize: 5242880 # 5 MB burst
http:routers:my-service:rule: "Host(`example.com`)"service: my-servicemiddlewares:- my-bandwidth-limiter
| Parameter | Type | Default | Description |
|---|---|---|---|
defaultLimit | int64 | 1048576 | Default bandwidth limit in bytes per second |
burstSize | int64 | 10x defaultLimit | Maximum burst size in bytes |
backendLimits | map[string]int64 | {} | Backend-specific limits |
clientLimits | map[string]int64 | {} | Client IP-specific limits |
| Parameter | Type | Default | Description |
|---|---|---|---|
bucketMaxAge | int64 | 3600 | Maximum age of unused buckets before cleanup (seconds) |
cleanupInterval | int64 | 300 | Interval between cleanup runs (seconds) |
persistenceFile | string | "" | File path for persistent storage (disabled if empty) |
saveInterval | int64 | 60 | Interval between saves to persistence file (seconds) |
http:middlewares:simple-limiter:plugin:bandwidthlimiter:defaultLimit: 524288 # 512 KB/sburstSize: 2621440 # 2.5 MB burst
http:middlewares:backend-limiter:plugin:bandwidthlimiter:defaultLimit: 1048576 # 1 MB/s defaultbackendLimits:api.example.com: 2097152 # 2 MB/s for APIstatic.example.com: 524288 # 512 KB/s for static contentvideo.example.com: 10485760 # 10 MB/s for video streaming
http:middlewares:client-limiter:plugin:bandwidthlimiter:defaultLimit: 524288 # 512 KB/s for regular usersclientLimits:203.0.113.100: 5242880 # 5 MB/s for premium client203.0.113.101: 2097152 # 2 MB/s for business client"2001:db8::1": 10485760 # 10 MB/s for IPv6 client
http:middlewares:production-limiter:plugin:bandwidthlimiter:# Basic limitsdefaultLimit: 1048576burstSize: 5242880# Memory managementbucketMaxAge: 1800 # 30 minutescleanupInterval: 300 # 5 minutes# PersistencepersistenceFile: "/plugins-storage/bandwidth-state.json"saveInterval: 60 # 1 minute# Advanced limitsbackendLimits:api.example.com: 2097152critical.example.com: 10485760clientLimits:192.168.1.100: 10485760"fd00::1": 5242880
Quickly convert between human-readable speeds and configuration values:
| Speed | Configuration Value |
|---|---|
| 128 Kbps | 16384 |
| 256 Kbps | 32768 |
| 512 Kbps | 65536 |
| 1 Mbps | 131072 |
| 2 Mbps | 262144 |
| 5 Mbps | 655360 |
| 10 Mbps | 1310720 |
| 25 Mbps | 3276800 |
| 50 Mbps | 6553600 |
| 100 Mbps | 13107200 |
Formula: Mbps × 131,072 = bytes/second
Configure cleanup based on your traffic patterns:
High-Traffic Sites:
bandwidthlimiter:bucketMaxAge: 600 # 10 minutescleanupInterval: 60 # 1 minute
Medium-Traffic Sites:
bandwidthlimiter:bucketMaxAge: 1800 # 30 minutescleanupInterval: 300 # 5 minutes
Low-Traffic Sites:
bandwidthlimiter:bucketMaxAge: 3600 # 1 hourcleanupInterval: 600 # 10 minutes
Critical Applications:
bandwidthlimiter:persistenceFile: "/plugins-storage/bandwidth-critical.json"saveInterval: 30 # Save every 30 seconds
Standard Applications:
bandwidthlimiter:persistenceFile: "/plugins-storage/bandwidth-standard.json"saveInterval: 60 # Save every minute
Development/Testing:
bandwidthlimiter:persistenceFile: "/tmp/bandwidth-dev.json"saveInterval: 300 # Save every 5 minutes
version: '3.8'services:traefik:image: traefik:latestvolumes:- /var/run/docker.sock:/var/run/docker.sock:ro- ./traefik.yml:/etc/traefik/traefik.yml:ro- ./dynamic.yml:/etc/traefik/dynamic.yml:ro- ./traefik/plugins-storage:/plugins-storage:rw- ./traefik/plugins-storage:/plugins-local:rwports:- "80:80"- "443:443"
apiVersion: v1kind: ConfigMapmetadata:name: traefik-bandwidth-configdata:dynamic.yml: |http:middlewares:bandwidth-limiter:plugin:bandwidthlimiter:persistenceFile: "/plugins-storage/bandwidth-state.json"defaultLimit: 1048576---apiVersion: v1kind: PersistentVolumeClaimmetadata:name: traefik-bandwidth-pvcspec:accessModes:- ReadWriteOnceresources:requests:storage: 100Mi
# Create directoriessudo mkdir -p /plugins-storagesudo chown traefik:traefik /plugins-storagesudo chmod 755 /plugins-storage# Traefik configurationcat > /etc/traefik/dynamic.yml << EOFhttp:middlewares:bandwidth-limiter:plugin:bandwidthlimiter:persistenceFile: "/plugins-storage/bandwidth-state.json"defaultLimit: 1048576EOF
Watch for these log messages:
# Successful operations
INFO: Cleanup removed 150 unused buckets (kept 500 active buckets)
INFO: Saved 500 buckets to /plugins-storage/bandwidth-state.json
INFO: Loaded 450 buckets from /plugins-storage/bandwidth-state.json
# Potential issues
WARNING: Failed to save buckets: disk full
ERROR: Failed to load persisted buckets: file corrupt
#!/bin/bash# bandwidth-monitor.sh# Check memory usageecho "Memory usage:"ps aux | grep traefik | grep -v grep | awk '{print $6/1024 " MB"}'# Check file sizeecho "Persistence file size:"du -h /plugins-storage/bandwidth-state.json# Count active connectionsecho "Active bandwidth buckets:"grep -o '"key":' /plugins-storage/bandwidth-state.json | wc -l# Recent cleanup activityecho "Recent cleanup events:"journalctl -u traefik --since "1 hour ago" | grep "Cleanup removed"
High Memory Usage
bucketMaxAgecleanupInterval)Slow Response Times
burstSize for initial data transferdefaultLimit valuesMissing Rate Limits After Restart
persistenceFile path is correctFile Permission Errors
# Fix ownership and permissionssudo chown traefik:traefik /plugins-storage/bandwidth-state.jsonsudo chmod 644 /plugins-storage/bandwidth-state.json
Enable detailed logging in Traefik:
# traefik.ymllog:level: DEBUG# Or via command line--log.level=DEBUG
For multiple Traefik instances:
# Instance 1bandwidthlimiter:persistenceFile: "/shared/storage/bandwidth-node1.json"# Instance 2bandwidthlimiter:persistenceFile: "/shared/storage/bandwidth-node2.json"# Use external synchronization for shared state
#!/bin/bash# bandwidth-backup.sh# Create timestamped backupcp /plugins-storage/bandwidth-state.json \/backup/bandwidth-$(date +%Y%m%d-%H%M%S).json# Keep only last 30 days of backupsfind /backup -name "bandwidth-*.json" -mtime +30 -delete# Verify backup integrityif ! jq . /backup/bandwidth-latest.json >/dev/null 2>&1; thenecho "ERROR: Backup file is corrupted"exit 1fi
Test configurations locally:
# development.ymlhttp:middlewares:dev-bandwidth:plugin:bandwidthlimiter:# Fast cleanup for testingbucketMaxAge: 300cleanupInterval: 60# Local persistencepersistenceFile: "/tmp/bandwidth-dev.json"# Test limitsdefaultLimit: 65536 # 64 KB/sclientLimits:127.0.0.1: 1048576 # 1 MB/s for localhost
Bucket Management
bucketMaxAge (1-2 hours)Persistence Settings
Resource Planning
Typical performance characteristics:
| Metric | Value |
|---|---|
| Request overhead | ~1-2ms |
| Cleanup duration | ~50-100ms per 1000 buckets |
| Save operation | ~100-200ms per 1000 buckets |
| Memory per bucket | ~200 bytes |
| File size per bucket | ~200 bytes (JSON) |
When reporting issues, include:
We welcome contributions for:
This plugin is licensed under the Apache 2.0 License. See LICENSE file for details.
# Query bucket statesjq '.[] | select(.key | contains("192.168.1.100"))' /plugins-storage/bandwidth-state.json# Count buckets by client IPjq -r '.[].key' /plugins-storage/bandwidth-state.json | cut -d: -f1 | sort | uniq -c# Find high-usage clientsjq '.[] | {key, tokens, limit} | select(.tokens < .limit * 0.1)' /plugins-storage/bandwidth-state.json
Prometheus Metrics (Custom Endpoint)
// Add to custom metrics endpointtype BandwidthMetrics struct {ActiveBuckets int64TotalRequests int64BytesTransferred int64}
Grafana Dashboard Query
# Active bandwidth bucketstraefik_bandwidth_active_buckets# Bandwidth utilizationrate(traefik_bandwidth_bytes_transferred[5m])
This comprehensive plugin provides enterprise-grade bandwidth limiting capabilities for Traefik, combining ease of use with advanced features for production environments. Start with the basic configuration and gradually enable advanced features as your needs grow.