If you've outgrown Simple Queues, it's time to learn Queue Trees. While Simple Queues match traffic by IP address and apply a flat speed limit, Queue Trees let you build a hierarchy – a parent queue representing your total WAN bandwidth, with child queues for different customers, services, or priorities. Combined with mangle rules that mark traffic, you can guarantee VoIP quality, burst web browsing, and throttle bulk downloads – all simultaneously.
Why Queue Trees Over Simple Queues?
- Hierarchical shaping (HTB) – Parent queues define total bandwidth; children share it with guaranteed minimums and flexible maximums.
- Per‑protocol prioritization – Mark VoIP, DNS, or gaming traffic and give it priority over downloads.
- Scalability – Better suited for ISPs with hundreds of users.
- Separate upload/download trees – Full control over each direction independently.
- Works with FastTrack – Unlike Simple Queues, Queue Trees using interface-based parents work alongside FastTrack in certain configurations.
Prerequisites
- A MikroTik router with basic internet access configured.
- Understanding of your internet speed (e.g., 100 Mbps down / 20 Mbps up).
- WinBox or SSH access.
- Familiarity with Simple Queues basics (recommended but not required).
Key Concepts
HTB (Hierarchical Token Bucket)
HTB is the queuing discipline MikroTik uses in Queue Trees. Think of it like a company budget:
- Parent queue = Total company budget (your WAN speed).
- Child queues = Department budgets. Each has a guaranteed minimum (limit-at) and a maximum ceiling (max-limit).
- When a department doesn't use its budget, other departments can borrow the excess.
- Priority (1=highest, 8=lowest) determines who gets bandwidth first when the parent is full.
Mangle Marks
Queue Trees don't match traffic by IP like Simple Queues. Instead, you first mark traffic in the firewall mangle table, then the Queue Tree matches packets by their mark.
- Connection mark – Marks an entire connection (all packets). Used for per-user identification.
- Packet mark – Marks individual packets. Used by Queue Trees to apply shaping.
Typical flow: Mangle marks connections by source/destination IP → then marks packets within those connections → Queue Tree matches the packet marks.
Step 1: Mark Traffic with Mangle Rules
We'll create marks for download and upload traffic. This example uses a customer IP (192.168.88.100).
1.1 Mark connections from/to the customer
/ip firewall mangle add chain=forward src-address=192.168.88.100 action=mark-connection new-connection-mark=customer1-conn passthrough=yes comment="Customer1 connection"
/ip firewall mangle add chain=forward dst-address=192.168.88.100 action=mark-connection new-connection-mark=customer1-conn passthrough=yes
1.2 Mark packets for download (traffic going TO the customer)
/ip firewall mangle add chain=forward connection-mark=customer1-conn dst-address=192.168.88.100 action=mark-packet new-packet-mark=customer1-down passthrough=no comment="Customer1 download"
1.3 Mark packets for upload (traffic coming FROM the customer)
/ip firewall mangle add chain=forward connection-mark=customer1-conn src-address=192.168.88.100 action=mark-packet new-packet-mark=customer1-up passthrough=no comment="Customer1 upload"
WinBox: IP → Firewall → Mangle → Add New for each rule.
Step 2: Create Parent Queues (Total WAN Bandwidth)
Parent queues represent your total available bandwidth. You need two – one for download, one for upload.
/queue tree add name=total-download parent=global max-limit=95M comment="Total WAN download"
/queue tree add name=total-upload parent=global max-limit=18M comment="Total WAN upload"
Important: Set max-limit slightly below your actual WAN speed (e.g., 95M instead of 100M). This prevents bufferbloat – if you queue at the exact WAN speed, your ISP's equipment will also queue, causing double buffering and latency spikes.
Note: parent=global means this queue applies to all traffic globally. You can also use parent=ether1 (your WAN interface) for download and parent=bridge-local (your LAN interface) for upload, depending on your topology.
Step 3: Create Child Queues (Per‑Customer)
Each customer gets a child queue under the parent, matched by their packet mark.
/queue tree add name=customer1-down parent=total-download packet-mark=customer1-down limit-at=5M max-limit=20M priority=4 comment="Customer1 download"
/queue tree add name=customer1-up parent=total-upload packet-mark=customer1-up limit-at=2M max-limit=5M priority=4 comment="Customer1 upload"
What this means:
limit-at=5M– Guaranteed 5 Mbps download, even when the network is congested.max-limit=20M– Can burst up to 20 Mbps when spare bandwidth is available.priority=4– Medium priority (1=highest, 8=lowest).
Step 4: Add Priority Queues for Critical Traffic
VoIP, DNS, and gaming traffic should get priority over bulk downloads.
4.1 Mark VoIP traffic (SIP + RTP)
/ip firewall mangle add chain=forward protocol=udp dst-port=5060-5061 action=mark-packet new-packet-mark=voip-traffic passthrough=no comment="SIP signaling"
/ip firewall mangle add chain=forward protocol=udp dst-port=10000-20000 action=mark-packet new-packet-mark=voip-traffic passthrough=no comment="RTP media"
4.2 Mark DNS traffic
/ip firewall mangle add chain=forward protocol=udp dst-port=53 action=mark-packet new-packet-mark=dns-traffic passthrough=no comment="DNS queries"
4.3 Create priority child queues
/queue tree add name=voip-priority parent=total-download packet-mark=voip-traffic limit-at=2M max-limit=5M priority=1 comment="VoIP highest priority"
/queue tree add name=dns-priority parent=total-download packet-mark=dns-traffic limit-at=1M max-limit=5M priority=1 comment="DNS highest priority"
Priority 1 means these queues are served first. Even when the network is saturated, VoIP and DNS will get their guaranteed bandwidth.
Step 5: PCQ with Queue Trees (Dynamic Per‑IP Shaping)
Instead of creating individual mangle rules and queues for every customer, use PCQ (Per Connection Queue) to dynamically allocate bandwidth per IP.
5.1 Create PCQ queue types
/queue type add name=pcq-download-10M kind=pcq pcq-rate=10M pcq-classifier=dst-address
/queue type add name=pcq-upload-3M kind=pcq pcq-rate=3M pcq-classifier=src-address
5.2 Mark all customer traffic
/ip firewall mangle add chain=forward src-address=192.168.88.0/24 action=mark-packet new-packet-mark=all-up passthrough=no comment="All upload"
/ip firewall mangle add chain=forward dst-address=192.168.88.0/24 action=mark-packet new-packet-mark=all-down passthrough=no comment="All download"
5.3 Create Queue Tree entries with PCQ types
/queue tree add name=pcq-customers-down parent=total-download packet-mark=all-down queue=pcq-download-10M comment="PCQ 10M per customer download"
/queue tree add name=pcq-customers-up parent=total-upload packet-mark=all-up queue=pcq-upload-3M comment="PCQ 3M per customer upload"
Now every IP in 192.168.88.0/24 automatically gets 10M down / 3M up, all sharing the parent's total bandwidth. No individual mangle rules needed.
Step 6: Real‑World ISP Example (3 Tiers)
Suppose you have a 100 Mbps WAN and three customer tiers:
| Tier | Guaranteed Down | Max Down | Guaranteed Up | Max Up | Priority |
|---|---|---|---|---|---|
| Premium | 20M | 50M | 10M | 20M | 2 |
| Standard | 10M | 30M | 5M | 10M | 4 |
| Basic | 5M | 15M | 2M | 5M | 6 |
Complete script for this ISP setup:
# ============================================
# Queue Tree ISP Setup – 3 Tiers
# WAN: 100M down / 20M up
# ============================================
# --- Parent queues ---
/queue tree add name=total-download parent=global max-limit=95M
/queue tree add name=total-upload parent=global max-limit=18M
# --- PCQ types per tier ---
/queue type add name=pcq-premium-down kind=pcq pcq-rate=50M pcq-classifier=dst-address
/queue type add name=pcq-premium-up kind=pcq pcq-rate=20M pcq-classifier=src-address
/queue type add name=pcq-standard-down kind=pcq pcq-rate=30M pcq-classifier=dst-address
/queue type add name=pcq-standard-up kind=pcq pcq-rate=10M pcq-classifier=src-address
/queue type add name=pcq-basic-down kind=pcq pcq-rate=15M pcq-classifier=dst-address
/queue type add name=pcq-basic-up kind=pcq pcq-rate=5M pcq-classifier=src-address
# --- Address lists per tier ---
/ip firewall address-list add list=tier-premium address=10.10.0.10 comment="Premium user"
/ip firewall address-list add list=tier-premium address=10.10.0.11
/ip firewall address-list add list=tier-standard address=10.10.0.20
/ip firewall address-list add list=tier-standard address=10.10.0.21
/ip firewall address-list add list=tier-basic address=10.10.0.30
/ip firewall address-list add list=tier-basic address=10.10.0.31
# --- Mangle marks per tier ---
/ip firewall mangle add chain=forward dst-address-list=tier-premium action=mark-packet new-packet-mark=premium-down passthrough=no
/ip firewall mangle add chain=forward src-address-list=tier-premium action=mark-packet new-packet-mark=premium-up passthrough=no
/ip firewall mangle add chain=forward dst-address-list=tier-standard action=mark-packet new-packet-mark=standard-down passthrough=no
/ip firewall mangle add chain=forward src-address-list=tier-standard action=mark-packet new-packet-mark=standard-up passthrough=no
/ip firewall mangle add chain=forward dst-address-list=tier-basic action=mark-packet new-packet-mark=basic-down passthrough=no
/ip firewall mangle add chain=forward src-address-list=tier-basic action=mark-packet new-packet-mark=basic-up passthrough=no
# --- Queue Trees per tier ---
/queue tree add name=premium-down parent=total-download packet-mark=premium-down queue=pcq-premium-down limit-at=20M max-limit=50M priority=2
/queue tree add name=premium-up parent=total-upload packet-mark=premium-up queue=pcq-premium-up limit-at=10M max-limit=20M priority=2
/queue tree add name=standard-down parent=total-download packet-mark=standard-down queue=pcq-standard-down limit-at=10M max-limit=30M priority=4
/queue tree add name=standard-up parent=total-upload packet-mark=standard-up queue=pcq-standard-up limit-at=5M max-limit=10M priority=4
/queue tree add name=basic-down parent=total-download packet-mark=basic-down queue=pcq-basic-down limit-at=5M max-limit=15M priority=6
/queue tree add name=basic-up parent=total-upload packet-mark=basic-up queue=pcq-basic-up limit-at=2M max-limit=5M priority=6
Step 7: Monitoring Queue Performance
# View real-time queue statistics
/queue tree print stats
# Filter by name
/queue tree print stats where name~"premium"
# Watch live bandwidth per interface
/tool torch interface=ether1
# Check mangle rule hit counters
/ip firewall mangle print stats
WinBox: Queues → Queue Tree tab shows real-time rates, queued bytes, and drops per queue.
Troubleshooting
- Queues not applying (0 bytes/packets): Check mangle rules – are packets being marked? Run
/ip firewall mangle print statsto see hit counters. If zero, the mangle chain or matchers are wrong. - FastTrack bypassing queues: FastTrack skips firewall processing for established connections, which means mangle rules don't mark the traffic. Either disable FastTrack or place your mangle marks in
chain=preroutinginstead ofchain=forward(some configurations). - Wrong traffic direction: Remember:
dst-addressmatching in forward chain = download to that IP.src-address= upload from that IP. Getting this backwards is the #1 mistake. - Parent limit too low: If children's
limit-atvalues sum to more than the parent'smax-limit, there's not enough guaranteed bandwidth. Reduce child guarantees. - Burst not working: Queue Trees support burst parameters too. Add
burst-limit,burst-threshold, andburst-timeto child queues. - PPPoE users not matched: For PPPoE networks, use dynamic queues via RADIUS attributes or match by
in-interface(the PPPoE interface name) instead of IP address.
Queue Tree vs. Simple Queue: When to Use Each
| Feature | Simple Queue | Queue Tree |
|---|---|---|
| Ease of use | ✅ Very easy | 😠Moderate |
| Hierarchical shaping | 🟡 Basic parent/child | ✅ Full HTB |
| Per-protocol priority | ⌠No (needs marks) | ✅ Yes |
| Requires mangle rules | ⌠No | ✅ Yes |
| FastTrack compatible | ⌠Breaks queues | 🟡 Depends on config |
| Best for | Small networks, quick limits | ISPs, QoS, complex shaping |
Tips for ISPs Using MikroRadius
If you're running a PPPoE network with MikroRadius, you can push bandwidth limits via RADIUS attributes instead of managing queues manually. MikroRadius sends Mikrotik-Rate-Limit attributes that create dynamic Simple Queues per PPPoE session. For advanced shaping, combine RADIUS rate limits with Queue Trees for global prioritization.
Conclusion
Queue Trees with HTB give you enterprise‑grade traffic shaping on MikroTik. Start simple – one parent, a few children – then add PCQ for dynamic allocation and priority queues for VoIP/DNS. The investment in learning mangle marks and queue hierarchy pays off enormously when you need guaranteed service quality for hundreds of users.
For simpler setups, Simple Queues remain a great choice. Graduate to Queue Trees when you need per-protocol prioritization, guaranteed minimums, or ISP‑scale shaping.