Postgres Backend¶
taskito supports PostgreSQL as an alternative storage backend for production deployments that need multi-machine workers or higher write throughput.
When to Use Postgres¶
Choose Postgres over the default SQLite backend when you need:
- Multi-machine workers — run workers on separate hosts against a shared database
- Higher write throughput — Postgres handles concurrent writes without SQLite's single-writer constraint
- Existing Postgres infrastructure — reuse your existing database server instead of managing SQLite files
For single-machine workloads, SQLite remains the simpler choice — no external dependencies required.
Installation¶
Linux only
The Postgres backend currently requires Linux. macOS and Windows are not yet supported for the postgres extra.
Configuration¶
from taskito import Queue
queue = Queue(
backend="postgres",
db_url="postgresql://user:password@localhost:5432/myapp",
schema="taskito", # optional, default: "taskito"
)
| Parameter | Type | Default | Description |
|---|---|---|---|
backend |
str |
"sqlite" |
Set to "postgres" or "postgresql" |
db_url |
str |
None |
PostgreSQL connection URL (required for Postgres) |
schema |
str |
"taskito" |
PostgreSQL schema for all tables |
workers |
int |
0 (auto) |
Number of worker threads |
All other Queue parameters (default_retry, default_timeout, default_priority, result_ttl) work identically to the SQLite backend.
Django Integration¶
Configure the Postgres backend via Django settings:
# settings.py
TASKITO_BACKEND = "postgres"
TASKITO_DB_URL = "postgresql://user:password@localhost:5432/myapp"
TASKITO_SCHEMA = "taskito"
Then use the Django integration as normal:
All Django settings:
| Setting | Default | Description |
|---|---|---|
TASKITO_BACKEND |
"sqlite" |
Storage backend ("sqlite" or "postgres") |
TASKITO_DB_URL |
None |
PostgreSQL connection URL |
TASKITO_SCHEMA |
"taskito" |
PostgreSQL schema name |
TASKITO_DB_PATH |
".taskito/taskito.db" |
SQLite database path (ignored with Postgres) |
TASKITO_WORKERS |
0 |
Worker thread count (0 = auto-detect) |
TASKITO_DEFAULT_RETRY |
3 |
Default max retries |
TASKITO_DEFAULT_TIMEOUT |
300 |
Default task timeout in seconds |
TASKITO_DEFAULT_PRIORITY |
0 |
Default task priority |
TASKITO_RESULT_TTL |
None |
Result TTL in seconds |
Schema Isolation¶
taskito creates all tables inside a dedicated PostgreSQL schema (default: taskito). The schema is created automatically if it doesn't exist.
# Use a custom schema
queue = Queue(backend="postgres", db_url="postgresql://...", schema="myapp_tasks")
Schema names must contain only alphanumeric characters and underscores. Invalid names raise a ConfigError at startup.
This lets you run multiple independent taskito instances in the same database by using different schemas, or keep taskito tables separate from your application tables.
Connection Pooling¶
The Postgres backend uses Diesel's r2d2 connection pool with a default size of 10 connections. Each connection has the search_path set to the configured schema on acquisition.
The pool size is configured at the Rust layer. For most workloads, the default of 10 connections is sufficient.
Migrations¶
Migrations run automatically on first connection. taskito creates the following 11 tables inside the configured schema:
| Table | Purpose |
|---|---|
jobs |
Core job storage |
dead_letter |
Dead letter queue |
rate_limits |
Token bucket rate limiting state |
periodic_tasks |
Cron-scheduled task definitions |
job_errors |
Per-attempt error tracking |
job_dependencies |
Task dependency edges |
task_metrics |
Execution time and memory metrics |
replay_history |
Job replay audit trail |
task_logs |
Structured task log entries |
circuit_breakers |
Circuit breaker state |
workers |
Worker heartbeat tracking |
All tables use PostgreSQL-native types (TEXT, BYTEA, BIGINT, BOOLEAN, DOUBLE PRECISION) rather than SQLite-compatible types.
Differences from SQLite¶
| Aspect | SQLite | Postgres |
|---|---|---|
| Connection model | Embedded, file-based | Client/server, networked |
| Write concurrency | Single writer (WAL mode) | Multiple concurrent writers |
| Distribution | Single machine only | Multi-machine workers |
| Setup | Zero config, bundled | Requires Postgres server |
| Connection pool default | 8 connections | 10 connections |
| Schema isolation | N/A (file per database) | Custom PostgreSQL schema |
| Tables | 6 tables | 11 tables (additional: job_dependencies, task_metrics, replay_history, task_logs, circuit_breakers) |
| Backup | sqlite3 .backup |
pg_dump |
Deployment¶
Docker Compose¶
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_USER: taskito
POSTGRES_PASSWORD: secret
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- "5432:5432"
worker:
build: .
environment:
TASKITO_BACKEND: postgres
TASKITO_DB_URL: postgresql://taskito:secret@postgres:5432/myapp
depends_on:
- postgres
stop_signal: SIGINT
stop_grace_period: 35s
dashboard:
build: .
command: taskito dashboard --app myapp:queue --host 0.0.0.0
environment:
TASKITO_BACKEND: postgres
TASKITO_DB_URL: postgresql://taskito:secret@postgres:5432/myapp
depends_on:
- postgres
ports:
- "8080:8080"
volumes:
pgdata:
With Postgres, there are no shared-file constraints — workers and dashboard connect over the network. You can run multiple worker containers across different hosts.
systemd¶
[Unit]
Description=taskito worker
After=network.target postgresql.service
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/.venv/bin/taskito worker --app myapp:queue
Restart=always
RestartSec=5
KillSignal=SIGINT
TimeoutStopSec=35
Environment=PYTHONPATH=/opt/myapp
Environment=TASKITO_BACKEND=postgres
Environment=TASKITO_DB_URL=postgresql://taskito:secret@db.internal:5432/myapp
[Install]
WantedBy=multi-user.target
Multi-Machine Workers¶
With Postgres, you can run workers on multiple machines. Each worker connects to the same database and coordinates through PostgreSQL's row-level locking:
# Machine 1
taskito worker --app myapp:queue
# Machine 2
taskito worker --app myapp:queue
# Machine 3
taskito worker --app myapp:queue
All workers share the same job queue and dequeue work atomically.
Backups¶
Use standard PostgreSQL backup tools instead of SQLite-specific commands:
# Dump the taskito schema
pg_dump -h localhost -U taskito -d myapp -n taskito > backup.sql
# Restore
psql -h localhost -U taskito -d myapp < backup.sql
For continuous backups, use PostgreSQL's built-in WAL archiving or a tool like pgBackRest.