惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
The Cloudflare Blog
G
Google Developers Blog
博客园_首页
Martin Fowler
Martin Fowler
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
D
Docker
C
Check Point Blog
T
Tailwind CSS Blog
博客园 - 司徒正美
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
Microsoft Security Blog
Microsoft Security Blog
V
V2EX
博客园 - 叶小钗
T
The Blog of Author Tim Ferriss
酷 壳 – CoolShell
酷 壳 – CoolShell
IT之家
IT之家
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 【当耐特】
GbyAI
GbyAI

Buttondown's blog

Email could have been X.400 times better The physicists who convinced Fermilab to send Brazil's emails Better in-app previews Analytics 3.0 Subscriber ID variables Comments! Send latest premium action Automation filtering Free API subscribers Surveys in automations Reply to replies Labels for RSS feeds How Jeremy Singer-Vine curates curious datasets for readers 2023 (and what's next) Email vs web content Sort by engagement Better gift subscriptions How Andy Dehnart built a career reviewing television New email template Email-based automations Opt-in reply tracking Automatic alt text More social network integrations Sort by metadata Overlarge image warnings Automation tag actions Pause emails mid-flight Search tags and automations Gift via automations Subscriber-driving emails
Announcing django-rq-cron
Justin Duke · 2025-06-10 · via Buttondown's blog

We've released django-rq-cron, a cleverly-titled cron module sitting on top of RQ and Django RQ.

We use this to process all of our scheduled and periodic events: sending daily emails, running our checker system, and more. We're releasing it in hopes that other folks with the same set of concerns and characteristics might find it useful.

We're marking this initial release as 0.2.0 (a nice middle ground between "stable" and "totally experimental, do not touch") not because we don't think it's technically production-ready — it is. We have been using this in production for almost a year. But because I suspect the API in some of the interfaces that work for our idiosyncratic needs might not be broadly applicable.

The question when releasing one of these packages is, why build out a cron package in the first place?

The existing package we were using, django-cron, had some issues for us and rather than try to paper over the issues that were fairly systemic it made sense to spike out building our own system. That spike ended up turning out pretty well and over time we fleshed out something that felt fairly mature and robust and now here we are.

The specific issues we ran into were threefold:

  1. The first was that django-cron's core processing and modeling didn't quite meet our requirements. For instance, django-cron serially processes CronJobs, meaning that if you have ten crons all running and the fourth one fails, the sixth never even attempts to run. This is an issue that we know we could paper over, but felt like a bit of a core flaw relative to having each one independently run its own task without interrupting its temporal neighbors. There were also some one-off locking issues that totally made sense from a design point of view, but just didn't quite work from our perspective. It was more important for us to be able to easily rerun and understand the state of a given job, as opposed to protect from reruns, because we generally design our crons with idempotence in mind.
  2. The second issue had nothing to do with django-cron. Buttondown sits on top of Heroku, and Heroku's default cron scheduler does not make any time guarantees. Unfortunately, this manifests in peculiar and dangerous ways—for instance, it might execute 9 minutes after we've scheduled it to run, causing django-cron to completely miss the entire batch of crons for a given window. The right approach here is to build a dedicated "dyno" for running the Cron full-time, which feels wasteful when we already have a process dedicated to doing exactly that.
  3. The third issue was that it was difficult to reconcile two separate systems for scheduled and periodic tasks. We've invested a lot in observability and tooling around RQ, and it felt painful to have to throw all that away for anything that was running on a cron, even if it looked very similar in all respects except for the harness actually handling the execution.

django-rq-cron started as an experiment for a few particularly sensitive crons, and it ended up working so well that we quickly migrated all of our crons to it. And here we are, releasing it to the world!

Even if you feel like your cron needs are completely solved, hopefully you find some of this interesting. The codebase itself is fairly compact and uncomplicated. We've got a set of models for governing the cron state machine, a registrar pattern for allowing you to register a cron in much the same way you might register a Django model admin, and a runner to actually invoke the crons and enqueue them as RQ jobs.

Please take a look at the codebase and let me know if you have any questions or hot takes or violent criticisms.