Messaging, WebSocket, and presence
The durable chat model is Postgres: conversations, conversation_participants, messages, attachments, reactions, pins, and user_chat_settings. SendMessageUseCase commits the message and an outbox row (messaging.direct-message-received or messaging.group-message-received). Notification-service turns that into push. The recipient who is online also gets a live frame.
Live delivery is a second path that is allowed to be lossy:
- Client
POST /v1/messaging/ws-ticket. - Client opens
/api/v1/messaging/wsthrough Kong.JwtWebSocketHandshakeInterceptorchecks the ticket or token. RedisMessageEventPublisherpublishes on a Redis pub/sub channel. Every messaging node runsRedisWsEventSubscriberand writes to local sockets.- Presence uses Redis (
RedisPresenceService,BulkGetPresenceUseCase) and is not a Postgres table.
If Redis pub/sub fails, history still loads over REST. Do not "fix" a missed live frame by writing a second message row.
Group chats that mirror social groups use SyncSocialGroupMembershipUseCase and inbox handlers for delete, rename, avatar, ownership, and member active flags. The source of truth for membership of a social group remains social-service.
Rate limiting on send is in-process Redis (MessagingRateLimiter), in addition to any Kong limit on the route. Typing (PublishTypingUseCase) is ephemeral and must not create an outbox row.