> ## Documentation Index
> Fetch the complete documentation index at: https://archie.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Using them together

> Combine the Event Bus and Queues into the fan-out-then-process pattern: publish one event, deliver an independent copy to several queues, and let workers drain each queue at their own pace. Includes a full walkthrough and common recipes.

Queues and the Event Bus are useful on their own, but they're most powerful **together**. The Event Bus is great at *broadcasting* an event; queues are great at *reliably processing* work one item at a time. Connect them and you get the best of both: one event fans out to several independent workstreams, each of which is buffered, retried, and processed at its own pace.

This is the classic **fan-out then process** pattern (in AWS terms, SNS delivering to several SQS queues).

## The pattern in one picture

When you publish `orders.created` once, three teams react without knowing about each other:

```
                         ┌────────────────────┐   worker
                    ┌──▶ │ queue: fulfillment  │ ─────────▶ pick & pack
                    │    └────────────────────┘
  publish           │    ┌────────────────────┐   worker
  orders.created ──▶│──▶ │ queue: billing      │ ─────────▶ charge card
  (topic: orders)   │    └────────────────────┘
                    │    ┌────────────────────┐   worker
                    └──▶ │ queue: analytics    │ ─────────▶ record metrics
                         └────────────────────┘
```

Each queue holds **its own copy** of the event. If the billing worker is down for an hour, its copies wait safely in the billing queue and are processed when it returns — fulfillment and analytics are unaffected.

## Why not deliver straight to your services?

You *can* subscribe your API directly to a topic. Putting a **queue in the middle** adds three things that matter in production:

* **Buffering** — a spike of events is absorbed by the queue instead of overwhelming a downstream service.
* **Retries and an error list** — a failed job is retried and, if it keeps failing, preserved in the queue's error list instead of being lost.
* **Independent pace** — each consumer drains its queue as fast as it can, fully isolated from the others.

## Walkthrough: order created → three reactions

<Steps>
  <Step title="Create the queues">
    In the **Queues** panel, create the queues that will do the work — for example `fulfillment`, `billing`, and `analytics`. Accept the defaults unless a job needs special timing.
  </Step>

  <Step title="Create the topic">
    In the **Event Bus** panel, create a topic — for example `orders`.
  </Step>

  <Step title="Subscribe each queue to the topic">
    On the `orders` topic, add three subscriptions. For each one:

    * **Step 1 (filter):** choose **One exact type** and enter `orders.created` (or a pattern like `orders.*` if the queue should react to more).
    * **Step 2 (target):** choose **Queue** and select `fulfillment`, then repeat for `billing` and `analytics`.
  </Step>

  <Step title="Publish an event">
    From your app, publish once:

    ```graphql theme={null}
    mutation {
      publishEvent(
        topic: "orders"
        eventType: "orders.created"
        payload: "{\"orderId\":\"A-1024\",\"total\":51.25}"
      ) { messageId }
    }
    ```

    Or use the topic's **Publish test** tab.
  </Step>

  <Step title="Watch the copies arrive">
    Open each queue — the **Pending** count on `fulfillment`, `billing`, and `analytics` each increases by one. Every subscribed queue got its own copy.
  </Step>

  <Step title="Let workers process each queue">
    Each worker runs its own loop — `receiveMessages` → do the work → `deleteMessage` — against its queue. They run independently and at their own pace. See [Queues](/docs/features/backend/app-services/queues-and-event-bus/queues#connect-your-app-to-a-queue) for the worker loop.
  </Step>
</Steps>

That's the whole pattern: **publish once, process in three isolated, retryable streams.**

## Together or separate — choosing per case

You don't have to combine them. Pick the shape that fits each need:

| Scenario                                                             | Shape                         | Setup                                                                            |
| -------------------------------------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------- |
| A single background job triggered directly by your app               | **Queue only**                | Send to a queue; a worker drains it.                                             |
| Notify one external partner when data changes                        | **Event Bus only**            | A topic with one external-endpoint subscription.                                 |
| One event, several **internal** reactions, each buffered and retried | **Together (topic → queues)** | One topic, one queue + subscription per reaction.                                |
| One event, a mix of internal writes and external notifications       | **Event Bus, mixed targets**  | One topic with several subscriptions (some Your API, some External, some Queue). |
| Broadcast **and** guarantee reliable processing of each copy         | **Together**                  | Fan out to queues; workers provide the reliability.                              |

## Recipes

<AccordionGroup>
  <Accordion title="Add a new reaction later, with zero risk">
    To make the system do one more thing when `orders.created` fires, create a new queue and subscribe it to the topic. Existing subscribers are untouched — they never know a new one was added. This is the safest way to grow an event-driven system.
  </Accordion>

  <Accordion title="Give one reaction its own retry policy">
    Because each reaction has its own queue, you can tune them independently. Give `billing` a longer **processing time** and more **max attempts** than `analytics`, for example — one queue's settings never affect another.
  </Accordion>

  <Accordion title="Mix a queue and a direct API write on the same topic">
    A topic can have both a **Queue** subscription (for heavy background work) and a **Your API** subscription (for a quick synchronous write) on the same event type. Each is independent.
  </Accordion>

  <Accordion title="Fan out to both internal and external systems">
    Subscribe a queue for your own processing and an **External endpoint** for a partner, both to `orders.created`. Your internal work and the partner notification happen in parallel, each retried on its own.
  </Accordion>

  <Accordion title="Replay a burst safely">
    If a downstream service was down, its queue simply accumulated the copies. When it recovers, its workers drain the backlog — no events were lost and nothing needs to be re-published.
  </Accordion>
</AccordionGroup>

## Keep it reliable

<Note>
  Two habits make an event-driven system dependable:

  1. **Make workers idempotent.** Delivery is *at least once*, so a copy may occasionally arrive twice. Key your writes on a stable identifier (like `orderId`) so a repeat is harmless.
  2. **Watch the error lists.** A non-empty dead-letter queue (a red badge on a queue) or a failing subscription in **Activity** is your early warning. Fix the cause, then redrive.
</Note>

## Next

<CardGroup cols={2}>
  <Card title="Reference & FAQ" icon="book" href="/docs/features/backend/app-services/queues-and-event-bus/reference">
    The full list of operations, limits, statuses, and troubleshooting.
  </Card>

  <Card title="Back to overview" icon="arrow-left" href="/docs/features/backend/app-services/queues-and-event-bus/overview">
    The concepts and when to use each service.
  </Card>
</CardGroup>
