Skip to Content
Core ConceptsData Persistence

Data Persistence API

Tracelet guarantees data delivery by using an offline-first architecture. Every location coordinate, activity change, and geofence event is written instantly to an encrypted local SQLite database.

While Tracelet’s Sync engine automatically reads and deletes data from this database, you have full manual control over the persistent store.


1. Querying Locations

You can extract the raw, un-synced locations currently sitting in the SQLite database.

// Get ALL locations currently stored in the database final locations = await tl.Tracelet.getLocations(); for (final loc in locations) { print('Location: \${loc.coords.latitude}, \${loc.coords.longitude}'); }

Advanced SQL Queries

You don’t have to fetch everything. Tracelet exposes a SQLQuery object that allows you to filter the database exactly like standard SQL.

// Get only the locations recorded on a specific date final query = tl.SQLQuery( where: "timestamp >= ? AND timestamp <= ?", whereArgs: ["2024-01-01T00:00:00Z", "2024-01-01T23:59:59Z"], limit: 100, order: "timestamp DESC" ); final specificLocations = await tl.Tracelet.getLocations(query);

2. Counting Records

If you just need to know how many locations are backlogged (e.g., to show an “Offline Sync Queue” badge in your UI), use getCount(). It is highly optimized and doesn’t load the records into memory.

// Count total un-synced locations final count = await tl.Tracelet.getCount(); print('Pending locations to sync: \$count'); // You can also use SQL queries here final highAccuracyCount = await tl.Tracelet.getCount( tl.SQLQuery(where: "accuracy <= 20") );

3. Inspecting the Offline Queue

Because Tracelet prunes each record the moment it is confirmed synced, every location still in the database is — by definition — pending upload. The pending-queue helpers make this explicit, which is ideal for showing a “waiting to sync” badge, building an audit view, or diagnosing connectivity.

// The locations still waiting to be delivered to your backend. final pending = await tl.Tracelet.getPendingLocations(); // Just the queue depth (optimized — no records are loaded into memory). final pendingCount = await tl.Tracelet.getPendingLocationCount(); print('Offline queue: \$pendingCount location(s) waiting to sync');

Both accept an optional SQLQuery for time-range filtering, exactly like getLocations() / getCount().


4. Destroying Data

If the user logs out, or explicitly deletes their account, you must destroy their location history to comply with GDPR/HIPAA.

Destroy All

This wipes the location database completely clean.

await tl.Tracelet.destroyLocations();

Destroy Specific Location

You can destroy a single, specific location if you know its UUID.

Where do you get the UUID? Every location generated by Tracelet is automatically assigned a unique uuid. You can get this ID by calling getLocations() and reading the uuid property on the Location object.

final locations = await tl.Tracelet.getLocations(); if (locations.isNotEmpty) { final firstLocationId = locations.first.uuid; // Destroy just this specific location from the database await tl.Tracelet.destroyLocation(firstLocationId); }

Destroy Synced

Typically Tracelet automatically deletes locations after it receives an HTTP 200 OK from your server. However, if you are doing manual syncing, you can trigger this cleanup manually.

await tl.Tracelet.destroySyncedLocations();