Skip to content

feat(realtime): websocket fan-out server and typed realtime client - #2

Merged
pulkitxm merged 9 commits into
mainfrom
feat/realtime
Jul 22, 2026
Merged

feat(realtime): websocket fan-out server and typed realtime client#2
pulkitxm merged 9 commits into
mainfrom
feat/realtime

Conversation

@pulkitxm

Copy link
Copy Markdown
Member

Adds the apps/realtime websocket server (session auth, scope authorization, batched Redis fan-out, presence, heartbeat, health, graceful shutdown) and the @orbit/realtime-client package with React bindings.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 3 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea293b2f-3f80-4ec0-9d03-80001c1b9783

📥 Commits

Reviewing files that changed from the base of the PR and between 67249ac and eab0388.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • apps/realtime/package.json
  • apps/realtime/src/auth.ts
  • apps/realtime/src/client-reconnect.test.ts
  • apps/realtime/src/connection.test.ts
  • apps/realtime/src/connection.ts
  • apps/realtime/src/env.ts
  • apps/realtime/src/index.ts
  • apps/realtime/src/logger.ts
  • apps/realtime/src/presence.ts
  • apps/realtime/src/server.test.ts
  • apps/realtime/src/server.ts
  • apps/realtime/src/test-helpers.ts
  • apps/realtime/tsconfig.json
  • apps/realtime/vitest.config.ts
  • packages/db/src/schema/index.test.ts
  • packages/realtime-client/package.json
  • packages/realtime-client/src/index.ts
  • packages/realtime-client/src/react.test.tsx
  • packages/realtime-client/src/react.tsx
  • packages/realtime-client/tsconfig.json
  • packages/realtime-client/vitest.config.ts
  • packages/shared/src/events/index.test.ts

Comment @coderabbitai help to get the list of available commands.

@pulkitxm

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pulkitxm
pulkitxm merged commit 7f1ee35 into main Jul 22, 2026
4 checks passed
@pulkitxm

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@pulkitxm

Copy link
Copy Markdown
Member Author

Captured demo: two clients, one Redis publish

Throwaway script boots the built server (node apps/realtime/dist/index.js), opens two websocket
clients with a real session token, and publishes 5 SyncActions to orbit:delta in a single Redis
round trip. Timestamps are relative to process start, every frame is printed exactly as received.

