ISP Subscriber Throttling
ISP Subscriber Throttling
Section titled “ISP Subscriber Throttling”This guide explains how RouterOS implements the token bucket algorithm for traffic shaping, how burst parameters interact, and how to build per-subscriber rate limiting for residential and business ISP deployments.
Prerequisites: Queue Types, Simple Queue, Queue Tree.
Token Bucket Algorithm
Section titled “Token Bucket Algorithm”RouterOS queue shaping is based on Hierarchical Token Bucket (HTB). Understanding the underlying model helps you predict queue behaviour under load.
How the token bucket works
Section titled “How the token bucket works”A token bucket controls how much traffic a queue can transmit. Tokens accumulate in the bucket at a steady rate (the configured rate limit) up to a maximum capacity. Each byte transmitted consumes one token. When the bucket is empty, packets must wait until enough tokens accumulate.
Token rate: 10 MbpsBucket capacity: determines how long a burst can last
Time → 0s 1s 2s 3sTokens: FULL → drained → refilling → FULLTraffic: idle → burst → steady → idleRouterOS implementation: averaging window
Section titled “RouterOS implementation: averaging window”RouterOS does not use a classical token bucket with explicit capacity. Instead
it tracks a rolling average rate over the burst-time window:
average_rate = exponential moving average of throughput over burst-time- When
average_rate < burst-threshold→ queue can transmit up toburst-limit - When
average_rate ≥ burst-threshold→ queue is capped atmax-limit - When burst is inactive, rate never exceeds
max-limit
The burst-time window is the averaging period — longer windows mean the router
needs more sustained low-traffic time before burst reactivates.
Parameter mapping to token bucket concepts
Section titled “Parameter mapping to token bucket concepts”| Token Bucket Concept | RouterOS Parameter | Effect |
|---|---|---|
| Token refill rate (normal) | max-limit | Steady-state ceiling |
| Committed Information Rate | limit-at | Guaranteed minimum |
| Bucket capacity / peak rate | burst-limit | Maximum burst speed |
| Bucket fill threshold | burst-threshold | Activates/deactivates burst |
| Averaging window | burst-time | How long the average is measured |
Burst Limit vs Burst Threshold
Section titled “Burst Limit vs Burst Threshold”These two parameters are frequently confused. They serve different roles.
burst-limit — the peak speed
Section titled “burst-limit — the peak speed”burst-limit sets the maximum rate a queue can reach when burst is active.
It is always higher than max-limit. If burst-limit = max-limit, burst has
no visible effect.
burst-limit=20M # queue can burst up to 20 Mbpsmax-limit=10M # normal steady-state cap is 10 Mbpsburst-threshold — the trigger
Section titled “burst-threshold — the trigger”burst-threshold is the average rate at which burst switches off. When the
rolling average exceeds this value, the queue drops from burst-limit back to
max-limit.
burst-threshold=8M # burst deactivates when average rate hits 8 MbpsFor burst to be useful, the threshold must be below max-limit. Otherwise,
normal traffic already exceeds the threshold and burst is permanently inactive.
Rule of thumb: set burst-threshold to 70–85% of max-limit.
Worked example: 10 Mbps plan with burst
Section titled “Worked example: 10 Mbps plan with burst”max-limit=10M # normal capburst-limit=20M # double speed when burstingburst-threshold=8M # 80% of max-limitburst-time=16s # average over 16 secondsBehaviour timeline:
| Phase | Average rate | Effective cap | Duration |
|---|---|---|---|
| Idle then page load | < 8 Mbps | 20 Mbps (burst active) | ~6–8s |
| Sustained download | rising → 8 Mbps | drops to 10 Mbps | — |
| Download continues | ≥ 8 Mbps | 10 Mbps (burst off) | steady |
| Idle again | falls below 8 Mbps | 20 Mbps (burst reactivates) | after ~8s |
Common burst misconfiguration
Section titled “Common burst misconfiguration”| Mistake | Result |
|---|---|
burst-threshold ≥ burst-limit | Burst never activates |
burst-threshold ≤ 0 (or unset) | Burst disabled entirely |
burst-threshold > max-limit | Burst always active — subscriber always at burst-limit |
burst-time too short (e.g., 4s) | Burst cycles on/off rapidly; annoying for TCP |
burst-limit = max-limit | No burst benefit; wastes configuration |
Per-Subscriber Rate Limiting
Section titled “Per-Subscriber Rate Limiting”Method 1: Simple Queue (small deployments, < 200 subscribers)
Section titled “Method 1: Simple Queue (small deployments, < 200 subscribers)”Simple Queue creates one queue entry per subscriber. Suitable when subscriber counts are small and IP addresses are static or predictable.
Basic subscriber queue:
/queue simpleadd name=sub-192.168.1.10 target=192.168.1.10/32 \ max-limit=10M/5M \ burst-limit=20M/10M \ burst-threshold=8M/4M \ burst-time=16s/16s \ comment="Residential 10M/5M"Applying to a range of subscribers with a catch-all:
/queue simple# Individual subscriber queues firstadd name=sub-10 target=192.168.1.10/32 max-limit=20M/10M \ burst-limit=40M/20M burst-threshold=16M/8M burst-time=16s/16sadd name=sub-11 target=192.168.1.11/32 max-limit=10M/5M \ burst-limit=20M/10M burst-threshold=8M/4M burst-time=16s/16s
# Catch-all for unmanaged IPs — throttle hardadd name=unmanaged target=192.168.1.0/24 max-limit=2M/1MOrder matters: RouterOS evaluates Simple Queue entries top-to-bottom. Place specific host queues before subnet catch-alls.
Method 2: Queue Tree + PCQ (large deployments)
Section titled “Method 2: Queue Tree + PCQ (large deployments)”PCQ (Per Connection Queue) creates dynamic per-IP sub-queues automatically. No per-subscriber queue entries needed — one queue rule handles all subscribers.
Step 1 — Define PCQ queue types:
/queue typeadd name=pcq-sub-down kind=pcq \ pcq-classifier=dst-address \ pcq-rate=10M \ pcq-limit=100
add name=pcq-sub-up kind=pcq \ pcq-classifier=src-address \ pcq-rate=5M \ pcq-limit=100Step 2 — Mark traffic in Mangle:
/ip firewall mangle# Download: mark packets destined for LANadd chain=forward action=mark-packet new-packet-mark=sub-down passthrough=no \ out-interface=bridge-LAN
# Upload: mark packets leaving LANadd chain=forward action=mark-packet new-packet-mark=sub-up passthrough=no \ in-interface=bridge-LANStep 3 — Attach PCQ queues to Queue Tree:
/queue treeadd name=Subscriber-Down parent=global packet-mark=sub-down \ queue=pcq-sub-down max-limit=1000M
add name=Subscriber-Up parent=global packet-mark=sub-up \ queue=pcq-sub-up max-limit=500MEach unique dst-address (download) or src-address (upload) gets its own
dynamic sub-queue capped at 10 Mbps down / 5 Mbps up.
Real-World ISP Examples
Section titled “Real-World ISP Examples”Example 1: Residential plan — 25M/10M with short burst
Section titled “Example 1: Residential plan — 25M/10M with short burst”Standard residential broadband. Give subscribers a fast burst for page loads and small downloads, then throttle to the plan rate.
/queue simpleadd name=residential-template target=192.168.100.0/24 \ max-limit=25M/10M \ burst-limit=50M/20M \ burst-threshold=20M/8M \ burst-time=8s/8s \ comment="25M/10M residential — burst 50M/20M for 8s"Short burst-time=8s means burst deactivates quickly after a download starts —
subscribers get a fast start but not sustained double-speed for long transfers.
Example 2: Business plan — 50M/25M with guaranteed minimum
Section titled “Example 2: Business plan — 50M/25M with guaranteed minimum”Business subscribers need predictable performance. Use limit-at to guarantee
a minimum even when the link is congested.
/queue tree# Mangle marks business traffic as biz-down / biz-upadd name=Business-Down parent=global packet-mark=biz-down \ limit-at=20M max-limit=50M \ burst-limit=75M burst-threshold=40M burst-time=30s \ priority=3
add name=Business-Up parent=global packet-mark=biz-up \ limit-at=10M max-limit=25M \ burst-limit=40M burst-threshold=20M burst-time=30s \ priority=3limit-at=20M ensures the queue receives at least 20 Mbps when congestion
causes parent bandwidth contention. priority=3 is higher than residential (6),
so business traffic is scheduled first.
Example 3: Throttled / over-quota subscribers
Section titled “Example 3: Throttled / over-quota subscribers”After a subscriber exhausts a monthly data quota, reduce them to a low speed without disconnecting. Use address lists to mark throttled subscribers.
# Add to throttle list via script or manual action/ip firewall address-listadd list=throttled address=192.168.1.55 comment="quota exceeded 2026-03-23"
# Mangle: mark throttled subscriber traffic/ip firewall mangleadd chain=forward action=mark-connection \ new-connection-mark=throttled-conn passthrough=yes \ src-address-list=throttledadd chain=forward action=mark-connection \ new-connection-mark=throttled-conn passthrough=yes \ dst-address-list=throttledadd chain=forward action=mark-packet \ new-packet-mark=throttled passthrough=no \ connection-mark=throttled-conn
# Queue: cap throttled subscribers at 1M/512k/queue treeadd name=Throttled parent=global packet-mark=throttled \ max-limit=1M priority=8 comment="over-quota throttle"To restore a subscriber, remove them from the address list:
/ip firewall address-list remove [find list=throttled address=192.168.1.55]Example 4: Time-based throttling (night vs day rates)
Section titled “Example 4: Time-based throttling (night vs day rates)”Use a script with scheduler to swap queue limits for off-peak hours.
# Script: apply night-rate (uncapped, or higher burst)/system scriptadd name=apply-night-rate source={ /queue simple set [find name=residential-template] \ max-limit=50M/25M burst-limit=100M/50M burst-threshold=40M/20M}
# Script: apply day-rate (normal plan limits)add name=apply-day-rate source={ /queue simple set [find name=residential-template] \ max-limit=25M/10M burst-limit=50M/20M burst-threshold=20M/8M}
/system scheduleradd name=night-rate on-event=apply-night-rate start-time=22:00:00 interval=1dadd name=day-rate on-event=apply-day-rate start-time=06:00:00 interval=1dChoosing Simple Queue vs Queue Tree for Subscribers
Section titled “Choosing Simple Queue vs Queue Tree for Subscribers”| Factor | Simple Queue | Queue Tree + PCQ |
|---|---|---|
| Subscriber count | < 200 | 200+ |
| Dynamic IPs (DHCP) | Manual or script-driven | Automatic via PCQ classifier |
| Per-subscriber burst | Per-entry configuration | PCQ does not support burst per sub-queue |
| Hierarchy / tiers | Flat only | Full HTB hierarchy |
| Visibility | Per-queue stats per subscriber | Aggregate stats; per-IP via /tool torch |
For large deployments with dynamic IPs, combine Queue Tree + PCQ for the rate cap and Mangle + address-lists for tier classification.
Monitoring
Section titled “Monitoring”# Check queue throughput and drops in real time/queue simple print stats
# Watch per-subscriber PCQ sub-queues/queue tree print stats
# Identify top talkers on an interface/tool torch interface=ether1 src-address=0.0.0.0/0 duration=10Troubleshooting
Section titled “Troubleshooting”Subscriber exceeds max-limit consistently
- Verify FastTrack is not bypassing the queue. FastTrack-ed connections skip queue processing. Either disable FastTrack on that interface or add a Mangle passthrough rule for subscribers before the FastTrack rule.
Burst never activates
- Check
burst-threshold < max-limit. If threshold ≥ max-limit, burst stays off. - Confirm
burst-limit > max-limit. - Verify the subscriber’s current average rate is below
burst-thresholdusing/queue simple print stats— look at theratecolumn.
PCQ appears to give unequal shares
- Confirm
pcq-classifier=dst-addressfor download andsrc-addressfor upload. Reversed classifiers break sub-queue creation. - Connections behind NAT share one source IP — PCQ sees them as one subscriber. For NAT environments, use Simple Queue per subscriber address instead.
Throttle queue not affecting subscriber
- Check Mangle rule order. Connection-mark rules must fire before the existing
mark-packet rules (or use
passthrough=yesand chain order carefully). - Confirm packet-mark name matches between Mangle and Queue Tree exactly (case-sensitive).
Related Resources
Section titled “Related Resources”- Burst Settings — parameter reference and algorithm detail
- Queue Tree — HTB hierarchy fundamentals
- PCQ Example — PCQ configuration patterns
- HTB ISP Tiered Bandwidth — tiered Bronze/Silver/Gold ISP design
- Simple Queue — per-client queue configuration