Back to Journal
Engineering |
January 15, 2026
10 min read

Building Offline-First Desktop Agents: The TimePerch Architecture

A deep dive into the polyglot architecture behind TimePerch: Rust for the client, Go for the network, Python for data processing, and SvelteKit for the dashboard.

ArchitectureRustGoOffline-FirstTimePerch

Building Offline-First Desktop Agents: The TimePerch Architecture

When we set out to build TimePerch, a workforce analytics platform, we faced a fundamental challenge: how do you build software that works reliably when the network doesn't?

This is the story of how we architected a 5-layer polyglot system that handles network instability without data loss.

The Problem

Traditional employee monitoring tools assume a stable internet connection. But reality is messier:

  • Field workers in areas with spotty cellular coverage
  • Office networks that go down for maintenance
  • VPN connections that timeout
  • Users who close their laptops mid-sync
  • Any of these scenarios can cause data loss with a naive "always-online" architecture. We needed something better.

    The Solution: Local-First Architecture

    We adopted a Local-First design philosophy: all data is written to local storage first, then synchronized to the cloud when connectivity is available.

    Layer 1: Desktop Agent (Rust + Tauri)

    The client is built with Rust and Tauri for maximum performance with minimum resource usage:

  • Memory footprint: < 10MB RAM
  • Startup time: < 200ms
  • Storage: SQLite for all local data
  • UI: SvelteKit 5 running in Tauri's WebView
  • Every event (clock-in, activity log, screenshot) is committed to SQLite immediately. The user sees instant feedback regardless of network state.

    Layer 2: Sync Engine (Go)

    A dedicated Go service handles synchronization between local SQLite and the cloud:

  • Queue-based sync: Events are queued and processed in order
  • Exponential backoff: Failed syncs retry with increasing delays
  • Conflict resolution: Client-wins strategy for most events
  • Idempotency: Unique constraints prevent duplicate inserts
  • The sync engine runs as a background process, completely decoupled from the UI. Users can work offline for days; when connectivity returns, everything syncs automatically.

    Layer 3: Reporting Core (FastAPI + Celery + Pandas)

    Heavy data processing happens asynchronously on the server:

  • FastAPI: REST endpoints for dashboard queries
  • Celery: Async task queue for report generation
  • Pandas: Data aggregation and analysis
  • This separation means the desktop agent stays lightweight—all the heavy lifting happens server-side.

    Layer 4: Dashboard (SvelteKit)

    The admin dashboard provides real-time visibility:

  • RBAC: Role-based access control for team managers
  • Visualizations: Productivity trends, time allocation, team metrics
  • Exports: Data export in multiple formats
  • Layer 5: Infrastructure (Supabase)

    We chose Supabase for centralized services:

  • Auth: User authentication and session management
  • Database: PostgreSQL for cloud storage
  • Storage: File storage for screenshots and exports
  • Key Lessons

    1. Embrace Eventual Consistency

    Not everything needs to be real-time. For most analytics use cases, data that's a few seconds (or minutes) old is perfectly acceptable.

    2. Design for Failure

    Every network call will fail eventually. Build retry logic from day one, not as an afterthought.

    3. Keep the Client Dumb

    The desktop agent's job is to collect data and store it locally. All business logic lives on the server where it's easier to update.

    4. Use the Right Tool for Each Layer

    We didn't try to build everything in one language:

  • Rust: When performance and memory matter
  • Go: When concurrency and network handling matter
  • Python: When data processing and APIs matter
  • SvelteKit: When interactivity and developer experience matter
  • Results

    The TimePerch architecture handles:

  • Zero data loss during network outages
  • Sub-10MB memory footprint on client
  • < 10ms sync latency when online
  • Days of offline operation with automatic catch-up

  • This architecture pattern is applicable to any desktop application that needs to work offline. If you're building something similar, let's talk.