+  73ms  server   {"level":"info","message":"realtime listening","at":"2026-07-22T18:39:06.212Z","service":"realtime","port":3101}
+ 224ms  demo     GET /health -> {"status":"ok","connections":0,"subscriptions":0,"redis":"ready"}
+ 245ms  beta     RECV {"type":"ready","connectionId":"defadf9b-b4e2-43a2-a3b5-143afa5ae610","userId":"user_demo","organizationId":"org_demo","scopes":[]}
+ 245ms  server   {"level":"info","message":"connection ready","at":"2026-07-22T18:39:06.383Z","service":"realtime","connectionId":"defadf9b-b4e2-43a2-a3b5-143afa5ae610","userId":"user_demo","organizationId":"org_demo"}
+ 245ms  server   {"level":"info","message":"connection ready","at":"2026-07-22T18:39:06.384Z","service":"realtime","connectionId":"5edf79cb-64ea-4e49-8d4b-0bca04c25bc3","userId":"user_demo","organizationId":"org_demo"}
+ 245ms  alpha    RECV {"type":"ready","connectionId":"5edf79cb-64ea-4e49-8d4b-0bca04c25bc3","userId":"user_demo","organizationId":"org_demo","scopes":[]}
+ 380ms  alpha    SEND {"type":"subscribe","scopes":["team:team_demo"]}
+ 380ms  beta     SEND {"type":"subscribe","scopes":["org:org_demo","team:team_nope"]}
+ 382ms  alpha    RECV {"type":"subscribed","scopes":["team:team_demo"]}
+ 382ms  beta     RECV {"type":"subscribed","scopes":["org:org_demo"]}
+ 781ms  demo     publishing 5 actions to redis in a single round trip
+ 916ms  demo     all 5 actions are now on the redis channel, 50ms batch window opens
+ 960ms  alpha    RECV delta (3 action(s) in 1 frame) [issue_102#1002:{"title":"other issue"}, issue_101#1003:{"title":"newest write for issue_101"}, issue_103#1004:{"title":"third issue"}]
+ 960ms  beta     RECV delta (1 action(s) in 1 frame) [issue_204#1005:{"title":"org scoped only"}]

VERDICT
  batching        alpha received 1 delta frame(s) for 4 published actions
  dedupe          alpha actions: issue_102#1002, issue_101#1003, issue_103#1004 (issue_101#1001 collapsed into #1003)
  ordering        syncIds ascending: 1002 < 1003 < 1004
  scope isolation beta actions:  issue_204#1005 (never saw the team scoped writes)
  authorization   beta subscribed set: ["org:org_demo"] (team:team_nope refused)
  result          PASS

+1719ms  demo     sending SIGTERM for graceful shutdown
+1719ms  server   {"level":"info","message":"shutting down","at":"2026-07-22T18:39:07.858Z","service":"realtime","signal":"SIGTERM"}

What the transcript proves, line by line:

Behaviour Evidence
Session auth over ?token= ready frame carries the resolved userId and organizationId
Scope authorization beta asked for team:team_nope, the accepted set came back as ["org:org_demo"] only
50ms coalescing 5 publishes land at +916ms, one delta frame per client at +960ms
De-duplication issue_101 published twice (#1001, #1003), only the newest survives
syncId ordering 1002 < 1003 < 1004 inside the frame
Scope isolation alpha never saw issue_204, beta never saw any team: write
Health endpoint {"status":"ok","connections":0,"subscriptions":0,"redis":"ready"}
Graceful shutdown SIGTERM logged, sockets closed with 1001, process exits

Test run

$ vitest run --reporter=verbose        (apps/realtime)
 ✓ src/server.test.ts > fan-out > delivers a delta only to connections subscribed to the scope 335ms
 ✓ src/server.test.ts > fan-out > never delivers a delta from another organization 250ms
 ✓ src/server.test.ts > fan-out > batches rapid actions into one delta and collapses duplicates 329ms
 ✓ src/server.test.ts > authorization > rejects an expired session with 4001 8ms
 ✓ src/server.test.ts > authorization > rejects an unknown token with 4001 3ms
 ✓ src/server.test.ts > authorization > drops scopes for organizations and teams the connection does not belong to 4ms
 ✓ src/server.test.ts > authorization > drops an issue scope owned by a team the connection does not belong to 13ms
 ✓ src/server.test.ts > authorization > never fans out to a connection whose subscription was refused 245ms
 ✓ src/server.test.ts > protocol > answers a ping with a pong 10ms
 ✓ src/server.test.ts > protocol > unsubscribes and stops receiving deltas 248ms
 ✓ src/server.test.ts > protocol > reports an invalid message without closing the socket 4ms
 ✓ src/server.test.ts > protocol > serves health with connection and redis status 12ms
 ✓ src/server.test.ts > presence > broadcasts to others in the scope but not to the sender 252ms
 ✓ src/server.test.ts > presence > refuses presence on a scope the connection cannot access 6ms
 ✓ src/server.test.ts > liveness > terminates a connection that stops answering heartbeats 413ms
 ✓ src/client-reconnect.test.ts > reconnects and resubscribes after the server drops the socket 483ms
 ✓ src/connection.test.ts > Connection > coalesces queued actions into one ordered, de-duplicated delta 2ms
 ✓ src/connection.test.ts > Connection > drops a connection whose outbound buffer exceeds the threshold 0ms
 ✓ src/connection.test.ts > Connection > caps the number of subscriptions per connection 0ms
 ✓ src/connection.test.ts > Connection > only matches actions from its own organization 0ms
 Test Files  3 passed (3)
      Tests  20 passed (20)
   Duration  3.44s

$ vitest run --reporter=verbose        (packages/realtime-client)
 ✓ src/react.test.tsx > RealtimeProvider under StrictMode > opens exactly one socket and keeps it across the double mount 11ms
 ✓ src/react.test.tsx > RealtimeProvider under StrictMode > subscribes to each scope once no matter how many consumers retain it 7ms
 ✓ src/react.test.tsx > RealtimeProvider under StrictMode > closes the socket once the provider truly unmounts 11ms
 Test Files  1 passed (1)
      Tests  3 passed (3)

$ pnpm typecheck && pnpm test          (all workspaces)
 Tasks:    4 successful, 4 total
@orbit/db:test:               Tests  1 passed (1)
@orbit/shared:test:           Tests  4 passed (4)
@orbit/realtime-client:test:  Tests  3 passed (3)
@orbit/realtime:test:         Tests 20 passed (20)
 Tasks:    4 successful, 4 total

$ pnpm check-comments
0 disallowed comment(s) in 0 file(s) (0 directive(s) ignored).
OK: no disallowed comments found.

CI on this branch: Build, Lint, comments, types, and Unit and integration tests all green.

@pulkitxm
pulkitxm deleted the feat/realtime branch July 22, 2026 19:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant