realtime-apis
Skill8 starsChanged 9 days agoMITView on GitHub
Designs and scales realtime features with polling, long polling, Server-Sent Events, WebSockets or webhooks, covering auth at connect time, heartbeats, reconnect and resume, ordering, backpressure, fan-out across instances, and deploys. Use when building live updates, chat, notifications, dashboards, collaborative editing or streaming responses, choosing between SSE and WebSockets, or debugging dropped connections, missed messages or connection limits. Not for request/response API design (use api-design).
In this repository60 other files it gives its agents.
- api-designSkill
- auth-implementationSkill
- background-jobsSkill
- building-agentsSkill
- caching-strategiesSkill
- ci-cd-pipelinesSkill
- cloud-cost-optimizationSkill
- codebase-onboardingSkill
- code-review-changesSkill
- concurrency-patternsSkill
- database-migrationsSkill
- database-schema-designSkill
- database-testingSkill
- data-pipelinesSkill
- data-privacy-retentionSkill
- dependency-upgradesSkill
- design-docsSkill
- design-systemsSkill
- dockerfilesSkill
- domain-driven-designSkill
- event-driven-architectureSkill
- file-storage-uploadsSkill
- frontend-securitySkill
- git-workflowSkill
- graphql-apisSkill
- grpc-servicesSkill
- incident-responseSkill
- infrastructure-as-codeSkill
- internationalizationSkill
- kubernetes-deploymentsSkill
- large-scale-migrationsSkill
- legacy-refactoringSkill
- llm-evalsSkill
- llm-integrationSkill
- mcp-serversSkill
- micro-frontendsSkill
- ml-experimentsSkill
- monorepo-managementSkill
- nosql-designSkill
- observabilitySkill
- orm-patternsSkill
- performance-profilingSkill
- postgres-operationsSkill
- rag-systemsSkill
- react-patternsSkill
- resilience-patternsSkill
- root-cause-debuggingSkill
- search-integrationSkill
- security-auditSkill
- seo-and-ssrSkill
- sql-optimizationSkill
- system-designSkill
- test-strategySkill
- threat-modelingSkill
- typescript-patternsSkill
- unit-testingSkill
- verify-before-doneSkill
- web-accessibilitySkill
- web-performanceSkill
- writing-skillsSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈5
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
Not for: REST/HTTP API design (see api-design).
- Distinctive: line 31
Default: SSE for server push to browsers, WebSockets only when the client must send frequent messages over the same channel.
- Very specific: line 37
Design the message envelope: every message has a type, a unique, increasing id per stream, and a timestamp.
- Distinctive: line 62
When the session expires or is revoked, close the connection (close code 1008, policy violation).
- Distinctive: line 84
Never let one slow client grow server memory without bound.
- Distinctive: line 99
Stop routing new connections to the old instance (mark it not-ready).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Realtime APIs
Connections drop: networks change, proxies time out, servers redeploy. Design so a client can reconnect and catch up without losing or duplicating messages, and so one server can be replaced without a reconnect storm. Choose the simplest transport that meets the latency and direction you actually need.
When to use
- Live updates (notifications, feeds, dashboards, job progress, order status).
- Chat, presence, multiplayer or collaborative editing.
- Streaming long responses to a browser (including LLM token streams).
- Choosing between polling, SSE, WebSockets and webhooks.
- Debugging dropped connections, missing or duplicated messages, or servers hitting connection limits.
Not for: REST/HTTP API design (see api-design); message brokers between backend services (see event-driven-architecture).
Choose the transport
| Need | Use | Why |
| Updates every 30 s+ are fine | Polling (with ETag / If-None-Match) | Simplest; works through every proxy and cache |
| Server-to-browser only, near real time | Server-Sent Events | Plain HTTP, built-in reconnect and resume |
| Two-way, low latency, frequent client messages | WebSockets | Full duplex over one connection |
| Server-to-server notifications | Webhooks | No open connection; see api-design for signing and retries |
| Legacy clients or proxies that break streaming | Long polling | Fallback only |
Default: SSE for server push to browsers, WebSockets only when the client must send frequent messages over the same channel. Each step up adds operational cost.
Workflow
- Write down the requirements: direction, latency target, messages per second per client, number of concurrent connections, whether missed messages must be recovered.
- Pick the transport from the table.
- Design the message envelope: every message has a
type, a unique, increasingidper stream, and a timestamp. Version the schema. Read references/protocol-details.md for an envelope, close codes and reconnect code. - Authenticate at connect time and authorize every subscription (rules below).
- Add heartbeats, reconnect with backoff and jitter, and resume from the last message ID.
- Handle backpressure for slow clients.
- Plan scaling and deploys: fan-out across instances, idle timeouts, connection limits, draining.
- Add metrics (list below) and load-test with the target number of connections before launch.
Server-Sent Events
- Response:
Content-Type: text/event-stream, kept open; each event isid:,event:,data:lines followed by a blank line. - The browser
EventSourcereconnects automatically and sends the last receivedidin theLast-Event-IDheader. The server must replay events after that ID from a buffer or log. - The server can set the reconnect delay with a
retry:field (milliseconds). EventSourcecan't set custom headers (onlywithCredentialsfor cookies). Use cookie auth, or a fetch-based SSE client if you need anAuthorizationheader.- Send a comment line (
: ping) every 15-30 s so proxies don't close an idle stream. - Disable response buffering in proxies (for example nginx
proxy_buffering off;or theX-Accel-Buffering: noresponse header) and in compression middleware, or events arrive in bursts. - Over HTTP/1.1, browsers limit concurrent connections per origin (commonly 6), and each SSE stream uses one. Serve over HTTP/2 or share one stream across tabs.
WebSockets
Auth at the handshake:
- The browser
WebSocketAPI can't set custom headers. Options:- Cookie session: the cookie is sent with the handshake. You must check the
Originheader against an allowlist, or any site can open an authenticated socket for your users (Cross-Site WebSocket Hijacking). - Short-lived ticket: the client gets a single-use token from an authenticated HTTP endpoint and passes it in the URL query. Expire it within seconds and keep it out of access logs.
- Cookie session: the cookie is sent with the handshake. You must check the
- Re-check authorization for every channel or room the client subscribes to, not only at connect.
- When the session expires or is revoked, close the connection (close code 1008, policy violation).
Liveness:
- Servers should send protocol ping frames and close connections that don't answer with a pong.
- Browser JavaScript can't send protocol pings. If the client needs to detect a dead connection, add an application-level heartbeat message.
Limits:
- Set a maximum message size and a per-connection message rate; close abusers.
- Validate every inbound message against a schema, just like an HTTP request body.
Reconnect and resume
- Reconnect with exponential backoff, full jitter and a cap (for example start at 1 s, cap at 30 s). Without jitter, every client reconnects at the same moment after an outage.
- On reconnect, the client sends the last message ID it processed. The server replays newer messages from a bounded buffer (in memory, Redis Streams, or a log), or tells the client to refetch full state if the gap is too old.
- Make client handlers idempotent: drop messages whose ID was already applied.
- Order is only guaranteed within one connection. If order matters across reconnects, rely on message IDs or sequence numbers, not arrival order.
Backpressure and slow consumers
- Each connection gets a bounded send queue. When it is full, either drop non-essential messages (for example older presence updates), coalesce (send only the latest state), or disconnect the client so it reconnects and resyncs.
- Never let one slow client grow server memory without bound.
- In the browser,
WebSocket.bufferedAmountshows unsent bytes; stop sending when it keeps growing.
Scaling connections
| Concern | What to do |
| Messages must reach clients on other instances | Fan out through a pub/sub layer (Redis pub/sub or Streams, NATS, Kafka, a cloud pub/sub service). Each instance subscribes to the channels its clients use |
| Sticky sessions | Needed only if a protocol keeps state across HTTP requests (for example long-polling fallbacks). Pure WebSocket and SSE connections stay on one instance anyway |
| Load balancer and proxy idle timeouts | Many default to about 60 s. Send heartbeats more often than the shortest timeout on the path |
| Per-instance limits | Raise file descriptor limits (ulimit -n), budget memory per connection, and watch ephemeral port limits on proxies |
| Autoscaling | Scale on connection count and memory, not only CPU |
Deploys and draining
- Stop routing new connections to the old instance (mark it not-ready).
- Tell connected clients to reconnect elsewhere: WebSocket close code 1001 (going away) or 1012 (service restart), or end the SSE stream.
- Spread the reconnects: clients use jittered backoff, or the server closes connections in batches over the drain window.
- Make the termination grace period longer than the drain window (see kubernetes-deployments).
Observability
Track per instance and in total:
- Open connections, connects and disconnects per minute, and close codes.
- Reconnect rate (a spike usually means a proxy timeout or a deploy problem).
- Messages sent and received per second; send queue depth; dropped messages.
- Delivery lag: time from event creation to send.
- Auth failures at handshake.
Anti-patterns
- WebSockets for one-way updates that SSE or polling would handle.
- Checking auth only at connect and never again for subscriptions or expiry.
- Cookie-authenticated WebSockets without an Origin check.
- No message IDs, so reconnecting clients silently miss events.
- Fixed reconnect delay with no jitter, causing a reconnect storm after each deploy.
- Unbounded per-connection buffers.
- In-memory fan-out only, which breaks as soon as there are two instances.
Done when
- The transport choice is written down with its reason.
- Clients survive a server restart and a network drop without losing or duplicating messages (tested by killing an instance during a load test).
- Handshake auth, per-subscription authz and Origin checks are in place.
- Heartbeats are shorter than every idle timeout on the path.
- Fan-out works across at least two instances.
- Connection, reconnect, queue and lag metrics are on a dashboard.
References
- references/protocol-details.md: read when writing the message envelope, close-code handling or client reconnect logic.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

