Overview
Problem Statement
Indie developers and growing teams end up juggling a separate CDN provider, a separate object-storage provider, opaque pricing, and no unified access model — two bills, two dashboards, two SDKs for what should be one job.
Solution
A customer creates a zone pointing at their own origin server; RivoCloud's edge network caches and serves that traffic globally. Customers can also push files directly into RivoCloud's own object storage and serve them straight from the CDN with no origin server at all. Zones, uploads, domains, cache purges, analytics, and billing all live behind one dashboard, one REST API, and one identity/permissions model.
Architecture Overview
RivoCloud is deliberately split into two halves optimized for opposite things. The Control Plane ('the office') handles configuration and management — zones, billing, analytics — built for correctness and safety in TypeScript/NestJS microservices. The Data Plane ('the front counter') is the part that touches every visitor request, all day — built for raw speed in Go. The two communicate only through fast, disposable infrastructure (Redis for config, NATS for events), never by calling each other's APIs directly on the hot path — the single most important architectural decision in the system, since it means the CDN never gets slower no matter how much configuration logic the control plane accumulates.
Features
Origin-pull and origin-push CDN with a 3-layer cache (in-process, Redis, object storage)
Smart cache-key normalization, ETag/conditional requests, gzip + brotli compression, HTTP range requests
Bring-your-own domain with fully automatic TLS issuance and renewal via Let's Encrypt
S3-compatible object storage with presigned and multipart uploads
Per-path cache rules, instant global purge by path or tag propagated in seconds
HMAC-signed, time-limited URLs verified at the edge with zero origin round-trips
Real-time analytics: bandwidth, cache hit ratio, geography, P95 latency, status-code breakdowns
Organizations with role-based access control, scoped API keys, audit logging, rate limiting
Stripe-powered subscriptions with usage-based plan enforcement
Multiple physical edge PoPs with GeoDNS routing
Full REST API, a JS/TS SDK, and a Go CLI — every dashboard action is also a one-line script
Architecture Diagrams
Cache Hit Path
- Every request first checks an in-process L1 LRU cache — a hit here resolves in under a millisecond.
- On an L1 miss, the edge proxy checks L2 Redis (~0.5ms) and repopulates L1 from it.
- On a full miss, the proxy fetches from the customer's origin and populates both cache layers before responding, so the next visitor gets a fast hit.
System Overview
- The Control Plane (TypeScript/NestJS) owns configuration and management — identity, zones, storage, billing, analytics — built for correctness, not raw speed.
- The Data Plane is a single Go edge proxy built for one job: serve every visitor request as fast as possible, with a 3-layer cache in front of it.
- The two halves only communicate through Redis (published config) and NATS (invalidation/analytics events) — never by calling each other's APIs on the hot path.
System Scaling Path
- Started as a single machine running Docker Compose, then moved to a single VPS with monitoring once real usage began.
- Migrated to a self-healing k3s Kubernetes cluster with GitOps (ArgoCD) as the next real bottleneck was reliability, not raw compute.
- Expanded to multiple edge PoPs with GeoDNS, and finally to multi-region production scale — each stage added only once the previous one's actual limit was hit.
Global Traffic Routing
- GeoDNS routes each visitor to the nearest physical edge Point of Presence — EU traffic to the Nuremberg PoP, US traffic to the control-plane region's PoP.
- Each PoP serves cached content locally from its own edge proxy, so most requests never leave the region.
- PoPs stay in sync through a shared NATS cluster carrying configuration updates and cache invalidations, keeping every edge location consistent.
Upload & Cache-Invalidation Flow
- The customer app requests a presigned upload URL from the Storage Service and uploads the file directly to MinIO — no data passes through RivoCloud's own servers.
- MinIO confirms the upload via webhook, and the Storage Service publishes an object.uploaded event to NATS.
- A follow-up invalidation request fans out over NATS to every edge proxy at once, so the next visitor anywhere gets the fresh file instead of a stale cached copy.
Implementation Workflows
Technology Stack
Data Plane (Edge Proxy)
Control Plane Services
Frontend / Dashboard
Primary Database
Cache & Fast Store
Object Storage
Analytics Database
Messaging / Events
Reverse Proxy / TLS
Payments
SDK / CLI
Platform
Observability
Monorepo Tooling
CI/CD Pipeline
- Lint & typecheck across the monorepo (Turborepo runs only what changed)
- Unit tests per service
- Integration tests against real Postgres/Redis/MinIO in CI, not mocks
- Security scan (dependency + code scanning) before merge
- Build & push container images on merge to main
- Automatic deploy to staging for smoke-testing
- ArgoCD GitOps sync to production with health-check gating
- Blue/green cutover — instant revert if the new version fails health checks
Case Studies
The Indie SaaS Founder
A solo developer's SaaS product serves images and API responses from a single origin, and global users complain about load times while two separate CDN/storage bills and dashboards pile up. Pointing the app at RivoCloud collapses this to one zone with custom per-path TTL rules and one bucket serving user images directly through the CDN — one dashboard, one API key, one transparent usage-based bill.
The Media-Heavy E-Commerce Platform
A growing online store serves thousands of product images and needs instant purges whenever inventory photos change, since stale images showing the wrong product cost sales. Origin-push storage holds every image, cache rules cache aggressively, and a single invalidate-by-tag call purges every image tied to an updated product across every edge location within seconds.
The API-First Startup Team
A small engineering team needs to expose a versioned API to third-party developers with different access levels per teammate. Organizations with role-based access control (Owner/Admin/Developer/Viewer) scope exactly who can create zones, invalidate caches, or manage billing, enforced identically across dashboard, API, and CLI — zero custom permission code written by the team.
The DevOps-Forward Engineering Org
A platform team wants cache purges wired into their deploy pipeline instead of a manual dashboard click someone forgets. The Go CLI drops into any CI pipeline as a post-deploy step, and the JS/TS SDK covers anything triggered from application code — cache invalidation becomes part of the deploy pipeline itself.
Engineering Highlights
- Control plane / data plane split — configuration logic never runs on the request hot path, so the CDN's latency is decoupled from how much business logic the control plane accumulates.
- 16 sequenced build stages — infrastructure, then identity, then the core caching engine, then the management layer, then public-launch polish — each stage supplying something a later one depends on.
- Multi-layer cache architecture (in-process LRU, Redis, object storage) tuned for sub-millisecond hits at L1.
- GitOps deployment — ArgoCD treats Git as the single source of truth for what's actually running in the Kubernetes cluster, with blue/green cutover gated on health checks.
- Deliberate scaling path — single machine to single VPS to self-healing k3s cluster to multi-PoP edge to multi-region — each stage solving the bottleneck the previous one actually hit, not a hypothetical one.
