The transactional outbox solves the dual write problem and then hands you a second one: a relay service that has to be deployed, watched and kept pointed at the right database. ulak moves the relay into PostgreSQL as background workers. This is how it claims, delivers and recovers, and the trade it asks you to accept in return.
The queue, the cache, the search index, the vector store, the job scheduler and the analytics table for a product with 40,000 daily users all live in one Postgres 18 instance. That is not a compromise. It is the design. Here is what each piece looks like, what it costs, and the three specific signals that would make me move one of them out.
PostgreSQL 18 ships uuidv7() in core. It looks like a small convenience function. It is actually the end of a decade-long argument about UUID primary keys, and the numbers from a 200 million row table explain why. Migration path included, with the one gotcha around the timestamp you can extract.