Skip to main content

Overview

Zeus Finance is built on a local-first architecture that prioritizes user data ownership and offline capability. This document explains the key architectural decisions and how components interact.

Core Principles

1. Local-First

Data is created, stored, and modified locally first. The server acts as a synchronization point, not the source of truth.
User Action → Local Storage → Background Sync → Server

2. Optimistic Updates

UI updates immediately after local operations. If sync fails, the user is notified but can continue working.

3. Eventual Consistency

All devices will eventually sync to the same state. Conflicts are resolved by timestamp (last-write-wins) or manual intervention.

System Components

Mobile Application (Flutter)

lib/
├── cache/           # Local-first cache layer
│   ├── models/      # Data models
│   ├── repositories/# CRUD operations
│   └── services/    # Sync logic
├── app/             # App-level configuration
└── ...              # Feature modules
Key Responsibilities:
  • Store all data in SQLite
  • Provide instant read/write operations
  • Queue changes for sync
  • Handle conflict resolution

Backend Server (Rust)

server/
├── src/
│   ├── models/      # Data structures
│   ├── repositories/# Database access
│   ├── services/    # Business logic
│   └── controllers/ # HTTP handlers
└── migrations/      # Database migrations
Key Responsibilities:
  • Store canonical data in PostgreSQL
  • Provide REST API for sync
  • Handle authentication
  • Manage concurrent updates

Data Flow

Creating a Transaction

Offline Scenario

Sync Strategy

Sync Status States

Every entity has a sync_status field:
StatusMeaning
syncedIn sync with server
pending_createNew entity, needs server creation
pending_updateModified locally, needs server update
pending_deleteMarked for deletion

Sync Process

  1. Query all entities where sync_status != 'synced'
  2. Batch operations by type (create/update/delete)
  3. Send to server in dependency order (categories → wallets → transactions)
  4. Update local records with server IDs and synced status
  5. Hard delete entities marked pending_delete and synced

Conflict Resolution

When the same entity is modified on multiple devices:
  1. Server receives update with current updated_at
  2. Compare with server’s last known update
  3. Last-write-wins based on timestamp
  4. Return current server state to outdated clients

Database Schema

Local (SQLite)

-- Core entities with sync tracking
CREATE TABLE transactions (
    id TEXT PRIMARY KEY,           -- Local UUID
    server_id TEXT,                -- Server-assigned ID
    wallet_id TEXT NOT NULL,
    amount REAL NOT NULL,
    -- ... other fields
    sync_status TEXT DEFAULT 'pending_create',
    is_deleted INTEGER DEFAULT 0,
    created_at INTEGER NOT NULL,
    updated_at INTEGER NOT NULL,
    synced_at INTEGER
);

Server (PostgreSQL)

-- Canonical data storage
CREATE TABLE transactions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID NOT NULL REFERENCES users(id),
    wallet_id UUID NOT NULL REFERENCES wallets(id),
    amount DECIMAL(15,2) NOT NULL,
    -- ... other fields
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

Security Considerations

Authentication

  • JWT tokens for API authentication
  • Tokens refreshed on app foreground
  • Secure storage for credentials

Data Validation

  • Client-side validation for immediate feedback
  • Server-side validation as authoritative
  • Type safety via Rust/Flutter type systems

Scaling Considerations

Mobile

  • SQLite handles thousands of records efficiently
  • Lazy loading for transaction history
  • Image compression for attachments

Server

  • Stateless design enables horizontal scaling
  • Connection pooling for database
  • Rate limiting per user

Monitoring

Track these metrics in production:
  • Sync success/failure rates
  • Average sync latency
  • Conflict frequency
  • Cache hit rates
  • Storage utilization