Offline calorie tracking: what continues without a connection
A lost signal should pause network work, not erase the record you just made. Offline calorie tracking starts with a local save, keeps queued work durable, preserves the entry's day, and makes reconnection a state you can inspect rather than a reason to type lunch twice.
Workflow map
Know what continues offline and what has to wait
You tap save once, the signal drops, and now the useful question is not whether the cloud icon looks cheerful. It is whether the entry was saved on the phone, what work is waiting for a connection, and how you will recognise completion later. That separation is the core of offline calorie tracking.
Start with four separate states. Locally saved means the entry has been committed to storage on the phone and can appear in the daily record without waiting for the network.
Queued means the app has durable work describing what must be created, changed, or deleted when synchronisation can run. These states can happen together, but they answer different questions: is the entry safe here, and is there still work to send?
Synced should mean more than a green icon appeared. The service accepted the operation, the app received an authoritative result, and the local copy now reflects that result. A product should also avoid presenting every ordinary refresh as proof that each individual pending change reached the service.
Rejected means the service could not apply the operation as sent. A validation failure, a missing record, or a version conflict is not the same as a weak connection.
Retrying an unchanged rejected request forever only creates a very energetic queue. The interface should say which entry needs attention and offer an action that fits the cause.
- Locally saved: the phone has committed the entry to its local record.
- Queued: a durable create, update, or delete operation is waiting to synchronise.
- Synced: the service result has been applied to the local entry.
- Rejected or failed: the operation stopped and the affected entry needs a clear next action.
Reconnecting should not create a second lunch
A connection returning is a trigger, not proof of completion. The app still has to read its queued operations, send them, match each response to the correct operation, apply successful results, and leave retryable network failures in place. If the process stops halfway through, it must be safe to continue later.
Reliable synchronisation therefore needs stable operation identifiers and an idempotent service. In plain language, sending the same queued create twice should not create two food entries simply because the first acknowledgement disappeared. The product should be able to recognise a duplicate operation and settle the original local record instead.
Haps keeps core operations in a durable queue and sends them in batches when a usable connection is detected, when the app becomes active, and when synchronisation starts. Network or provider errors leave those operations queued for a later attempt. The API accepts idempotent batches, so a repeated operation can be recognised rather than treated as a fresh meal.
A retry should also be narrow. One failed entry should not blank the current day, reset navigation, discard focus, or force every cached record to be fetched again.
Haps renders from its encrypted local database and, after network success, merges authoritative fields into the affected record. Unrelated entries remain available while that one operation changes state.
A conflict needs reconciliation, not a silent winner
A conflict happens when the local operation expects one version of an entry but the service has a newer one. Perhaps the same record was edited on another device, or a deletion crossed paths with a correction. Connectivity is working; the disagreement is about which change follows which.
Automatically choosing whichever copy arrived last can hide a real correction. Replacing the complete day is worse because a one-entry disagreement can overwrite unrelated work. The safer pattern is targeted reconciliation: compare the local operation with the current server record, retry against the newer version only when that is valid, and ask the person when the conflict remains meaningful.
Haps applies an optimistic version check. On the first conflict it records the current server version and retries the affected operation once. If the conflict persists, that entry moves to a failed state with both the attempted local change and the server record available for resolution; its operation is no longer retried blindly.
The resolution is specific to that entry. The person can restore the attempted change against the current version or discard it and use the saved server version. Successful remote results merge into the same local entity, while remote changes do not overwrite an entity that still has a pending local operation.
Rejection needs similarly exact handling. Some outcomes can be reconciled automatically, such as discovering that a record targeted by an update or delete no longer exists. Other rejection codes should leave the entry failed and visible to the product rather than masquerading as synced or blocking every other queued operation.
The queue should survive the app, and the date should survive travel
A queue held only in memory lasts until the operating system closes the process. That may be seconds after you switch apps. Durable means the operation is stored in the database, not merely attached to a spinner that hopes to finish before the phone decides it has other plans.
Haps stores core food entries and synchronisation operations in its encrypted local database. The database key is held through the platform credential store. Because the queue is persisted, a queued core operation remains available after the app process ends and can be read again when the app starts and synchronisation resumes.
The entry and its operation also belong together. Haps creates them in one local database transaction, so the app does not intentionally show a saved entry while forgetting to record the work needed to synchronise it. Updates and deletions likewise change local state and enqueue their operation transactionally.
Dates need the same discipline. A food entry records its local date, IANA timezone, and timezone offset when it is logged.
Those values travel in the synchronisation payload and remain on the entry when an authoritative result is merged. Reconnecting after crossing midnight or changing timezone should not quietly move dinner into tomorrow.
Test this with a dated example rather than trusting the word durable. Save an entry without a connection, close the app completely, change location or timezone if practical, reopen it, and reconnect. The useful result is one entry on its original local day, with its queued work either completed or clearly asking for attention.
Offline and sync status should work without colour or guesswork
A tiny grey cloud and a tiny green cloud are not a complete status system. Colour, animation, and position can support meaning, but they cannot carry it alone. Pending, synced, rejected, retrying, and conflicted states need concise text or semantics that screen readers can reach.
Status changes also need proportionate announcements. A locally saved entry should not be described as lost merely because it is queued, and a background retry should not interrupt every other task with repeated alerts. A failure that requires a decision deserves an accessible message, focus order, and action; routine progress can use a quieter live update.
In Haps, a persistent conflict changes the affected entry action to resolve sync conflict, and the resolution offers explicit restore, discard, and cancel choices. Overall background status still needs hands-on assistive-technology testing before it can be described as fully exposed or announced.
That does not remove the need for hands-on testing. Use VoiceOver and TalkBack, increase text size, disable motion, and navigate without relying on a swipe gesture. Confirm that the status is read in context, that a conflict can be opened and resolved, and that the resulting state is understandable without watching an icon change colour.
The best message answers two questions in one breath: is the entry safe on this phone, and do I need to act? Everything else is implementation detail until one of those answers changes.
Use an offline drill before relying on the workflow
Do not judge offline support from an airplane-mode badge. Use one synthetic entry you can recognise, then run a short drill: save it without a connection, edit it before reconnecting, close the app, reopen it, reconnect, and inspect the final record. If another device is available, change the same entry there to test conflict handling.
Watch the nouns. The app should tell you whether the entry is locally saved, queued, synchronised, rejected, or conflicted. It should not use saved and synced interchangeably, and it should not make a failed operation vanish simply because other entries completed.
Then check scope. A successful response should reconcile the affected record without replacing unrelated entries or moving the record to a different local day.
A retry should not create a duplicate. A conflict should offer a deliberate choice, and a restart should find the durable operation again.
Haps is preparing for its first public release on iPhone and Android. It is not currently available for public installation. Its implemented local-first architecture uses an encrypted mobile database, a durable core-operation queue, idempotent batch synchronisation, optimistic version checks, and targeted record merges; these facts describe the pre-launch product rather than a guarantee that every future network or device failure is recoverable.
For the next step, read the Haps data and privacy facts. Synchronisation means calorie-ledger records are handled by the Haps service after the local save, so local-first must not be mistaken for device-only. The simple-tracker and fast-logging pages then show how this reliability model fits the narrower daily workflow.
- Save and edit one recognisable entry before reconnecting.
- End and reopen the app while the operation is still queued.
- Confirm one final entry on its original local date after synchronisation.
- Check that a rejection or conflict names the affected entry and offers a suitable action.
- Repeat the status check with a screen reader and without colour cues.
How this guide was prepared
Haps-specific statements in this guide were checked against maintained implementation, automated tests, contracts, public policy, and operational documentation. General decision criteria are editorial analysis, not competitor testing or measured product performance.
- Separate current Haps behavior from general category guidance.
- Exclude unverified competitor, availability, price, rating, outcome, and health claims.
- Trace privacy-sensitive statements to the public policy or the maintained operational contract.
- Treat the diagram as an explanatory model, not observed user data.
Sources and evidence
- Haps data and privacy factsHaps — Local-first storage, synchronisation, analytics, export, and deletion facts.
- About HapsHaps — Product scope, pre-release status, operator identity, and supported workflow boundary.
- How Haps guides are researched and reviewedHaps — Source hierarchy, evidence labels, comparison boundaries, and correction process.
Common questions
What does pending mean in a calorie tracker?
Pending should mean the entry is saved locally but its queued synchronisation operation has not yet been confirmed by the service. It should remain visible on the phone, survive an app restart when the queue is durable, and move to synced or a clear failure state after an attempt.
Is a locally saved calorie entry already synced?
No. Locally saved means the phone has committed the entry to local storage; synced means the service accepted the operation and the app applied its authoritative result. A local-first product can show the entry immediately while synchronisation is still pending.
Will retrying calorie tracker sync duplicate an entry?
It should not. A reliable system uses stable operation identifiers and idempotent handling so repeating the same queued operation does not create another entry when an earlier acknowledgement was lost. After retrying, check that one local entry maps to one service record.
What should happen when the same calorie entry changed on two devices?
The tracker should reconcile only that entry and avoid silently replacing the whole day. Haps retries the affected operation once against the current version, then exposes a persistent conflict for a restore-or-discard decision if the disagreement remains.
Does Haps keep pending entries if I close the app?
Yes. Haps stores core entries and their operations in an encrypted local database, so queued work is persisted rather than held only in memory. It can be read again when the app starts and synchronisation resumes; Haps is still preparing for its first public iPhone and Android release.