Skip to Content
OverviewGlobal architecture

Global Architecture

System-wide architecture reference covering KMP module structure, Clean Architecture layers, Ktor server, and cross-platform data flow.

System Overview

Oter is built on a Kotlin Multiplatform architecture that enables code sharing across Android, iOS, Desktop, Web, and Server platforms. Feature logic, UI components, ViewModels, and data models all live in the shared module, consumed by thin platform-specific shells (composeApp, androidApp, iosApp). The server (server) provides REST and WebSocket APIs.

Module Organization

The platform was consolidated onto a single shared UI (2026-06). The old per-feature Android modules (*_domain/*_data/*_presentation) and the core-data / core-ui / navigation / test-core libraries were removed — all feature code now lives in shared/.

Gradle Modules

  • shared: KMP shared client layer — UI components, ViewModels, services, models, design system, and utilities. The single source of feature logic across Android, iOS, Desktop, and Web.
  • composeApp: Compose Multiplatform application entry point. Contains platform-specific code (desktop window management, iOS host setup, Android activity), navigation shell, and wires the shared UI via SharedAppNavHost.
  • androidApp: Android entry point that hosts the shared Compose UI. Minimal shell — DI (Koin) and lifecycle wiring.
  • server: Ktor-based backend server providing REST APIs and WebSocket support, with business logic for all features.
  • core: Core Android-specific functionality (permissions, background services, Firebase integration).

Architecture Diagram

Data Flow

Balance Prediction Flow

Transaction Processing Flow

  1. User Input: User creates/edits a transaction in the UI
  2. ViewModel: ViewModel validates and prepares the request
  3. Service: Shared service sends HTTP request to server
  4. Routing: Server routing layer receives and validates request
  5. Service Layer: Business logic processes the transaction
  6. Repository: Data access layer persists to database
  7. Response: Success/error response flows back through layers
  8. UI Update: ViewModel updates state, UI reflects changes

Cross-Cutting Concerns

Client offline and sync

The mobile consolidation (2026-06) removed the Android Room/offline layer. All clients are currently online-first: they read from and write to the server directly. Compose Desktop and Wasm are similarly network-dependent. No offline queue or stale-while-revalidate cache is in place post-consolidation. The offline/sync architecture is being re-evaluated — full detail: Offline & sync.

Configuration

Configuration is managed through:

  • Environment variables: Server configuration (database URLs, API keys)
  • Gradle properties: Build-time configuration
  • Application config: Runtime configuration via YAML files
  • User settings: Per-user preferences stored in database

The server uses Ktor’s configuration system with support for environment-specific configs (development, staging, production).

Error Handling

Error handling follows a consistent pattern:

  • Client-side: Services catch HTTP errors and convert to domain exceptions
  • Server-side: Routing layer catches exceptions and returns appropriate HTTP status codes
  • UI Layer: ViewModels expose error states that UI components display

Error responses follow a standard format:

data class ErrorResponse( val message: String, val code: String? = null, val details: Map<String, Any>? = null )

Logging

  • Server: Uses Logback for structured logging
  • Client: Platform-specific logging (Android Log, iOS NSLog, etc.)
  • Log levels: DEBUG, INFO, WARN, ERROR
  • Structured logging: JSON format for production environments

Authentication & Security

  • JWT-based authentication: Tokens issued on login, validated on each request
  • Token storage: Secure storage on client platforms (Keychain on iOS, EncryptedSharedPreferences on Android)
  • Password hashing: BCrypt for password storage
  • HTTPS: All API communication over HTTPS
  • CORS: Configured for web client access
  • Rate limiting: API rate limiting to prevent abuse

Performance Considerations

Long-Range Predictions

Balance predictions can span months or years, generating thousands of data points. Performance optimizations include:

  • Pagination: Results paginated to limit response size
  • Lazy loading: UI loads prediction data incrementally
  • Caching: Frequently accessed data cached on client
  • Database indexing: Optimized indexes on transaction date, user, account
  • Query optimization: Efficient SQL queries with proper joins

Real-Time Updates

  • WebSocket: Real-time updates for timers and notifications
  • Polling fallback: HTTP polling when WebSocket unavailable
  • Connection management: Automatic reconnection with exponential backoff

Mobile Optimization

  • Offline support: Local caching of critical data
  • Background sync: Periodic synchronization when app in background
  • Battery efficiency: Optimized network requests and background processing

Module Dependencies

Dependency Rules

  1. Client apps depend on shared: androidApp, composeApp, and iosApp consume shared UI and logic
  2. composeApp provides platform-specific entry points: it wires the shared module to each platform (desktop window, Android activity, iOS host, WASM entry)
  3. server depends on shared: Server uses shared models and serialization
  4. shared is independent: No dependencies on server, composeApp, or platform-specific code
  5. No circular dependencies: Strict acyclic dependency graph

Common Dependencies

  • Kotlinx Serialization: JSON serialization/deserialization
  • Ktor: HTTP client (client) and server framework (server)
  • Coroutines: Asynchronous programming
  • Compose Multiplatform: UI framework (via shared and composeApp)
  • Exposed: Database ORM (server)
  • Koin: Dependency injection (shared + all platforms)
  • Kotlinx DateTime: Date/time handling

Deployment Architecture

Server Deployment

  • Containerized: Docker containers for consistent deployment
  • Database: PostgreSQL with connection pooling
  • File storage: AWS S3 for user-uploaded files
  • Reverse proxy: Nginx for load balancing and SSL termination
  • Monitoring: Sentry for error tracking (optional)

Client Distribution

  • Android: Google Play Store
  • iOS: App Store
  • Desktop: Platform-specific installers (DMG for macOS, MSI for Windows)
  • Web: Static hosting with WebAssembly support