SKIP LOCKED is amazing for this kind of thing. I used it to build a transaction outbox a few years ago.
One thing worth looking into if you do this in production is adding a way to add partitions such that each partition is single threaded. It’s the only way to guarantee ordering if your jobs are doing anything non-deterministic.