Coop
Concepts

Message Queue

How Coop queues, prioritizes, retries, and handles failed messages.

Every outgoing message in Coop passes through a queue before it reaches the recipient. This isn't just a FIFO buffer — it handles prioritization, retries, expiration, and failure isolation. Understanding how it works helps you design integrations that handle edge cases gracefully.

Why a queue?

Sending an iMessage isn't instantaneous. The message needs to reach a Mac running Coop Desktop, the Mac needs to hand it to the Messages app, and the Messages app needs to deliver it through Apple's servers. Any of those steps can be slow or fail.

A queue decouples "I want to send a message" from "the message is being sent." Your API call returns immediately with a queued status, and the actual delivery happens asynchronously. This means your application doesn't block while waiting for Apple's infrastructure.

Priority

Each message has a priority score from 0 to 100. The queue processes higher-priority messages first. If you don't set a priority, the default is 0, which means standard FIFO ordering.

This matters when you have a mix of time-sensitive and routine messages. An appointment confirmation (priority: 90) should go out before a marketing follow-up (priority: 0), even if the follow-up was queued first.

Retries

When a message fails to send — the Mac is temporarily unreachable, iMessage returns an error, the network drops — the queue retries it with exponential backoff. Each attempt is logged so you can see exactly what happened.

The number of retries is configurable. After exhausting all attempts, the message moves to the dead letter queue.

Dead letter queue

The dead letter queue (DLQ) is where messages go after all retries fail. Messages in the DLQ have status failed and include the error from their last attempt.

The DLQ exists to prevent poison messages from blocking the rest of your queue. A message that consistently fails (bad phone number, iMessage account issue) gets moved aside so other messages keep flowing.

You can inspect the DLQ through the dashboard or API. The message.failed webhook fires when a message enters the DLQ.

TTL

Messages have a time-to-live — by default, 24 hours. If a message sits in the queue beyond its TTL without being processed, it expires and moves to the DLQ.

This prevents stale messages from being delivered hours or days late. If someone requested an appointment confirmation and it's been stuck for 12 hours, sending it now would be confusing, not helpful.

What to watch for

A growing pending count in queue stats usually means one of:

  • Your Mac is offline or Coop Desktop isn't running
  • You're sending messages faster than the Mac can process them
  • There's a network issue between the API and Coop Desktop

Check relay status first. If all Macs show as online but the queue keeps growing, you may need to connect additional Macs to increase throughput.

On this page