Backend Migration Guide¶
This guide covers moving an application from local development storage ("ephemeral" or "memory") to a production database backend, selecting SQLSpec wakeup transports, and provisioning forever-uniqueness reservation tables.
Moving from Ephemeral or Memory to Production Storage¶
During initial prototyping, QueueConfig() defaults to queue_backend="ephemeral", which stores queue tables in a temporary local SQLite file shared across processes on a single host.
Because QueueService, @task, WorkerConfig, and QueueEventsConfig use a backend-neutral storage contract (BaseQueueBackend), migrating to PostgreSQL, CockroachDB, Spanner, Oracle, or Redis/Valkey requires changing only QueueConfig.queue_backend and WorkerConfig.placement:
from litestar_queues import QueueConfig, WorkerConfig
from litestar_queues.backends.sqlspec import SQLSpecBackendConfig, SQLSpecWorkerWakeupConfig
from sqlspec.adapters.asyncpg import AsyncpgConfig
config = QueueConfig(
queue_backend=SQLSpecBackendConfig(
sqlspec_config=AsyncpgConfig(connection_config={"dsn": "postgresql://app:secret@db:5432/app"}),
manage_schema=False,
terminal_ttl=86_400.0,
worker_wakeups=SQLSpecWorkerWakeupConfig(transport="notify_queue"),
),
worker=WorkerConfig(placement="external", max_concurrency=32, stale_after=60.0),
)
from litestar_queues import QueueConfig, WorkerConfig
from litestar_queues.backends.redis import RedisBackendConfig
config = QueueConfig(
queue_backend=RedisBackendConfig(
url="redis://redis.internal:6379/0",
key_prefix="prod_queues",
worker_wakeups=True,
terminal_ttl=86_400.0,
),
worker=WorkerConfig(placement="external", max_concurrency=32, stale_after=60.0),
)
SQLSpec Wakeup Transports Across Environments¶
When transitioning from embedded SQLite or DuckDB to a network database in production, SQLSpecWorkerWakeupConfig.transport selects the optimal wakeup strategy for the target adapter:
notify_queue: Default on PostgreSQL (asyncpg,psycopg,psqlpy); combinesLISTEN/NOTIFYpush delivery with the durablesqlspec_event_queuetable.notify: Transient PostgreSQLLISTEN/NOTIFYpush delivery without requiring thesqlspec_event_queuetable.poll_queue: Durable event-queue polling (default onduckdb).aq/txeventq: Oracle Advanced Queuing and Transactional Event Queues.polling: Adaptive interval polling without an event channel.
Forever-Uniqueness Reservation Storage¶
Tasks configured with @task(..., unique_until="forever") persist a lightweight TaskReservation (key, task_id, task_name, created_at) in a dedicated reservation store separate from queue_task:
- SQLSpec: Stored in
queue_task_reservation(configurable viaSQLSpecBackendConfig.task_reservation_table_name), created automatically by migration0001_create_queue_tasksorawait backend.create_schema(). - Advanced Alchemy: Stored in
QueueTaskReservationModel(queue_task_reservationtable, or a custom model composed withQueueTaskReservationModelMixin). - Redis & Valkey: Stored in the
{prefix}:task_reservationshash.
Routine terminal cleanup (cleanup_completed, terminal_ttl, and WorkerConfig.terminal_retention) and event history pruning never delete TaskReservation entries. To release a forever reservation so the identity key can be enqueued again, call await queue_service.reset_task_identity(key) with the exact effective key.