Skip to content

Behavior & limits ​

How the SDK behaves at runtime — worth understanding before you ship. For the full “not a bug” list see Limitations. For storage split (Intercom vs Postgres) see Data model.

Message delivery (polling) ​

There is no WebSocket. The SDK polls the backend (default every 4s, pollingInterval). On failure the interval backs off (4s → 8s → 16s → max 30s) and resets on success. Tickets poll less often (~20s). Comment threads poll ~5s while open.

Message statuses ​

User messages show delivery ticks:

TickMeaning
🕓sending
✓sent / accepted by the backend
✓✓ (tinted)seen — an operator replied after this message
⚠ (red)failed — tap to retry (chat only)

"Seen" and "typing" caveat

Intercom does not expose real read-receipts or operator typing, and there is no WebSocket:

  • sent / delivered-to-backend are real.
  • seen is inferred when an operator message follows.
  • Live typing is not a real presence signal (mock mode fakes it for demos).

Error states ​

The SDK never shows a blank screen. Localized panels cover:

  • Session expired (401) → onSessionExpired, re-login.
  • Offline (web: navigator.onLine) → recovers on reconnect.
  • Support unavailable (backend / Intercom down) → retry.

Resilience (backend) ​

  • Circuit breaker on Intercom (opens after consecutive failures, then probes).
  • Rate limit per user on /api/* (429 + Retry-After).
  • Read coalescing cache so concurrent polls share one Intercom call (in-process — see scale notes).

Scale ​

Intercom allows on the order of ~10k API calls/min per app. With 4s polling that is roughly a ~660 concurrent active-user ceiling before caching and ticket-poll decoupling matter. Beyond one API instance, move cache + rate limits to Redis — Deployment.

Request lifecycle ​

The user sees one continuous thread; each support request is its own Intercom conversation (open / closed / snoozed):

  1. No continuable request → pick a topic (admin-managed reasons) → request starts.
  2. Open or snoozed → composer replies into that conversation (a reply unsnoozes in Intercom).
  3. Closed within the reopen window (default 5 days, INTERCOM_REOPEN_WINDOW_DAYS; mirrors Intercom Messenger) → the next message is a reply that reopens the same conversation, and the canned first-message acknowledgement is posted again. CSAT stays visible until that reply succeeds.
  4. Closed after the window → pick a topic; a new Intercom conversation appends below; history remains.
  5. Stars persist in Postgres (csat_ratings) — one row per close-cycle (a reopen + later close asks again).

State updates arrive on the next message poll (~4s) without reload.

Single thread, many tickets ​

One ongoing support thread per user (sequential requests) and any number of tickets (also Intercom). Replying to a resolved ticket reopens it. A chat that support converts into a ticket keeps its history in the support thread, followed by a system line with the ticket number. Conversion does not close the request: the user keeps chatting until an admin closes the conversation in Intercom, and only then CSAT is asked.

Hub Archive ​

The Archive shortcut opens a Coming soon placeholder — not a defect.

AW Chat SDK — integration & platform handoff docs.