Contexto
O feed de notificações para telão (issue #146) precisa entregar notificações em tempo real. Duas abordagens concorrentes:
- Pool em memória: Worker mantém
Map<churchId, WritableStream[]>;POSTcria notificação e empurra para streams ativos. - Polling no D1: SSE endpoint faz
SELECTno D1 a cada 3s e emite notificações novas como eventos SSE.
Decisão
Usar polling no D1 (abordagem 2).
Consequências
Positivas
- Funciona com múltiplas instâncias Worker — Cloudflare escala horizontalmente sem perder notificações
- Sobrevive a deploys —
EventSourcereconecta e o polling recomeça dolastCheck - Mais simples de implementar e testar (sem gerenciamento de pool)
- Sem risco de memory leak por conexões órfãs
Negativas
- Latência de ~3s entre criação e exibição no telão (vs tempo real com pool)
- Custo de D1 queries: 1 query a cada 3s por conexão SSE ativa (~20/min)
- CPU time: polling é I/O-bound (D1 wait), não CPU-bound — não impacta limite de 30s
Mitigações
- 3s de latência é aceitável para telão de igreja (o pai já está sendo chamado presencialmente)
- D1 query é indexada por
(church_id, created_at)e retorna no máximo ~1 linha por polling - Se latência for problema no futuro, dá para migrar para pool sem quebrar clientes (EventSource é compatível)
Alternativas consideradas
| Alternativa | Motivo para rejeitar |
|---|---|
| Pool em memória | Perde conexões em deploy; não escala com múltiplas instâncias Worker |
| WebSocket com Durable Objects | Dependência de infraestrutura mais complexa; superdimensionado para MVP |
| D1 + Durable Object como broker | Complexidade desnecessária para o volume de notificações esperado |
Referências
- Cloudflare Workers Streams API: https://developers.cloudflare.com/workers/runtime-apis/streams/
- Workers duration limits: https://developers.cloudflare.com/workers/platform/limits/#duration
- Issue #146: https://github.com/barateza/neemias/issues/146
- Spec:
.specs/features/notifications/spec.md