Skip to content

Architecture

Capsule is a cross-platform photo service designed for professional and enthusiast photographers who expect fast syncing, seamless uploads, and powerful search—regardless of device or network conditions.

We need a high-performance backend with a modern, developer-friendly interface for building rich client apps on all platforms.

To achieve this, Capsule employs a hybrid API strategy that balances performance, flexibility, and reliability. Here’s a breakdown of the core technology decisions and why they were made.

  • Performance Optimization: Each data channel should use the best-fit protocol:
  • Developer Experience: UI and backend teams can move independently with tools tailored to their workflows.
  • Cross-Platform Consistency: Various data models should be serializable and deserializable across platforms.
  • Network Efficiency: Use binary formats where necessary to reduce payload size and energy use, especially on mobile.
  • Scalability: Decoupled subsystems (sync, search, uploads, UI) with differing performance requirements and domains must be able to scale independently.
TechnologyUse CaseBenefits
gRPC + Protocol BuffersBulk metadata sync, initial sync, delta updates- 60–80% smaller payloads than JSON
- Highly efficient for syncing thousands of records
- Strongly typed to reduce data corruption
GraphQLUI queries, search, and filtering- Ideal for flexible UI data needs
- Reduces API iteration cycles
- Great developer experience for frontend teams
HTTP + TUS ProtocolUploading and downloading original photo assets- Resume-capable uploads for poor networks
- CDN-compatible
- Built for large file transfers
WebSockets + Protocol BuffersReal-time sync status, presence, notifications- Efficient binary messaging
- Reuses existing protobuf models
- Low-latency delivery for system-level events
GraphQL SubscriptionsUser-facing real-time events (comments, shares, collab)- Easy to use in UI clients
- Strong typing
- Filtering and selective subscriptions
Offline-First ArchitectureLocal caching, editing, and sync- Guarantees smooth experience regardless of connectivity
- Local-first UX with background resolution and merge
  • For gRPC and gRPC-Web traffic, we use Envoy as proxy (or via Istio for Kubernetes deployments) because at the time of creation, it is the most mature and robust solution. As such, for Kubernetes deployments, Envoy needs to be installed as a sidecar on every pod hosting Capsule services using gRPC (e.g. capsule-metadata​)
  • Object storage vs. File storage: While we use object storage for ephermal storage, we use file storage for long-term storage. The use of object storage for the former needs no explanation (standard industry practice). However, for the latter, we use file storage for high-throughput and low-latency block-level access. For most self-hosted deployments, filesystems are also easier to manage and maintain. By storing (potentially large) files on file storage, we could save network bandwidth on back-and-forth copies and have faster block-level access essential to metadata and thumbnail generation.
  • Filesystems: While Kubernetes abstracts filesystem features behind POSIX standards. For consistency, we officially target and support ZFS and XFS via NFS and Ceph RBD

We prefer native client applications where possible for consistent UX and leveraging platform-specific features.

Capsule has several native clients for the following platforms: