Tech News
← Back to articles

How/why to sweep async tasks under a Postgres table

read original related products more articles

How/Why to Sweep Async Tasks Under a Postgres Table

I like slim and stupid servers, where each endpoint wraps a very dumb DB query.

Dumb queries are fast. Fast queries make websites smooth and snappy. Keep those click/render loops sacred.

Sweep complexity under a task table:

router.post("/signup", async ctx => { const { email, password } = await ctx.request.body().value; const [{ usr_id } = { usr_id: null }] = await sql` with usr_ as ( insert into usr (email, password) values (${email}, crypt(${password}, gen_salt('bf'))) returning * ), task_ as ( insert into task (task_type, params) values ('SEND_EMAIL_WELCOME', ${sql({ usr_id })}) ) select * from usr_ `; await ctx.cookies.set("usr_id", usr_id); ctx.response.status = 204; });

Of course using mailgun.send is easier than queuing it in a task table. Adding indirection rarely makes systems less complex. But somehow I'm here to advocate exactly that. You may ignore my manifesto and skip to my implementation at the end.

Secret Surface Error Area

Customers don't care about cosmic rays. They want a thing. More imporantly, they want immediate confirmation of their thing. They want to offload the mental burden of their goal.

For them to delegate that responsibility, your DB is probably the only thing that matters. Once information is committed to your database, you can confidently say "we'll take it from here".

You can send emails later. You can process payments later. You can do almost anything later. Just tell your customer they can continue with their goddamn day.

... continue reading