Offline-first architecture
A syndicate does not live where the data centre is. The aircraft might be on a grass strip, or at a remote airfield with no signal at all. Syndik8 is built so that the app works where the aircraft is, offline and trusting its own local copy, and reconciles with the server when connectivity comes back. This page explains the three people that model is built for, what “offline-first” means in practice, and the one part of the app that is deliberately not offline.
The three people this is for
Section titled “The three people this is for”The pilot on an airfield with no signal. Pre-flight, on the apron, phone in hand, wants to see today’s booking, log the out-time, record a squawk from yesterday’s flight. Mobile data is two bars on a good day and gone on most.
The instructor in a steel-frame hangar. Signal behaves as if the hangar is a Faraday cage. They want to scroll through past usage logs and log an hour’s ground brief against today’s booking. Round-trips to a server are not available.
The treasurer working in a cafe. Usually has Wi-Fi, occasionally doesn’t. They want to pull up member balances and last month’s expenses without the app going blank.
None of these three users want to think about connectivity. The app’s job is to make connectivity invisible: to work with what is local, to queue what needs to go to the server, and to tell the user honestly when something is waiting.
What local-first means for Syndik8
Section titled “What local-first means for Syndik8”The app keeps a local copy of your syndicate’s data on the device. Reads come from that local copy, which is why the calendar, the bookings tab, and the asset details render instantly whether or not the device is online. Writes go into the local copy first, then into a queue the app pushes to the server at the next opportunity.
Most of what you look at on a normal day is on the device. The full breakdown is on the Offline capabilities reference page. It covers every part of the operational day: syndicates, memberships, assets, bookings, usage logs, maintenance items and logs, squawks, billing schemes, transactions, expenses, notifications, and more.
Sync follows active membership: a syndicate is in your local cache only while your membership is active. The moment you leave a syndicate (or an admin removes you) it drops out of your device’s sync set and the cache stops receiving updates for it. The data already on the device stays until the next clean sync clears it, but no new changes will appear.
How the app talks to you about offline state
Section titled “How the app talks to you about offline state”Two affordances do most of the work, and you’ll see them everywhere.
The “will sync when you’re back online” suffix on success messages. When you create or edit something that is queued on the device, the success snackbar tells you so. Online, you see Booking created. Offline, the same action shows Booking created on the first line and will sync when you’re back online on a second line. The change is real on your device immediately; the suffix is a promise that the server will hear about it when connectivity returns. Used on bookings (create, confirm, approve, reject, cancel), usage logs, expense submissions, squawk reports, and the other sync-backed writes.
Disabled buttons with a clear reason on online-only actions. A small set of actions cannot be queued because they touch the financial ledger or call out to a third-party service that has no offline contract. When the device is offline, those buttons disable and surface a short snackbar that names the reason: Settlements need a connection, Approval needs a connection, Invites need a connection, Payment setup needs a connection. The button re-enables automatically when the connection returns. You don’t have to refresh, and you don’t get the chance to tap an action that would silently drop on the floor.
The app prefers to be honest. It would rather tell you “this can’t go out yet” than accept a tap that has nowhere to go.
What runs on the device, not the server
Section titled “What runs on the device, not the server”A few pieces of business logic that started life as server-side checks have moved into the app so they keep working offline. The most visible is the maintenance check that runs when you open the booking dialog. Syndik8 reads the maintenance items, the asset’s current meter reading, and the recent usage history (all from the local database) and shows an amber or red warning in the dialog if the booking would push past a service threshold. Typical evaluation time is a few milliseconds; no network round-trip is required. A pilot opening the app on the apron sees the same warning the treasurer would see at home on Wi-Fi.
The traffic-light indicator
Section titled “The traffic-light indicator”The profile avatar in the navigation chrome carries a live connectivity dot. Green means connected and receiving real-time updates from the server. Amber means reconnecting: the app has noticed the connection dropped and is trying to restore it. Red means offline; no sync session, no network. The dot reacts in seconds rather than waiting for a protocol timeout, because the OS tells the app when the radio goes away.
That single indicator is the whole status display. You do not need to tap through screens to know whether the app is current; the avatar says so.
The trade-off: eventual consistency vs strict consistency
Section titled “The trade-off: eventual consistency vs strict consistency”Offline-first is a deliberate choice with consequences. Two devices can make conflicting edits while both offline; when they reconnect, one has to give way. Syndik8 handles different parts of the app with different consistency models depending on how bad a conflict would be.
Most of the app is eventually consistent. If two members edit the same record offline and reconnect, the later write wins. For a booking note or a usage-log comment, last-write-wins is fine. A member typing on a phone in a hangar does not want the app to refuse the edit because another member edited the record three minutes ago.
Bookings are eventually consistent, but with a server-side guard. Two members who each create a confirmed booking overlapping the same slot offline will both see their booking locally. When their devices reconnect, the first to reach the server wins; the second is rejected by a server-side conflict check and surfaces as a sync error on the losing device. The losing member edits the times or cancels. See Conflict detection. The cost is occasional late rejection; the benefit is that members can plan bookings on an airfield with no signal at all.
Financial finalisation is strictly consistent. This is the one domain where offline-first is the wrong answer. Money conflicts are not an inconvenience; they are a correctness problem. If two people attempted to finalise the same booking offline, the ledger could end up double-charged or silently re-written under the last-write-wins rule. Syndik8 therefore writes ledger sources of truth (settlements, reversals, refunds) only online. A read-only synced view of the financial picture is available on the device, so members can see their balance and “debit incoming” cards offline; the Offline capabilities reference lists what that view covers. A collection in progress syncs in its own right, together with the record of which charges it is holding, so the card is there whenever the charges are. Any action that changes the ledger goes through an online button. Finalising a booking, approving or rejecting an expense, issuing a refund, generating an invite, and starting payment setup all sit behind disabled buttons when the device is offline, with a short reason in a snackbar. The sister explanation page on why finalisation is a separate step explores the money model more fully.
What happens when the server says no
Section titled “What happens when the server says no”A queued change is not a promise the server will accept it. Most land. A few cannot: another member took the slot while you were offline, an admin grounded the aircraft, your syndicate was closed to new activity, or the record you edited was removed before your device reconnected. When one is refused for good — a refusal no amount of retrying would turn into a yes — the app does two things.
It puts your device back to what the server is holding. For an edit, the app reads back the fields your change touched and restores the server’s version of them, so the device stops showing a value the server declined. Without that step you would go on seeing, say, a maintenance check marked complete that the server had refused, with nothing on screen to say otherwise. If the server will not show you the record at all — which is what happens if your membership ended while you were offline — the app leaves your copy alone rather than inventing a value, and records that it could not check. The difference between “we checked, and here is what the server holds” and “we could not check” is kept deliberately visible; the app never lets the second read as the first.
Bookings take one extra step, and it is worth knowing why. Checking what the server holds for a cancelled booking means reading who cancelled it, and that is a detail Syndik8 does not show everybody: a syndicate can keep member names off the shared calendar, in which case the booker of a slot is withheld. Your own bookings are never affected — you always see your own, and admins always see everybody’s — so a cancellation you made offline is checked and put back like any other change. Where the booking is someone else’s and its booker genuinely is not yours to see, the app treats that as we could not check rather than reading the blank it was handed as the server’s answer: your copy is left exactly as it was, and the notification still tells you the change was not saved. Quietly blanking a real value and calling it a success would be the worse mistake.
It tells you. A refusal raises a notification naming the record and the reason. Bookings get the most detailed wording, because they have causes nothing else has: the slot is taken, a flight is already under way, the aircraft was grounded, maintenance was scheduled over your window. Everything else — squawks, expenses, maintenance items, usage logs, documents, aircraft and syndicate settings — raises an Offline Change Not Saved notice that names the record (“your offline change to the squawk was not saved”) and gives one of three reasons: you no longer have permission, something it depends on is gone, or the server would not accept one of the values.
The wording tells you which of two states your device is now in, because they are not the same. Something you created offline that was refused has been removed from your device, and the notice says so and suggests adding it again. Something you changed is still there, put back to the server’s version, and the notice says the version on the server is unchanged — so you are not sent looking for a record that never left.
Tapping the notice takes you to what it is about: a squawk opens directly, and everything else opens the syndicate it belongs to, where the calendar, maintenance, squawks and expenses tabs all live.
Some refusals stay deliberately quiet. Changes to your own profile raise nothing, because nothing in the app can refuse them — a “you no longer have permission” notice about your own profile would be nonsense. Neither does marking a notification read. Nor does opening an edit screen and tapping Save without changing anything: that is refused like any other write, but it cost you nothing, and a notice about it would send you looking for an edit you never made.
You can turn these off. Offline change not saved is an ordinary row in notification settings with separate push and email switches, both on to begin with. It is not one of the locked notices, because nothing has happened that you must act on: the record on the server is exactly as it was before you touched it.
The one refusal that is not a loss is a duplicate. If the server already holds the record your device queued, your copy is the real one: it stays, and nothing is said. Flights logged from the watch are the exception, and only in appearance. There the clash is not over the reference but over the flight itself — the same flight is already recorded under a different one — so it is the copy on your device that is the duplicate, and that copy is removed. The flight is not lost; the server’s version syncs down in its place, which is why nothing is said about this one either.
Refusals like these are rare. A syndicate that carries on normally will never see one; they are what happens when the world moved while a device could not see it.
Why the web build is a slightly different story
Section titled “Why the web build is a slightly different story”The web build runs in a browser tab and keeps its local data in the browser’s storage (OPFS or IndexedDB, depending on the browser). That data persists between tab closes, so reopening the app does not trigger a full re-download from the server. Where the web differs from iOS and Android is offline document caching: the file-caching layer is mobile-only. The web always fetches document files over the network, and the document library shows a banner saying offline caching is available in the mobile app. For everything else (bookings, usage logs, maintenance, financials) the web build’s local store works the same way as on mobile.
See also
Section titled “See also”- Offline capabilities: the full list of synced tables, what works offline, what doesn’t
- Conflict detection: how the server guards booking overlaps when offline writes arrive late