Summary: The elixir-backend uses Google Pub/Sub as its async event spine, publishing domain events that are consumed internally via Broadway pipelines and potentially by external subscribers. Sources: direct code inspection (mix.exs — broadway 1.1, broadway_cloud_pub_sub 0.9, goth 1.0; lib/backend/shared/) Last updated: 2026-05-15


Architecture

The event bus is the primary decoupling mechanism inside the modulith (see modulith-domain-model). When a domain completes a significant action, it publishes a versioned event struct to a Google Pub/Sub topic. Other domains or external systems subscribe to topics and process events asynchronously via Broadway pipelines.

Domain A
  └─ publishes event → Pub/Sub topic
                              └─ Broadway consumer (Domain B or external)
                                      └─ processes event, updates own state

This means Domain A does not know about Domain B. Coupling is through the event schema, not through code.

Key libraries

  • Broadway 1.1 — concurrent, fault-tolerant pipeline processing of Pub/Sub messages
  • Broadway Cloud Pub/Sub 0.9 — Broadway adapter for Google Cloud Pub/Sub
  • Goth 1.0 — GCP service account authentication (used to auth against Pub/Sub API)

Event definition

Events follow the Backend.Event behaviour with versioning support. This means event schemas are typed and versioned, which allows consumers to handle multiple versions of the same event during rolling deploys.

Local development

The Pub/Sub emulator replaces the real GCP service locally. Setup:

just containers=db,pubsub docker            # start emulator
mix pubsub.emulator.setup $PUBSUB_EMULATOR_HOST my-project
mix pubsub.emulator.seed projects/my-project/topics/test_topic 100

What connects here

Publishers (known from backend): all backend domains — practice, monetization, user_identity, prevention, activation publish events when state changes.

Consumers inside backend: Broadway pipelines in the shared domain and individual domains consume events from other domains.

External consumers: TBD — other internal services may subscribe to backend topics. Requires inspection of other repos.

What agents should know

  • New cross-domain interactions should be modeled as events, not direct function calls.
  • Event structs are versioned. When changing an event schema, add a new version rather than modifying the existing one to avoid breaking existing consumers.
  • The PUBSUB_EMULATOR_HOST env var switches between the local emulator and real GCP. It must be unset in production.
  • GCP authentication for Pub/Sub uses Goth with a service account — the credentials are injected via Kubernetes secrets, not env vars directly.