Skip to main content

Microservices

Every service is NestJS + TypeScript, has its own package.json, its own Dockerfile target, and a clear responsibility. None of them share a database connection string in the deployed target shape; the MVP shares one Postgres schema (see Database) as a documented, temporary shortcut.

API Gateway

Nginx or Traefik. Routing, WebSocket upgrade, rate limiting, load balancing, request-size limits. No business logic ever lands here — see Ingress for the actual nginx.conf shape.

Auth Service

Registration, login, logout, JWT access tokens, refresh-token rotation, OAuth (Google/GitHub), session management, password management, account verification. Full flow: Auth & Permissions.

User Service

User profiles, avatars, settings, devices, friend relationships, user status.

Server Service

Servers (Discord-style "guilds"), members, roles, permissions, channel management, invitations, server settings. Owns the effective-permission resolver (roleDefaults ∪ customRoles ∪ granted \ denied) that chat, call and presence all call into via @betweenus/database.

Chat Service

Text channels, direct messages, messages, editing, deletion (tombstones), replies, reactions, attachments, message history. Realtime fanout over WebSocket (/ws/chat), Redis Pub/Sub between instances.

Presence Service

Online / offline / idle status, typing indicators, activity status. All state lives in Redis — presence-service holds nothing durable. /ws/presence.

Notification Service

Raises no notifications itself — the desktop client already receives every message over /ws/chat and is the only thing that knows what's on screen. What it owns is the state that has to outlive the client: mutes, quiet hours, read markers, and (phase 27) minting the data-only FCM push that tells a backgrounded device something happened.

Call Service

Call signalling only (/ws/call): who may join which call, the roster of peers, relaying offers/answers/ICE candidates, handing out ICE server config. Call Service never sees media — it is a switchboard, not an SFU. See Peer-to-Peer Media.

Remote Gateway

Session handshake, offer/answer/ICE relay for the remote-desktop peer connection, mouse/keyboard/clipboard event relay, permission enforcement, audit trail. Never carries the screen itself. See Remote Desktop.

Remote Agent

A scaffold for a headless agent. In practice the desktop app is the agent on a machine somebody uses — it already has desktopCapturer, a WebRTC publisher and safeStorage for the enrollment credential, so a second process duplicating that would be scaffolding for its own sake.

Rules every service follows

  • Controllers are thin; services hold business logic; repositories handle persistence.
  • No service reaches into another service's database directly — they call APIs, or publish/subscribe to events (see Events).
  • Every service exposes /health, and it says nothing sensitive.
  • TypeScript strict mode; no any; typed DTOs and typed events.