System Architecture
Vidivo is built as a set of independent microservices, each responsible for a distinct domain. Services communicate over HTTP/JSON internally. The system is deployed on Docker Swarm with Traefik as the reverse proxy.
System Diagram
Section titled “System Diagram” +-------------------------+ | Clients | | Web . iOS . Android . | | Admin Panel | +-----------+--------------+ | HTTPS +-----------v--------------+ | Traefik 3 | | Reverse Proxy / TLS | +---+------------------+---+ | | +---------------v---+ +---------v-----------+ | api.vidivo.app | | signal.vidivo.app | | API Gateway | | Signaling Service | | (Echo v5) | | (WebSocket) | +---+----------+----+ +---------------------+ | | +------------+ +-----+ | | v v +------+--+ +----------+--+ +----------+ +----------+ | Auth | | User | | Call | | Billing | | Service | | Service | | Service | | Service | +---------+ +-------------+ +----------+ +----------+ +----------+ +----------+ +----------+ +------------+ | Chat | | Follow | | Notif | | Support | | Service | | Service | | Service | | Service | +----------+ +----------+ +----------+ +------------+ +----------+ +----------+ | Verif. | | Admin | | Service | | Service | +----------+ +----------+ | | | | v v v v +----------------------------------------------+ | PostgreSQL 17 (Neon) | +----------------------------------------------+ +----------------------------------------------+ | Redis 8 | | Sessions . Call State . Signaling . Limits | +----------------------------------------------+
External: Stripe . FCM . Resend . Xident . Cloudflare R2
+------------------------+ | turn.vidivo.app | | TURN Server | | (pion/turn v4, VPS) | | UDP 3478 / TCP 5349 | +------------------------+The Twelve Services
Section titled “The Twelve Services”| Service | Path | Responsibility |
|---|---|---|
| API Gateway | api.vidivo.app | Route aggregation, auth middleware, rate limiting, CORS |
| Auth | /v1/auth/* | Registration, login, JWT issuance, token refresh, OAuth, guest sessions |
| User | /v1/users/* | Profile CRUD, avatar upload, host onboarding, availability scheduling |
| Call | /v1/calls/*, /v1/schedule/* | Call links, sessions, history, scheduling, calendar invites |
| Billing | /v1/payments/* | Stripe hold/capture, earnings, payouts, invoices, data export |
| Chat | /v1/chat/* | Real-time messaging, WebSocket hub, file sending, broadcast |
| Follow | /v1/users/:id/follow* | User follows host system |
| Signaling | signal.vidivo.app | WebSocket relay for WebRTC SDP/ICE exchange |
| Notification | /v1/notifications/* | In-app notifications, FCM push delivery, email |
| Support | /v1/support/* | Support ticket system with threaded messages |
| Verification | /v1/verification/* | Age verification via Xident integration |
| Admin | /v1/admin/* | User/call management, stats, notification broadcast, refunds |
Technology Stack
Section titled “Technology Stack”Backend
Section titled “Backend”| 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) |
| pion/turn | v4 | TURN server binary |
| slog | stdlib | Structured JSON logging |
| Prometheus | latest | Metrics collection |
Data Stores
Section titled “Data Stores”| Store | Version | Role |
|---|---|---|
| PostgreSQL | 17 | Primary relational database (Neon in production) |
| Redis | 8 | Sessions, call state, signaling, rate limits, presence |
| Cloudflare R2 | - | Object storage (avatars, invoices) |
Frontend
Section titled “Frontend”| 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) |
Mobile
Section titled “Mobile”| Platform | Technology | Architecture |
|---|---|---|
| iOS | Swift + SwiftUI | MVVM + Clean Architecture, min iOS 16 |
| Android | Kotlin + Jetpack Compose | MVVM + Clean Architecture, min SDK 26 |
Infrastructure
Section titled “Infrastructure”| 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, invoices |
| Resend | Transactional emails | |
| Push notifications | Firebase Cloud Messaging | iOS, Android, Web push |
| Observability | Prometheus + Grafana + Loki + Jaeger | Metrics, logs, traces |
Clean Architecture
Section titled “Clean Architecture”Each service follows a consistent Clean Architecture pattern:
internal/<service>/+-- router.go -- RegisterRoutes(), dependency wiring+-- handler/handler.go -- HTTP handlers (parse request -> call service -> respond)+-- service/service.go -- Business logic (orchestrates repos + external clients)+-- repository/ -- Database access via GORM+-- dto/ -- Request/response typesKey conventions:
- Handlers only parse HTTP requests and format responses
- Business logic lives exclusively in the service layer
- Repository methods accept and return GORM models
- DTOs are the contract between handlers and services
- Functional options pattern for optional dependencies (e.g.,
WithBilling(),WithNotifier())
Data Flow Overview
Section titled “Data Flow Overview”Guest Call Initiation Flow
Section titled “Guest Call Initiation Flow”Guest Browser | | 1. GET /c/{short_code} (Cloudflare CDN -> Web App) vWeb App (React) | | 2. GET /v1/calls/links/{shortCode}/info -- fetch link metadata | POST /v1/auth/guest-session -- obtain guest token | POST /v1/payments/guest/setup-intent -- get Stripe client secret | POST /v1/calls/join/{short_code} -- place hold, create session vAPI Gateway -> Billing Service -> Stripe API | | 3. Signaling token + TURN credentials issued vWebSocket -> signal.vidivo.app | | 4. SDP offer/answer exchanged vP2P WebRTC (direct or via TURN relay)Billing Data Flow
Section titled “Billing Data Flow”Call starts | | PaymentIntent (hold) created via Stripe API | -> payment_transactions record (status: hold) vWindow timer runs (Redis: billing:{id}:state) | | At window_size - 60s: next hold placed | At window_size: current window captured | -> Stripe captures PaymentIntent | -> payment_transactions updated (status: captured) | -> Invoice PDF generated (fire-and-forget) | -> Notification created + email receipt sent vCall ends (POST /v1/calls/{id}/end) | | Partial window captured | Remaining holds released | call_sessions record finalized vHost requests payout -> Stripe Payout to bankDatabase Schema Overview
Section titled “Database Schema Overview”The platform uses 16+ tables across 18 migrations. Key tables:
| Table | Description |
|---|---|
users | All user accounts (multi-role, soft deletes) |
call_links | Shareable URLs with configuration |
call_sessions | Active and completed call records |
scheduled_calls | Booked future calls |
payment_transactions | Per-window Stripe PaymentIntent records |
host_payouts | Payout requests and status tracking |
invoices | Invoice records with R2 storage keys |
guest_sessions | Anonymous caller sessions |
user_follows | Follower relationships |
conversations | Chat conversation metadata |
conversation_participants | Chat participants with read tracking |
messages | Chat messages |
notifications | In-app notification records |
push_tokens | FCM device tokens |
support_tickets | Support ticket records |
ticket_messages | Threaded ticket replies |
verification_records | Age verification results |
stripe_accounts | Host Stripe Connected Account references |
All primary keys use UUID format. All timestamps use TIMESTAMPTZ (UTC). Soft deletes are implemented on user-facing tables for GDPR compliance.
DNS Architecture
Section titled “DNS Architecture”| Hostname | Backend | Notes |
|---|---|---|
vidivo.app | Cloudflare CDN | Web app (React PWA) |
api.vidivo.app | Traefik -> API Gateway | REST API |
signal.vidivo.app | Traefik -> Signaling | WebSocket (sticky sessions required) |
turn.vidivo.app | Direct to TURN VPS | UDP 3478 / TCP 5349 --- no proxy |
admin.vidivo.app | Traefik -> Admin Panel | Admin panel |
docs.vidivo.app | Cloudflare CDN | This documentation site |
Security Architecture
Section titled “Security Architecture”Authentication Flow
Section titled “Authentication Flow”Client -> API Gateway | | Validate JWT (RS256, public key from JWKS) | Check token expiry, role claims v Upstream ServiceAccess 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.
Data Protection
Section titled “Data Protection”- 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)
Observability
Section titled “Observability”All services emit:
- Structured JSON logs via slog, collected by Loki
- Prometheus metrics scraped every 15s, visualized in Grafana
- Distributed traces via OpenTelemetry -> Jaeger
Key dashboards:
- Active calls and concurrent sessions
- Billing success/failure rate
- TURN usage percentage
- API latency percentiles (p50, p95, p99)
- WebRTC connection failure rate