Vidivo is built as a set of independent microservices, each responsible for a distinct domain. Services communicate over HTTP/JSON internally (gRPC is planned for a later phase). The system is deployed on Docker Swarm with Traefik as the reverse proxy.
┌────────────────▼──┐ ┌───────▼────────────┐
│ api.vidivo.app │ │ signal.vidivo.app │
│ API Gateway │ │ Signaling Service │
│ (Echo v5) │ │ (WebSocket / Echo) │
└──┬──────────┬────┘ └────────────────────-┘
┌────────────┘ ┌─────┘ ┌────┘
┌──────┐ ┌────────────┐ ┌──────────────┐ ┌──────────────┐
│ Auth │ │ User │ │ Call │ │ Billing │
│ Svc │ │ Service │ │ Service │ │ Service │
└──┬───┘ └─────┬──────┘ └──────┬───────┘ └──────┬───────┘
┌──────────────────────────────────────────────────────────┐
│ (Primary + Read Replica planned) │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ Sessions · Call State · Signaling · Rate Limits │
└──────────────────────────────────────────────────────────┘
┌────────────────────┐ ┌──────────────┐ ┌────────────┐
│ Notification Svc │ │ Admin Svc │ │ Verif. │
│ (Email/Push/SMS) │ │ (internal) │ │ Service │
└────────────────────┘ └──────────────┘ └────────────┘
Service Path Responsibility api-gateway api.vidivo.appRequest routing, auth middleware, rate limiting auth /v1/auth/*Registration, login, JWT issuance, token refresh user /v1/users/*Profile management, role promotion, preferences call /v1/calls/*Call session lifecycle, signaling coordination signaling signal.vidivo.appWebSocket relay for WebRTC SDP/ICE exchange billing /v1/payments/*Stripe hold/capture, window billing, payouts notification Internal Email, push notifications, SMS (via Resend + FCM/APNs) verification /v1/verification/*Age verification via Xident integration admin admin.vidivo.appInternal dashboard for platform operations
Technology Version Role Go 1.26 All microservice runtimes Echo v5 HTTP framework (router, middleware, binding) GORM latest ORM for PostgreSQL golang-migrate latest Database schema migrations pion/webrtc v4 WebRTC (signaling, TURN) pion/turn v3 TURN server binary zap latest Structured JSON logging Prometheus latest Metrics collection
Store Version Role PostgreSQL 16 Primary relational database Redis 7 Sessions, call state, signaling, rate limits
Technology Version Role React 19 Web app and admin panel UI Vite 7 Build tool and dev server React Router v7 Client-side routing Zustand latest Global state management TanStack Query v5 Server state, caching, mutations Radix UI latest Accessible component primitives Tailwind CSS 4 Utility-first styling Stripe Elements latest Secure card input (PCI compliance)
Component Technology Notes Container orchestration Docker Swarm Not Kubernetes (simpler for single-region V1) Reverse proxy Traefik 3 Auto-discovery, Let’s Encrypt TLS CDN Cloudflare Web app, DDoS protection Object storage Cloudflare R2 Profile images, future media assets Email Resend Transactional emails Observability Prometheus + Grafana + Loki + Jaeger Metrics, logs, traces
│ 1. GET /c/{short_code} (Cloudflare CDN → Web App)
│ 2. GET /v1/links/{short_code} — fetch link metadata
│ POST /v1/auth/guest — obtain guest token
│ POST /v1/calls/initiate — place Stripe hold
API Gateway → Billing Service → Stripe API
│ 3. Signaling token issued
WebSocket → signal.vidivo.app
│ 4. SDP offer/answer exchanged
P2P WebRTC (direct or via TURN relay)
│ PaymentIntent (hold) created via Stripe API
│ → payment_transactions record (status: hold)
Window timer runs (Redis: call:{id}:timer)
│ At window_size - 60s: next hold placed
│ At window_size: current window captured
│ → Stripe captures PaymentIntent
│ → payment_transactions updated (status: captured)
Call ends (POST /calls/{id}/end)
│ Partial window captured
│ Remaining holds released
│ call_sessions record finalized
│ Host transfer initiated (Stripe Connect)
Payout sent to host bank (T+2 business days)
The platform uses approximately 12 core tables. Key tables:
Table Description usersAll user accounts (multi-role, soft deletes) call_linksShareable URLs with configuration call_sessionsActive and completed call records with JSONB quality metrics payment_transactionsPer-window Stripe PaymentIntent records guest_sessionsAnonymous caller sessions with card reference verification_recordsAge verification results from Xident stripe_accountsHost Stripe Connected Account references notificationsDelivery log for all notifications
All primary keys use ULID format. All timestamps use TIMESTAMPTZ (UTC). Soft deletes are implemented on all user-facing tables for GDPR compliance.
Hostname Backend Notes vidivo.appCloudflare CDN Web app (React PWA) api.vidivo.appTraefik → API Gateway REST API signal.vidivo.appTraefik → Signaling WebSocket (sticky sessions required) turn.vidivo.appDirect to TURN VPS UDP 3478 / TCP 5349 — no proxy admin.vidivo.appTraefik → Admin Admin panel docs.vidivo.appCloudflare CDN This documentation site
│ Validate JWT (RS256, public key from JWKS)
│ Check token expiry, role claims
Access tokens are signed with a private RSA key held only by the auth service. All other services validate tokens using the public key available at /.well-known/jwks.json. This means no service-to-service token sharing is needed.
Passwords : bcrypt with cost factor 12
Media : DTLS-SRTP (mandatory, browser-enforced)
Transport : TLS 1.2+ enforced by Traefik
Card data : Never touches Vidivo servers (Stripe Elements)
TURN credentials : HMAC-SHA1 time-limited (24h expiry, RFC 5389)
All services emit:
Structured JSON logs via zap, collected by Loki
Prometheus metrics scraped every 15s, visualized in Grafana
Distributed traces via OpenTelemetry → Jaeger
Key dashboards (planned):
Active calls and concurrent sessions
Billing success/failure rate
TURN usage percentage
API latency percentiles (p50, p95, p99)
WebRTC connection failure rate