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 efficiently 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, 7, and 8.

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