Skip to content

Architecture Overview

SyncTV is a single-binary service. One process contains HTTP APIs, public gRPC, WebSocket realtime rooms, management gRPC, media providers, proxying, livestreaming, and cluster coordination.

Start with the single-node production model: clients reach SyncTV through a TLS reverse proxy or Ingress, SyncTV connects to PostgreSQL, and Redis is recommended for shared short-lived state.

Minimal production topology showing clients reaching SyncTV through a TLS reverse proxy or Ingress, with SyncTV connected to PostgreSQL and Redis. Minimal production topology showing clients reaching SyncTV through a TLS reverse proxy or Ingress, with SyncTV connected to PostgreSQL and Redis.
First production model: one SyncTV service entrypoint, PostgreSQL, and Redis. Redis is optional for simple single-node deployments and expected in production.

PostgreSQL is durable business state. Redis is shared short-lived state and coordination. data_dir is the local runtime file directory. When you need horizontal scaling, add multiple SyncTV replicas, shared PostgreSQL/Redis, a unified edge entrypoint, and an explicit HLS storage or publisher-node proxy model.

SyncTV architecture overview showing clients, ingress, the SyncTV single binary, PostgreSQL, Redis, external providers, and HLS storage. SyncTV architecture overview showing clients, ingress, the SyncTV single binary, PostgreSQL, Redis, external providers, and HLS storage.
SyncTV’s main boundaries: one process hosts business APIs, realtime collaboration, the management plane, media proxying, and livestreaming. Durable state goes to PostgreSQL, and cross-node short-lived state goes to Redis.
LevelUse caseRequired componentsExtra attention
Single-node productionSmall team or one serverSyncTV, PostgreSQL, production secretsRedis is recommended, backups are required
Temporary local evaluationUI preview or development preflightSyncTV, PostgreSQLDevelopment Compose secrets are acceptable only locally; do not use publicly or long term
Multi-replica productionHorizontal scaling, rolling updates, highly available entrypointsMultiple SyncTV instances, PostgreSQL, Redis, cluster secretSplit HTTP/gRPC Ingresses and choose an HLS model

API and realtime

HTTP REST, public gRPC, WebSocket, and room realtime events share the same business services and permission model.

Authentication

Password, OPAQUE, passkey/WebAuthn, email codes, OAuth2, user-level 2FA, and JWT tokens make up the login layer.

Media

Providers resolve external media, the proxy performs controlled forwarding, and slice cache stores Range slices only.

Horizontal scaling

Multi-node deployments use Redis, discovery, leader election, and transactional outbox delivery boundaries.

SurfaceDefault port or pathPurposeProduction guidance
HTTP RESTserver.port=8080Client API, health checks, OpenAPI UIExpose through a reverse proxy or Ingress
Public gRPCserver.port=8080gRPC API for clients or SDKsUse a separate Kubernetes Service and Ingress
WebSocketserver.port=8080Room realtime events, playback sync, chatConfigure connection limits and shutdown drain
Management gRPCUnix socket or management.port=50052CLI, administration, operational control planePrefer Unix socket; TCP requires a token
Metricsmetrics.port=9090Prometheus metricsKeep private and authenticated
RTMPlivestream.rtmp_port=1935Livestream publishingExpose only when livestreaming is used
STUN UDPwebrtc.stun_port=3478WebRTC NAT assistanceExpose only when built-in STUN is used

HTTP REST and public gRPC share the main process port, but Kubernetes deployments should still use separate Services and Ingresses. This lets the gRPC Ingress set nginx.ingress.kubernetes.io/backend-protocol: "GRPC" independently.

PostgreSQL is the durable system of record. Users, rooms, permissions, provider instances, user preferences, audit data, and business records live there.

Production requirements: startup runs embedded SQLx migrations automatically; maintain backup and restore procedures; keep connection pool sizing within database capacity; treat database migrations as rollback-sensitive.

  1. A client calls SyncTV through HTTP or gRPC.
  2. The API layer performs authentication, rate limiting, permission checks, and request parsing.
  3. Services read and write PostgreSQL, using Redis and L1 caches when configured.
  4. After transactional business changes commit, realtime changes are pushed to local WebSocket connections. In multi-replica mode, database outbox records and shared event channels deliver the event to other nodes. Some membership or runtime events use best-effort fanout and do not share the same database transaction boundary.
  1. A provider resolves a media URL and decides whether the client should fetch directly or through the proxy.
  2. The provider explicitly selects upstream headers such as User-Agent, Referer, Range, or authentication headers.
  3. The proxy layer uses provider-supplied headers only. It does not forward raw client headers by itself.
  4. Slice cache handles Range-capable upstreams only. If an upstream does not support Range, the proxy bypasses caching and does not store full-body responses.

Cluster mode is for multi-replica deployments. When cluster.enabled=true, Redis and cluster.secret are required.

Key settings:

SettingPurpose
cluster.discovery_modeNode discovery: redis, static, or k8s_dns
cluster.leader_election_modeBackground task leader election: redis or k8s_lease
server.advertise_hostAddress other nodes use to reach this node
cluster.secretAuthentication for inter-node gRPC calls
cluster.catchup_window_secsEvent replay window after short disconnects

For multi-replica deployments, also confirm:

  • All replicas share the same PostgreSQL database.
  • All replicas share the same Redis and redis.key_prefix.
  • WebSocket tickets must be cross-node capable, not node-local memory only.
  • Local HLS backends use publisher-node proxying. shared_file serves TS segments from the current node’s shared mount, and OSS provides object-storage-backed segment storage.
  • Kubernetes termination grace period is longer than server.shutdown_drain_timeout_seconds.

For the full runtime design, discovery modes, leader election, and clustered livestreaming boundaries, see Cluster Configuration.

The livestream path is separate from the on-demand proxy path. RTMP is the publishing entrypoint; HTTP-FLV serves low-latency playback; HLS remuxing produces playlists and segments into the selected memory, file, or oss backend. In multi-replica deployments, the publisher owner is exposed through a shared registry; today non-publisher nodes read playlists and segments through the HLS gRPC proxy to the publisher node. Shared filesystem storage or OSS is a storage and recovery boundary, not a signal that non-publisher nodes bypass the publisher and read segments directly.

For the RTMP/StreamHub/HTTP-FLV/HLS pipeline, backend selection, and clustered livestreaming failure boundaries, see Livestream Configuration.

Kubernetes multi-replica topology:

Kubernetes multi-replica topology showing HTTP Ingress, gRPC Ingress, separate Services, multiple SyncTV pods, PostgreSQL, Redis, HLS backend or publisher-node proxy, and external media providers. Kubernetes multi-replica topology showing HTTP Ingress, gRPC Ingress, separate Services, multiple SyncTV pods, PostgreSQL, Redis, HLS backend or publisher-node proxy, and external media providers.
Kubernetes multi-replica deployments should split HTTP and gRPC Services/Ingresses and connect every pod to the same PostgreSQL and Redis backends. Local HLS backends use publisher-node proxying; shared_file lets the current node read TS segments from a shared path, and OSS provides object-storage-backed segments.