My first useful QoS decision was not choosing a queueing algorithm or assigning a priority. It was deciding where I wanted the queue to exist.
If a router sends faster than the next hop can carry, packets wait in a modem or an upstream policer. The router can mark them beautifully, but it no longer controls which packet leaves that queue next. The fix is to shape slightly below the usable bottleneck so the backlog forms locally, where CAKE or FQ-CoDel can enforce fairness.
That rate is not always fixed. r3’s mobile path adjusts within bounded limits when load and latency show that carrier capacity has moved. r4’s shared physical uplink stays just below a stable line rate, with smaller path ceilings underneath it where a tunnel encounters another policer.
I now treat queue location as part of the policy and its attachment as runtime state. The configuration is rendered in Ansible; the kernel’s qdiscs, backlog and drops are exported to Prometheus; Grafana and alerts tell me when the queue has moved out of my control because a policy or collector disappeared.