Here is my practical use case example, showing the reason behind my "dislike" of COBS. (It's a hobby investigation, not a product; just something I do for fun.)
I have a host SBC with a ~ 2Mbit/s UART connection to my microcontroller. I want to use that same UART connection for the serial console (including boot log), bulk data for displaying graphics and other information on a small display, feed back entropy from a hardware random number generator back to the Linux kernel, as well as provide some user interface events (key presses et cetera) back to the kernel.
I have my own kernel driver for the UART connection, and my own firmware on the microcontroller.
The serial console data from SBC to microcontroller should have maximum priority. This is especially important during bootup, to not slow down the bootup process (and to avoid having a larger buffer at boot time).
The bulk data from SBC to microcontroller should have minimum priority; it should only be transmitted when there is nothing more important.
The serial console events from the microcontroller back to the SBC should have equal priority with the user interface events reported.
Feeding back some entropy from the microcontroller back to the SBC should have minimum priority; it should only be transmitted when there is nothing more important.
As you can see, I kinda-sorta have to treat each of these as a stream. Packetizing them is really not feasible, since the bulk data could be huge, and I want the serial console data to 'interrupt' bulk data flow, and have priority.
Byte stuffing, with specific byte values reserved as "serial console data follows", "display data follows", "event data follows", and "entropy data follows", means I can interrupt at any position (except between a stuffed "escape" marker and the payload byte). If I assume I end up with 8 reserved byte values, the escape one included, I can use 8+8×8=72 other byte values following the escape marker to encode the reserved byte values and any pair of reserved byte values, limiting the maximum overhead to 50%: when the original data stream has every other byte a reserved value, giving 2 to 3 expansion, or 150% encoded length compared to original.
(If you consider the worst case in isolation, three bytes where the first and last are reserved values, that does expand to five bytes, giving 67% overhead. With additional implementation complexity, using 64 additional three-byte escape sequences (ESC PAIR mid -> FIRST mid SECOND) would fix that, though. Assuming 8-bit bytes, there is just enough unique byte values for this scheme to handle up to 10 reserved byte values, but no more.)
Note that even the latency requirement/preference here is not related to the physical connection, but a direct result of the preferred priorities on what data gets transmitted first. I do not want to wait for a full packet to be transmitted before switching to the more important, higher priority data; I want to do it as soon as possible.
I do believe that similar needs are relatively rare, though. I should have been clearer in my earlier posts: these are my preferences due to the kind of problems I work with, not universal or directly applicable to others. For example, anyone using USB can use multiple endpoints, one for each sub-stream or channel.
This can be useful in embedded environments that use TLS encrypted TCP connections, because the 50% overhead is much preferable to the work involved in TLS handshakes for using multiple TCP connections in parallel; basically, you save on both computation and memory requirements, and can even simplify the TLS+TCP code needed.
Now, if I was doing something else, where consistent overhead was more important, and I didn't need to multiplex a single connection for multiple logical connections, I'd like COBS just fine.