Skip to content

Welcome to docket

Docket is a distributed background task system for Python functions with a focus on the scheduling of future work as seamlessly and efficiency as immediate work.

PyPI - Version PyPI - Python Version GitHub main checks Codecov PyPI - License

At a glance

from datetime import datetime, timedelta, timezone

from docket import Docket


async def greet(name: str, greeting="Hello") -> None:
    print(f"{greeting}, {name} at {datetime.now()}!")


async with Docket() as docket:
    await docket.add(greet)("Jane")

    now = datetime.now(timezone.utc)
    soon = now + timedelta(seconds=3)
    await docket.add(greet, when=soon)("John", greeting="Howdy")

And in another process, run a worker:

from docket import Docket, Worker

async with Docket() as docket:
    async with Worker(docket) as worker:
        await worker.run_until_finished()

Which produces:

Hello, Jane at 2025-03-05 13:58:21.552644!
Howdy, John at 2025-03-05 13:58:24.550773!

Why docket?

⚡️ Snappy one-way background task processing without any bloat

📅 Schedule immediate or future work seamlessly with the same interface

⏭️ Skip problematic tasks or parameters without redeploying

🌊 Purpose-built for Redis streams

🧩 Fully type-complete and type-aware for your background task functions

How It Works

docket integrates two modes of task execution:

  1. Immediate tasks are pushed onto a Redis stream and are available to be picked up by any worker.
  2. Scheduled tasks are pushed onto a Redis sorted set with a schedule time. A loop within each worker moves scheduled tasks onto the stream when their schedule time has arrived. This move is performed as a Lua script to ensure atomicity.

Docket requires a Redis server with Streams support (which was introduced in Redis 5.0.0). Docket is tested with Redis 6 and s7.

For more detailed information, check out our Getting Started guide or dive into the API Reference.