A couple notes (co-author of fq_codel, cake and multiple other latency fighting algorithms in the linux kernel, here).
Yes, you have to be careful when fiddling with netem, especially with old kernels, but a failure to have netem work right had nothing to do with your prior successful application of fq_codel. I have many rants about how to use netem properly elsewhere.
fq_codel entered the kernel as of about linux 3.4, so it should be available. However there was an issue with GRO + HTB + fq_codel not resolved until 3.12. But if GRO is not enabled, and you are not using HTB, fq_codel as a native qdisc should work fine, and you can see it in operation via running tc -s qdisc show after subjecting your link to some load. If it is working you might see some backlogs, drops, or ecn_marks. Reschedules show the fq part working.
Most ethernet devices today have multiple queues (the mq qdisc), and rather than applying it to the top level interface as you did, the right way to apply fq_codel universally is to have it available in the kernel and configured via the appropriate sysctl, which mq will automatically pick up. There is a race in some distributions between enabling the interface and fq_codel.ko inserted as a module, on boot.
Most major linux distributions, in the years since 2012, starting with openwrt, switched to fq_codel over the past decade. It became the default in RHEL 8, for example. Ideally it is compiled into the kernel and made the default qdisc there.
This works at line rate, and with ethernet pause frames. The fq-ing portion, especially breaks up large packet trains and ensures voip and videoconferencing and other forms of smaller traffic observe no queue from the fatter flows.
The sqm-scripts can be applied to any distribution to further shape the connection down below line rate and manage latency both on the up and down, better, Example might be a cable connection, configured for 110mbit/22mbit by the ISP, but with horrible bufferbloat (I have seen +500ms!), shape it down to 100/20mbit and the connection will feel much smoother and handle a lot more users.
I had no idea anyone was still shipping 3.10!! I did a backport of sch_cake (a superset of fq_codel with many new features, which has an integral shaper) for ubnt years ago, it is available out of tree on github. That makes a lot of complex Qos rather easy, and you can also use it as a default qdisc as per the methods I outlined above. Configuring it is also supported by the sqm-scripts.
But cake shaping outbound is simpler. a one liner : tc qdisc add dev eth0 root bandwidth 20Mbit ack-filter nat diffserv4
It is four lines to configure it to shape inbound. I believe RHEL9 ships cake also, but fq_codel remains the default because it is faster, but if you have the cpu, I recommend trying cake highly. Hope this helps!