PersistenceConfig¶
Persistence and storage configuration for the background geolocation SDK.
PersistenceConfig controls how the SDK stores, orders, templates, and purges
records in its on-device SQLite database — the durable buffer between data
producers (locations, geofences) and consumers (your app and the HTTP service).
Contents¶
Overview¶
The SDK maintains an internal SQLite database as a rolling queue. Each recorded Location and geofence event is written immediately, then consumed and deleted by downstream services. The SDK prefers an empty database — records exist only while awaiting upload or retrieval.
| Category | Properties | Notes |
|---|---|---|
| Retention | maxDaysToPersist, maxRecordsToPersist |
TTL and count-based purge limits. |
| Ordering | locationsOrderDirection |
Controls upload and retrieval order. |
| Templates | locationTemplate, geofenceTemplate |
Custom JSON structure for uploads. |
| Extras | extras |
Static key/value pairs merged into every record. |
| Persist mode | persistMode |
Which event types are written to SQLite. |
| Diagnostics | disableProviderChangeRecord |
Suppress provider-change records. |
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
maxDaysToPersist: 3,
maxRecordsToPersist: 1000,
extras: {
'user_id': 123,
'appVersion': '1.2.3'
},
persistMode: PersistMode.all
)
));
Storage lifecycle¶
Records are written to SQLite immediately upon recording and deleted when any of the following occur:
- Your server returns a
20xresponse for the HTTP upload (see HttpConfig) - You call BackgroundGeolocation.destroyLocations
maxDaysToPersistelapses (rolling TTL purge)maxRecordsToPersistwould be exceeded (oldest records are dropped)
Inspect the pending queue with BackgroundGeolocation.getCount or BackgroundGeolocation.getLocations.
Ordering¶
locationsOrderDirection controls the order in which records are selected
for upload or returned by BackgroundGeolocation.getLocations:
"ASC"— oldest first (default)"DESC"— newest first
Templates¶
By default the SDK serializes locations and geofence events using its standard
JSON schema. Use locationTemplate and geofenceTemplate to
substitute a custom ERB template that reshapes the JSON to match your backend.
Use extras to merge static key/value metadata into every record at write
time, without a custom template.
Persist mode¶
persistMode controls which event types are written to SQLite. All events
are still delivered to their live callbacks (BackgroundGeolocation.onLocation,
BackgroundGeolocation.onGeofence) regardless of this setting. Events that
are not persisted are not eligible for HTTP uploads via HttpConfig.url.
The persist option on individual API calls can override this setting per-request:
final location = await BackgroundGeolocation.getCurrentPosition({
persist: true,
extras: { get_current_position: true },
samples: 3,
});
Examples¶
final state = await BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
maxDaysToPersist: 14,
maxRecordsToPersist: 5000,
locationsOrderDirection: 'ASC',
persistMode: PersistMode.all,
extras: { user_id: 123, appVersion: '1.2.3' },
),
http: HttpConfig(
url: 'https://example.com/locations',
autoSync: true,
)
));
final pending = await BackgroundGeolocation.count;
print('Pending records: ${pending}');
// Purge all records
final ok = await BackgroundGeolocation.destroyLocations();
print('Destroyed all records? ${ok}');
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate: '{
"lat": <%= latitude %>,
"lng": <%= longitude %>,
"ts": "<%= timestamp %>",
"meta": <%= JSON.stringify(extras) %>
}',
geofenceTemplate: '{
"id": "<%= identifier %>",
"action": "<%= action %>",
"ts": "<%= timestamp %>"
}',
),
));
Configure persistence behavior¶
final state = await BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
maxDaysToPersist: 14,
maxRecordsToPersist: 5000,
locationsOrderDirection: 'ASC',
persistMode: PersistMode.all,
extras: { user_id: 123, appVersion: '1.2.3' },
),
http: HttpConfig(
url: 'https://example.com/locations',
autoSync: true,
)
));
Inspect and purge the database¶
final pending = await BackgroundGeolocation.count;
print('Pending records: ${pending}');
// Purge all records
final ok = await BackgroundGeolocation.destroyLocations();
print('Destroyed all records? ${ok}');
Custom JSON templates¶
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate: '{
"lat": <%= latitude %>,
"lng": <%= longitude %>,
"ts": "<%= timestamp %>",
"meta": <%= JSON.stringify(extras) %>
}',
geofenceTemplate: '{
"id": "<%= identifier %>",
"action": "<%= action %>",
"ts": "<%= timestamp %>"
}',
),
));
final pending = await BackgroundGeolocation.count;
print('Pending records: ${pending}');
// Purge all records
final ok = await BackgroundGeolocation.destroyLocations();
print('Destroyed all records? ${ok}');
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate: '{
"lat": <%= latitude %>,
"lng": <%= longitude %>,
"ts": "<%= timestamp %>",
"meta": <%= JSON.stringify(extras) %>
}',
geofenceTemplate: '{
"id": "<%= identifier %>",
"action": "<%= action %>",
"ts": "<%= timestamp %>"
}',
),
));
Members¶
disableProviderChangeRecord¶
Android only Disables the automatic insertion of a synthetic "provider-change" location into the SDK's SQLite database and its subsequent HTTP upload.
By default, when an BackgroundGeolocation.onProviderChange event fires, the Android SDK records a special location documenting when and where the device's location-services state changed (e.g., GPS disabled). This behavior historically existed to support platforms with limited or unreliable Headless Task implementations (e.g., Cordova, Capacitor).
Set this to true if your server-side JSON schema or locationTemplate
cannot accommodate the automatically injected provider field.

BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
disableProviderChangeRecord: true
)
));
extras¶
Optional arbitrary key/value pairs merged into each recorded location at write time.
These values are persisted and included in all HTTP uploads, making them
ideal for attaching static contextual metadata such as user_id, route_id,
or session_id.
See also
- HTTP Guide
BackgroundGeolocation.ready(Config(
http: HttpConfig(
url: "https://my-server.com/locations",
params: {
device_id: "abc123" // appended to root JSON of each POST request
}
),
persistence: PersistenceConfig(
extras: {
route_id: 1234 // merged onto each location record
}
)
));
The resulting HTTP request body:
POST /locations
{
"device_id": "abc123",
"location": {
"coords": {
"latitude": 45.51927004945047,
"longitude": -73.61650072045029
},
"extras": {
"route_id": 1234
}
}
}
geofenceTemplate¶
Optional custom ERB template for reshaping GeofenceEvent JSON in HTTP uploads.
Behaves like locationTemplate but includes two additional tags:
geofence.identifier and geofence.action. Use Ruby-style ERB tags to
interpolate field values:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate:
'{ "lat":<%= latitude %>, "lng":<%= longitude %>, "geofence":"<%= geofence.identifier %>:<%= geofence.action %>" }'
)
));
// Or a compact Array form:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate:
'[<%= latitude %>, <%= longitude %>, "<%= geofence.identifier %>", "<%= geofence.action %>"]'
)
));
Warning
The SDK does not automatically apply double-quotes around string data. Templates are JSON-encoded exactly as written.
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate: '{"timestamp": <%= timestamp %>}'
)
));
Produces invalid JSON:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate: '{"timestamp": "<%= timestamp %>"}'
)
));
Template tags¶
Identical to locationTemplate with the following additions:
| Tag | Type | Description |
|---|---|---|
geofence.identifier |
String |
Identifier of the activated geofence |
geofence.action |
String |
"ENTER" or "EXIT" |
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Whether device is plugged in |
mock |
Boolean |
True when location was generated from a mock app |
is_moving |
Boolean |
True if recorded while in moving state |
timestampMeta |
Object |
Timestamp metadata; see GeoConfig.enableTimestampMeta |
See also
- locationTemplate
- HttpConfig.rootProperty
- HTTP Guide
Incorrect¶
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate: '{"timestamp": <%= timestamp %>}'
)
));
Correct¶
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
geofenceTemplate: '{"timestamp": "<%= timestamp %>"}'
)
));
locationTemplate¶
Optional custom ERB template for reshaping Location JSON in HTTP uploads.
When set, the SDK evaluates the template string against each location record before serializing it. Use Ruby-style ERB tags to interpolate field values:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate:
'{"lat":<%= latitude %>,"lng":<%= longitude %>,"event":"<%= event %>",isMoving:<%= is_moving %>}'
)
));
// Or use a compact Array template:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate:
'[<%=latitude%>, <%=longitude%>, "<%=event%>", <%=is_moving%>]'
)
));
Warning
The SDK does not automatically insert quotes around string values. Templates are JSON-encoded exactly as written.
The following produces invalid JSON because timestamp is a string but is
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate: '{"timestamp": <%= timestamp %>}'
)
));
This renders invalid JSON:
BackgroundGeolocation.ready(Config(
persistence: PersistenceConfig(
locationTemplate: '{"timestamp": "<%= timestamp %>"}'
)
));
Configured extras¶
If extras are configured, the key/value pairs are merged directly
into the rendered location JSON.
BackgroundGeolocation.ready(Config(
http: HttpConfig(
url: 'https://my.server.com/locations',
rootProperty: 'data',
),
persistence: PersistenceConfig(
locationTemplate: '{"lat":<%= latitude %>,"lng":<%= longitude %>}',
extras: { foo: "bar" }
)
));
Produces:
Template tags¶
| Tag | Type | Description |
|---|---|---|
latitude |
Float |
|
longitude |
Float |
|
speed |
Float |
Meters |
heading |
Float |
Degrees |
accuracy |
Float |
Meters |
altitude |
Float |
Meters |
altitude_accuracy |
Float |
Meters |
timestamp |
String |
ISO-8601 |
uuid |
String |
Unique ID |
event |
String |
motionchange, geofence, heartbeat, providerchange |
odometer |
Float |
Meters |
activity.type |
String |
still, on_foot, running, on_bicycle, in_vehicle, unknown |
activity.confidence |
Integer |
0–100% |
battery.level |
Float |
0–100% |
battery.is_charging |
Boolean |
Is device plugged in? |
mock |
Boolean |
True if generated by mock provider |
is_moving |
Boolean |
Device was moving when recorded |
timestampMeta |
Object |
Timestamp metadata; see GeoConfig.enableTimestampMeta |
See also
- HTTP Guide
- geofenceTemplate
- HttpConfig.rootProperty
locationsOrderDirection¶
Sort order used when selecting records for upload or returning them from
BackgroundGeolocation.getLocations. Defaults to "ASC" (oldest first).
"ASC"— oldest records first"DESC"— newest records first
maxDaysToPersist¶
Maximum number of days to retain a persisted record in the SDK's on-device
SQLite database. Defaults to 1 day.
When your server fails to return a 20x response, the SDK continues retrying
uploads. If a record remains unuploaded for longer than maxDaysToPersist days,
it is permanently discarded to prevent unbounded database growth.
maxRecordsToPersist¶
Maximum number of records the SDK may retain in its on-device SQLite database.
Defaults to -1 (no limit).
When a limit is set and the stored record count would exceed it, the oldest records are purged to make room for the newest.
See HttpEvent for details on upload behavior.
persistMode¶
PersistMode? persistMode
Controls which event types the SDK writes to its internal SQLite database. Defaults to PersistMode.All.
All recorded events are always delivered to their live callbacks (BackgroundGeolocation.onLocation and BackgroundGeolocation.onGeofence). This setting only determines what is written to persistent storage. Events that are not persisted are also not eligible for HTTP uploads via HttpConfig.url.
| Value | Description |
|---|---|
| PersistMode.All | Default — persist both location and geofence events. |
| PersistMode.Location | Persist location events only. |
| PersistMode.Geofence | Persist geofence events only. |
| PersistMode.None | Persist nothing. |
Warning
This setting is intended for specialized cases. For example, if you need
continuous location tracking via BackgroundGeolocation.start but only
want to store geofence events, configure persistMode: PersistMode.Geofence.