Skip to main content

10 — Real-Time Communication Strategy

Decision Date: 2026-03-31 Impact: R1-7 (Onboarding), R2-2 (Batch), R3+ (Notifications) Reference: Polling vs WebSocket vs SSE analysis

Problem

  • AI discovery, headhunt, and batch operations can take 5–30+ seconds. The user stares at a blank screen during this time — poor UX.
  • A notification system will be needed in the future (new lead, discovery completed).
  • AI defaults to classic request/response. If live updates are needed, a conscious decision must be made.

Pattern Comparison

PollingWebSocketSSE
MechanismClient asks the server at intervalsPersistent bidirectional connectionPersistent one-way connection (server → client)
DirectionClient → Server (repeatedly)Client ↔ ServerServer → Client
SetupEasyHard (connection mgmt, scaling)Easy (runs over HTTP)
EfficiencyLow (empty requests)HighHigh
Use CaseSimple dashboard, status checkChat, co-editing, gamesProgress bar, notifications, live feed
Next.js Compatibilityfetch + setIntervalExtra library (socket.io)Route Handler + ReadableStream (native)

Decision: SSE Primary, Polling for Simple Tasks

Why NOT WebSocket?

  1. Cernio has no bidirectional communication need (no chat, no co-editing).
  2. WebSocket scaling is hard — connection management adds overhead on Hetzner VPS.
  3. Next.js App Router has no native WebSocket support — requires extra server/library.
  4. MVP principle: simplest solution = SSE.

Why NOT Polling Only?

  1. With 1000 users, 500 empty requests per second — server gets overloaded.
  2. Cannot show progress for long-running operations (discovery 10s, batch minutes).
  3. “Ring the bell when it arrives” is better than “Is there a notification? Is there? Is there?”

Pattern Selection Matrix

ScenarioPatternReason
Onboarding Discovery (ONBOARD-5)SSEAI search 5–15s. Progress + result streaming.
Batch Operations UI (R2-2)SSEMinutes-long operation. Progress streaming. Already specified as SSE in TODO.
Admin Dashboard metrics (R2-3)Polling (30s)Simple, infrequently updated data. Over-engineering unnecessary.
Notification system (R3+)SSE”New lead”, “Discovery completed” → one-way, server push.
Live chat (IF NEEDED, R3+)WebSocketBidirectional required. However, chat is not in Cernio’s scope.

Architecture

SSE Handler Pattern (to be created in R1-7)

// lib/api/createSSEHandler.ts
// createHandler()-like wrapper — SSE endpoint with auth and rate limiting

export function createSSEHandler(config, handler) {
  return async (request) => {
    // Auth + rate limit (from createHandler)
    // Create ReadableStream
    // handler calls stream.write() to send events
    // Content-Type: text/event-stream
  }
}

// Usage:
export const POST = createSSEHandler({
  auth: true,
  rateLimit: { limit: 5, window: 60 },
}, async (request, session, stream) => {
  stream.write({ event: 'progress', data: { step: 1, message: 'Searching...' } })
  // ... AI call
  stream.write({ event: 'result', data: { companies: [...] } })
  stream.close()
})

Client-Side Hook

// lib/hooks/useSSE.ts
// EventSource wrapper — reconnect, error handling, typed events

Implementation Order

#WhatRingDependency
1createSSEHandler wrapperR1-7 (with ONBOARD-5)createHandler exists
2useSSE client hookR1-7 (with ONBOARD-5)
3Onboarding Discovery SSER1-7 ONBOARD-5#1, #2
4Batch Operations SSER2-2#1, #2
5Notification SSE (optional)R3+#1, #2

Future Decisions

FD-1: WebSocket Migration (R4+)

If Cernio requires chat or live collaboration, a WebSocket migration is possible. For now, SSE is sufficient.

FD-2: Supabase Realtime (R3+)

Supabase’s own Realtime feature (WebSocket over PostgreSQL LISTEN/NOTIFY) to be evaluated for the notification system. Advantage: DB change → instant push to client. Disadvantage: increases Supabase dependency.

FD-3: Redis Pub/Sub (R4+)

When horizontal scaling is needed on Hetzner VPS, SSE events can be distributed via Redis Pub/Sub. Not needed on a single VPS.