SkillAgentSearch skills...

Absurd

An experiment in durability

Install / Use

/learn @earendil-works/Absurd
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<div style="text-align: center" align="center"> <img src="logo.jpg" width="350" alt="Une photo d'un éléphant avec le titre : « Ceci n'est pas un éléphant »"> <br><br> </div>

Absurd

Absurd is the simplest durable execution workflow system you can think of. It's entirely based on Postgres and nothing else. It's almost as easy to use as a queue, but it handles scheduling and retries, and it does all of that without needing any other services to run in addition to Postgres.

… because it's absurd how much you can over-design such a simple thing.

More about it can be found in the announcement post.

You can read in the docs how Absurd compares to PGMQ, Cadence, Temporal, Inngest, and DBOS.

What is Durable Execution?

Durable execution (or durable workflows) is a way to run long-lived, reliable functions that can survive crashes, restarts, and network failures without losing state or duplicating work. Durable execution can be thought of as the combination of a queue system and a state store that remembers the most recently seen state.

Instead of running your logic in memory, a durable execution system decomposes a task into smaller pieces (step functions) and records every step and decision. When the process stops (fails, intentionally suspends, or a machine dies), the engine can replay those events to restore the exact state and continue where it left off, as if nothing happened.

In practice, that makes it possible to build dependable systems for things like LLM-based agents, payments, email scheduling, order processing--really anything that spans minutes, days, or even years. Rather than bolting on ad-hoc retry logic and database checkpoints, durable workflows give you one consistent model for ensuring progress without double execution. It's the promise of "exactly-once" semantics in distributed systems, but expressed as code you can read and reason about.

Installation

Absurd just needs a single .sql file (absurd.sql) which needs to be applied to a database of your choice. You can plug it into your favorite migration system of choice. Additionally if that file changes, we also release migrations which should make upgrading easy. See the quickstart guide for a short tutorial and the documentation index for everything else.

Client SDKs

Currently SDKs exist for the following languages:

Push vs Pull

Absurd is a pull-based system, which means that your code pulls tasks from Postgres as it has capacity. It does not support push at all, which would require a coordinator to run and call HTTP endpoints or similar. Push systems have the inherent disadvantage that you need to take greater care of system load constraints. If you need this, you can write yourself a simple service that consumes messages and makes HTTP requests.

High-Level Operations

Absurd's goal is to move the complexity of SDKs into the underlying stored functions. The SDKs then try to make the system convenient by abstracting the low-level operations in a way that leverages the ergonomics of the language you are working with.

A task dispatches onto a given queue from where a worker picks it up to work on. Tasks are subdivided into steps, which are executed in sequence by the worker. Tasks can be suspended or fail, and when that happens, they execute again (a run). The result of a step is stored in the database (a checkpoint). To not repeat work, checkpoints are automatically loaded from the state storage in Postgres again.

Additionally, tasks can sleep or suspend for events. Events are cached (first emit wins), which means they are race-free.

Components

Absurd comes with two basic tools that help you work with it. One is called absurdctl which allows you to initialize and migrate the schema, inspect schema versions, create/drop/list queues, and spawn or retry tasks. The other is habitat which is a Go application that serves up a web UI to show you the current state of running and executed tasks.

absurdctl init -d database-name
absurdctl schema-version -d database-name
absurdctl migrate -d database-name
absurdctl create-queue -d database-name default

Install the SDK for your language of choice:

# TypeScript / JavaScript
npm install absurd-sdk

# Python
uv add absurd-sdk
<div style="text-align: center" align="center"> <img src="habitat/screenshot.png" width="550" alt="Screenshot of habitat"> </div>

Example

Here's what that looks like in TypeScript.

import { Absurd } from 'absurd-sdk';

const app = new Absurd();

// A task represents a series of operations.  It can be decomposed into
// steps, which act as checkpoints.  Once a step has been passed
// successfully, the return value is retained and it won't execute again.
// If it fails, the entire task is retried.  Code that runs outside of
// steps will potentially be executed multiple times.
app.registerTask({ name: 'order-fulfillment' }, async (params, ctx) => {

  // Each step is checkpointed, so if the process crashes, we resume
  // from the last completed step
  const payment = await ctx.step('process-payment', async () => {
    // If you need an idempotency key, you can derive one from ctx.taskID.
    return await stripe.charges.create({ amount: params.amount, ... });
  });

  const inventory = await ctx.step('reserve-inventory', async () => {
    return await db.reserveItems(params.items);
  });

  // Wait indefinitely for a warehouse event - the task suspends
  // until the event arrives.  Events are cached like step checkpoints
  // (first emit wins), which means this is race-free.
  const shipment = await ctx.awaitEvent(`shipment.packed:${params.orderId}`);

  // Ready to send a notification!
  await ctx.step('send-notification', async () => {
    return await sendEmail(params.email, shipment);
  });

  return { orderId: payment.id, trackingNumber: shipment.trackingNumber };
});

myWebApp.post("/api/shipment/pack/{orderId}", async (req) => {
  const trackingNumber = ...;
  await app.emitEvent(`shipment.packed:${req.params.orderId}`, {
    trackingNumber,
  });
});

// Start a worker that pulls tasks from Postgres
await app.startWorker();

Spawn a task:

// Spawn a task - it will be executed durably with automatic retries.  If
// triggered from within a task, you can also await it.
app.spawn('order-fulfillment', {
  orderId: '42',
  amount: 9999,
  items: ['widget-1', 'gadget-2'],
  email: 'customer@example.com'
});

Documentation

More detail lives in the docs:

Working With Agents

Absurd is built so that agents such as Claude Code can efficiently work with the state in the database. You can either point them straight at Postgres and hope that they pry the information out, but the better idea is to make absurdctl available on PATH and give them some ideas of what to do with it. absurdctl can output some agent-specific help that you can put into your AGENTS.md / CLAUDE.md files:

absurdctl agent-help >> AGENTS.md

You might have to tweak the outputs afterwards to work best for your setup.

AI Use Disclaimer

This codebase has been built with a lot of support of AI. A combination of hand written code, Codex and Claude Code was used to create this repository. To the extent to which it can be copyrighted, the Apache 2.0 license should be assumed.

License and Links

View on GitHub
GitHub Stars1.2k
CategoryDevelopment
Updated4m ago
Forks53

Languages

Python

Security Score

95/100

Audited on Apr 2, 2026

No findings