The Rust Core Architecture
To guarantee absolute parity between Android and iOS and achieve the highest level of performance, Tracelet’s core logic is written entirely in Rust. This includes the state machine, HTTP sync engine, SQLite persistence layer, and battery budget calculations.
Why Rust?
Writing the core engine in Rust solves several critical challenges in cross-platform background execution:
- Zero Discrepancies: By relying on a single, shared codebase rather than separate Swift and Kotlin implementations, we ensure iOS and Android behave identically under all conditions. If a bug is fixed, it is fixed everywhere.
- Fearless Concurrency: The background Sync Engine operates flawlessly under heavy multithreaded loads. Rust’s strict compiler guarantees data-race freedom, avoiding concurrency bugs when locations are recorded and uploaded simultaneously on background threads.
- Performance & Safety: Rust operates with C-level performance and a near-zero memory footprint, making it perfect for battery-constrained background execution. It guarantees memory safety without a garbage collector, ensuring the background engine never crashes due to null pointers or out-of-memory errors.
How It Works: UniFFI Bindings
Tracelet uses Mozilla’s UniFFI (Universal Foreign Function Interface) to bridge the gap between Rust and the native platforms.
- Definition: We define the core API in Rust (e.g., methods to start tracking, sync data, or handle location updates).
- Generation: UniFFI automatically parses the Rust code and generates safe, idiomatic Swift bindings for iOS and Kotlin bindings for Android.
- Execution: When the Flutter plugin calls the native iOS/Android code, the native code calls the UniFFI-generated bindings, which seamlessly execute the underlying Rust logic.
Because the bindings are generated automatically, there is no manual JNI (Java Native Interface) or Objective-C bridging code to maintain. It is entirely type-safe.
Pre-compiled Binaries (No Rust Toolchain Required)
A common pain point with Rust in mobile development is forcing developers to install the Rust toolchain, configure cross-compilation targets, and endure long build times.
Tracelet solves this by distributing pre-compiled binaries.
When you add the tracelet plugin to your Flutter project, you do not need to install Rust on your machine. Tracelet’s CI/CD pipeline automatically builds and publishes the native libraries for every release.
Android Compilation
- The Rust code is compiled into a native shared library (
.so) for all major Android architectures (arm64-v8a,armeabi-v7a,x86,x86_64). - These libraries, along with the generated Kotlin bindings, are packaged into an Android Archive (
.aar). - When you build your Flutter app, Gradle automatically downloads the pre-built
.aarfrom the Tracelet repository.
iOS Compilation
- The Rust code is compiled into a static library (
.a) for iOS devices (arm64) and simulators (arm64,x86_64). - These libraries are bundled together with the generated Swift bindings into an Apple XCFramework (
TraceletCore.xcframework). - When you run
pod install, CocoaPods (or Swift Package Manager) automatically downloads the pre-compiledTraceletCore.xcframeworkdirectly from the tagged GitHub release.
This pre-compiled distribution ensures that your Flutter builds remain lightning fast, and your CI/CD pipelines work out-of-the-box without requiring custom Rust setups.