Engine

Architecture

GozWire is a messaging engine. PostgreSQL is the durable source of truth. Realtime, storage, moderation, and push are adapters.

GozWire is a messaging engine: primitives for conversations, messages, receipts, attachments, expiration, retention, realtime fanout, configurable moderation, and optional durable push. Developers can build WhatsApp-like, Discord-like, or Stream Chat-like products on top of it. The engine is not those products.

PostgreSQL is the only durable source of truth. Redis, Centrifugo, object storage, the moderation sidecar, and push providers (Web Push, FCM, APNs) are infrastructure. A persisted message must survive realtime, Redis, sidecar, and provider failure.

The package boundary

@gozwire/core is the messaging engine. The Express demo host, the Svelte playground, and the Python moderation sidecar are repository applications. The engine does not import Express, Svelte, or Python.

Domain model

Durable PostgreSQL entities include:

  • identities : referenced users, not a full account system
  • conversations : direct, group, channel, or forum
  • conversation_participants : membership plus role (owner / admin / moderator / member)
  • messages : public UUIDv7 id, clientMessageId, type, body, reply, threadRootId, timestamps, expiration, moderation status, per-conversation sequence
  • message_attachments : object keys and sanitized filenames, not bytes
  • message_reactions : idempotent (message, user, reaction) rows
  • message_receipts : delivered and read timestamps
  • message_outbox : at-least-once realtime publication work
  • push_installations / push_intents / push_jobs : device registry and per-installation push work, independent of the outbox
  • moderation_jobs / results / events : lifecycle, raw signals, audit
  • upload_sessions : authorized object-storage uploads

Adapters

PortDefault
RealtimeCentrifugo HTTP API
Object storageS3-compatible SDK (MinIO locally, R2 or S3 in production)
Image processorSharp (profile pictures)
ModerationHTTP sidecar
MetricsIn-memory sink
PushWeb Push, FCM HTTP v1, APNs HTTP/2 behind a composite adapter, or a no-op when push.enabled is false

The engine owns authorization against participant records, idempotency, persistence, outbox, push intents (when enabled), and workers.

Command path

  1. Validate payload (type, size, MIME, membership).
  2. Authorize the sender as an active participant.
  3. Enforce rate limits.
  4. Resolve idempotency (clientMessageId).
  5. In one PostgreSQL transaction: insert the message, insert outbox row(s), and when push.enabled insert one push intent per recipient for a visible message.created.
  6. Commit, then return the persisted message.
  7. Outbox and push workers publish and call providers independently. Duplicate delivery is harmless because events carry stable IDs.

Audio and video skip the moderation pipeline. Text and images enter it when enabled. BLOCK prevents fanout and keeps audit rows.