Skip to main content

Supporting queues on Postgresql

· 3 min read

Version 2.0 of Keuss comes with a new member for the supported backend family: PostgreSQL can be now used as a backend to create queues in tables of this RDBMS databases. Although not as performant as the other backends, we think it still achieve a fairly decent throughput, plus it gains the benefits of using this popular database engine:

  • Robust transactional support. PostgreSQL is fully ACID compliance, which may be appealing is some cases
  • PostgreSQL has a broader adoption in tech companies, has extensive support and resources, and a strong community
  • Reliability and maturity: PostgreSQL has been around for a long time now, and has a long track of reliability records which may be appealing to some organizations, especially risk-averse ones.
  • Strong cloud adoption

Implementing it added some challenges, due to the nature of PostgreSQL, and we needed to change the way in which we initialized the queue system, so we added some breaking changes to factory.queue() method, which is now asynchronous, and requires a callback.

Functionality

The postgres backend functionality is on par with that of mongo:

  • at-least-once (reserve-commit-rollback) with optional delays on rollback
  • scheduling (with no interference or degradation)
  • removal of elements by id

Requisites

In order to implement a Keuss queue using PostgreSQL as backend, you only need to provide an user with access to a PostgreSQL database with granted permissions to create tables and indexes on the database, as well as connection, query and update permissions over the tables in the db

Performance

Performance is far from that provided by mongo or redis backends, but it's still quite impressive for a SQL backend: it operates at a few hundred queue-ops per second

Here's a quite simple test comparison: we're running everything in localhost (i.e.: no latency), using 3 concurrent clients on a intel i5 gen8; we push 100K messages and then pop them (one run with at-most-once pop(), another run with at-least-once reserve()+commit()):

backendoptimeTPS
mongopush16s6250
pop30s3333
rsv+commit51s1960
redis-oqpush5s20000
pop6s16666
rsv+commit12s8888
redis-listpush4s25000
pop5s20000
rsv+commitn/an/a
bucket-mongo-safepush3s33333
pop6s16666
rsv+commit4s25000
postgrespush2m40s625
pop2m27s680
rsv+commit5m35s298

As you can see, figures for postgres are on a lower magnitude than the others (especially redis and buckets) but they are still pretty decent