How buoyient works

A visual tour of the sync engine

The big picture

Your app talks to buoyient. buoyient talks to your server. Your app never needs to worry about connectivity.

Your App
TodoService, InvoiceService, …
create() · update() · void() · get()
SyncableObjectService
powered by buoyient Engine
Local Store (SQLite)
Pending Queue
Sync Driver
Sync Up
Sync Down
Your Server
REST API, GraphQL, whatever you've got

Follow a CREATE

Click through to see what happens when your app creates a new object, step by step.

Step 1
Your app calls service.createTodo(todo)
Step 2
Is the device online?
↓ Yes
Online
HTTP request sent to your server immediately, wait for response synchronously
Response
Server returns serverId + version
Done
Local store updated → Synced
↓ No
Offline
Request added to Pending Queue, status PendingCreate
Instant
Response returned immediately
Later…
Connectivity returns. SyncDriver wakes up.
Resolve
{serverId} placeholders resolved, request sent → Synced
1 / 8

Connectivity is configurable — The “Is the device online?” check uses real network connectivity by default, but you have two ways to customize it: pass ProcessingConstraints on a per-request basis to force online or offline behavior, or provide a custom ConnectivityChecker implementation to override the global connectivity logic for a service.

Object lifecycle

Every SyncableObject carries a sync status that tracks where it is in its journey from local to server.

LocalOnly
PendingCreate
Synced
PendingUpdate
Synced
or from Synced →
PendingVoid
→ voided
conflict path:
PendingUpdate
Conflict
→ resolve →
Synced

The pending request queue

When offline, operations queue up. When connectivity returns, buoyient drains the queue in order, resolving placeholders as it goes.

Queue

Queue is empty

Server
0 received

Queue ordering guarantee

Request order is strictly preserved across all services in your app — not just within a single service. This matters when services have dependencies: for example, if a user creates an Order offline and then applies a Payment against that order, buoyient guarantees the order creation request reaches the server before the payment creation request, even though they belong to different services.

Placeholder resolution

When you create an object offline, it doesn't have a server ID yet. buoyient lets you reference it with a placeholder that gets resolved at sync time.

Before sync

HttpRequest (queued offline)
PUT /todos/{serverId}

{
  "title": "Buy milk",
  "version": {version}
}

After sync

HttpRequest (resolved)
PUT /todos/srv-a1b2c3

{
  "title": "Buy milk",
  "version": 42
}

Cross-service placeholders — Need to reference another service's server ID in an offline request? buoyient supports cross-service placeholder resolution too. For example, a Payment can reference an Order's server ID before the Order has synced — the placeholder is resolved automatically during sync-up.

Conflict resolution

When the server and local store diverge, buoyient does a field-level 3-way merge. Only truly conflicting fields need your attention.

Base (last synced)

title: "Buy milk"
completed: false
priority: "low"

Local changes

title: "Buy oat milk" changed
completed: false
priority: "high" changed

Server changes

title: "Buy milk"
completed: true changed
priority: "medium" changed

Merged result

title: "Buy oat milk" ← local wins (only local changed)
completed: true ← server wins (only server changed)
priority: CONFLICT ← both changed — your RebaseHandler decides

Customizable strategies — The 3-way merge logic and conflict handling come with sensible defaults out of the box, but you can fully override and customize the behavior by providing your own SyncableObjectRebaseHandler implementation.

Ready to set up?

Get started →