Async messaging (production)

Platform async messaging stacks on sqlx PgPool (PgPool), with production adapters in id_effect_jobs and id_effect_events.

SQL platform

id_effect_sql_pg replaces the deadpool era with sqlx:

Jobs — Apalis (pull workers)

ApalisJobQueue is enqueue-only. Workers pull tasks via Apalis WorkerBuilder + PostgresStorage::poll — there is no FIFO dequeue on the storage side.

use id_effect_jobs::{ApalisJobQueue, JobSpec};
use id_effect::run_async;

ApalisJobQueue::setup(&pool).await?;
let queue = ApalisJobQueue::new(&pool, "app_jobs");
run_async(queue.enqueue(JobSpec::new("notify", b"payload")), ()).await?;

Enable: id_effect_jobs features apalis (+ postgres).

Transactional outbox — obix

ObixOutbox persists OutboxRecord rows through obix on the shared pool. Relay is driven by obix's register_event_handler; the per-consumer cursor lives in job_executions.execution_state_json.

For unit tests only: memory feature + MemoryOutbox + relay_outbox.

Idempotent inbox — obix + job

ObixInbox wires obix Inbox to the job poller for idempotent consumers.

Kafka — rdkafka

RdKafkaBroker implements MessageBroker with rdkafka. KafkaBrokerStub remains memory-only (memory feature) for tests.

SQL event journal

EsEntityPgBackend (id_effect_events feature es-entity) implements SqlJournalBackend on the same PgPool.

Apply ES_ENTITY_EVENT_JOURNAL_DDL via apply_es_entity_journal_ddl.

Feature matrix

CrateFeatureAdapter
id_effect_jobsmemory (default)in-process stubs
id_effect_jobsapalisApalis PostgreSQL queue
id_effect_jobsobixobix outbox + inbox
id_effect_jobskafkardkafka broker
id_effect_eventspostgresEsEntityPgBackend

See also

  • ADR: docs/platform/adrs/adr-sql-driver-choice.md
  • Plan: .cursor/plans/platform_messaging_production.plan.md