Contributed — backend services
Super Local Fans
A social CRM that turns customers into brand advocates — auto-posting, loyalty and content tooling across several social platforms. It runs as microservices with a micro-frontend, on Kubernetes.
01The problem
One of the backend jobs I worked on was scheduled publishing: fire a post to several social platforms at a future time, reliably, in a deployment where the service is running as multiple replicas. Naive scheduling in that environment either fires duplicates or wastes work.
02The constraint
A scheduled post had to fire exactly once at its time, survive replicas scaling up and down, and retry cleanly on failure — all within a Kubernetes microservices deployment observed through Sentry.
03What I built
Scheduled publishing runs on BullMQ delayed jobs backed by Redis: a scheduled post becomes one durable job that Redis holds until its time, then hands to a single worker. Retries and backoff are built in rather than hand-rolled.
The services are NestJS with a GraphQL (Apollo) API over PostgreSQL and Prisma, deployed on Kubernetes and instrumented with Sentry.
04The decision
Options considered
Scheduling posts for a future time, in a service that runs as several replicas on Kubernetes, is where the naive answers fall apart.
- AA cron per service — simple, until every replica fires the same cron and you get duplicate posts (or you bolt on leader election).
- BPoll a 'due posts' table on an interval — works, but most queries find nothing and it never sits still.
- CBullMQ delayed jobs backed by Redis — one durable job per scheduled post, owned by one worker.
Chose BullMQ delayed jobs.
The trade-off I accepted
A cron per replica duplicates work as you scale out, and polling a table burns queries doing nothing most of the time. BullMQ delayed jobs make a scheduled post a single durable unit: Redis holds it until it's due, exactly one worker picks it up, retries are part of the mechanism. The cost is another Redis-backed queue to run and reason about — but it was already the queue backbone for the services I worked on, so scheduled publishing rode on infrastructure that was there rather than adding a new mechanism.
05Stack
- NestJS
- GraphQL
- Apollo
- BullMQ
- Redis
- PostgreSQL
- Prisma
- Kubernetes
- Sentry