Dynamics 365 and Power Apps Offline: Building Field Apps That Do Not Lose Data
Why technician records disappear in no-signal areas, the durable offline pattern, honest conflict resolution, and how to reconcile what has already gone wrong.
When technicians submit work in no-signal areas and records silently disappear, the cause is almost never random. Sync conflicts resolve last-write-wins and overwrite the earlier value, a device clock running ahead gets records rejected and blocks the queue, work is discarded by a reinstall or sign-out before the queue flushes, and canvas apps lose in-memory state on restart. The durable pattern is a local queue in which every record carries a client-generated unique key and metadata (device, user, captured time), explicit retry with idempotent upsert so a resend never duplicates, and a reconciliation view of what has not synced. Last-write-wins is acceptable for single-owner fields; for shared counts, readings and notes it is not.
Why do field app records disappear when technicians work offline?
Offline data loss feels random to the people living it, because the app looks normal right up to the moment somebody asks where Tuesday's job sheets went. It is not random. Almost every case we investigate traces back to one of four mechanisms, and each one leaves a recognisable symptom. None of them is fixed by telling technicians to sync more often.
| Cause | What actually happens | Symptom you see | Structural fix |
|---|---|---|---|
| Last-write-wins conflicts | Two people change the same field; the later sync overwrites the earlier value with no prompt, and nothing flags it unless auditing is on for that column. | A reading, count or note that the technician swears they entered is simply different. | Single owners for shared fields, child records instead of shared fields, conflict rules agreed per field. |
| Device clock skew | A device clock running ahead creates records the server rejects as created in the future. The queue is ordered, so everything behind the rejected record waits. | A sync that never finishes while the app otherwise works, and a growing backlog on one device. | Automatic network time enforced through device management, and last successful sync monitored per person. |
| Writes discarded before the queue flushes | A reinstall, clear data, sign-out, device swap or remote wipe removes the local queue with work still in it. | Everything since the last good sync is gone, often after a well-meant "reinstall the app" from the help desk. | A rule that nobody touches a device with unsynced work, and a visible pending count before sign-out. |
| App state lost on restart | A canvas app holds submissions in a collection in memory; the operating system closes the app, the phone restarts or the battery dies. | Work captured in the morning is missing after lunch, with no error at all. | Persist the queue to the device after every change, or use the platform offline mode that persists for you. |
Which offline model are you running: Field Service mobile offline profiles or a canvas app?
The fix depends on which sync engine is doing the work, and many estates run more than one. Establish this first, because advice written for one model is often wrong for the other. Whether Power Apps or a dedicated inspection platform is the right tool in the first place is a separate decision, compared in our field inspection app cost comparison.
| Model | How offline works | Where data loss usually comes from |
|---|---|---|
| Field Service mobile app and model-driven apps | A mobile offline profile defines the tables, a filter per table and related records. The app runs against a local copy of Dataverse and plays changes back on reconnect. | Profile membership and scoping, playback failures, same-field conflicts, clock skew, and devices reset with work in the queue. |
| Canvas app in offline first mode on Dataverse | The app uses the same mobile offline profile and sync engine as model-driven apps, so formulas read and write a local copy. | The same causes as above, plus formulas or connectors that assume a live connection and fail on the device. |
| Canvas app with a hand built queue | Collections hold data in memory; SaveData and LoadData persist them on the device; the app sends queued items with Patch when connected. | Collections never persisted, Patch results never checked, no unique key so retries duplicate, and no retry after a partial failure. |
What is the durable pattern for an offline field app that cannot lose data?
The pattern is the same whichever model you run; what changes is how much of it the platform does for you and how much you build. On the Field Service mobile app most of the queue is the platform, and the work is in the data model, conflict ownership and visibility. On a hand built canvas queue every step below is your code. These are the steps we build to.
- 1. Write every submission to a durable local queue first. The Submit button saves to storage on the device, never straight to the server. In the Field Service mobile app and in offline first canvas apps on Dataverse the platform keeps that queue; in a canvas app with a hand built queue it means SaveData after every change, not only when the app closes. The technician sees "saved on this device" immediately and "synced" later, as two different states.
- 2. Give every record a client-generated unique key. Generate a GUID on the device at the moment of capture and store it on the record, either as the Dataverse row ID supplied on create or in a column that carries an alternate key. The key belongs to the piece of work, not to the attempt to send it, so every retry refers to the same record.
- 3. Stamp metadata on every record. Store the device identifier, the signed in user, the captured time from the device, the app version and a sync status on the record itself. Stamp a received time server side as well, for example in a plugin on create. Comparing captured and received times is how you spot clock skew and late syncs without asking the technician.
- 4. Send with idempotent upsert. Create or update by the client key rather than blindly creating. A resend after a timeout, a double tap or a retry storm then updates the same row instead of producing a duplicate work order, time entry or parts line. The same rule applies to anything downstream, such as a flow that posts consumption to an ERP.
- 5. Retry explicitly and keep failures visible. Check the result of every write (in canvas apps, IfError or Errors after each Patch), keep failed items in the queue with the error text, retry on reconnect, and never drop an item because a single attempt failed. Anything that fails for a reason a retry cannot fix goes to an exception list that a named person owns.
- 6. Prefer inserts to updates in the data model. Parts consumed, measurements, service task results, time entries and notes are child records. Two people adding child rows to the same job never collide; two people editing one shared field always will. Most conflicts are designed out here rather than resolved later.
- 7. Publish a reconciliation view. Show the technician what is still waiting on the device, and show the back office what was completed on a device but never received, last successful sync per person, and the exception list. Data that fails loudly is recoverable; data that fails silently is how work goes uninvoiced.
How should sync conflicts be resolved, and when is last-write-wins acceptable?
The Field Service offline client tracks changes column by column, so two people editing different fields on the same work order do not overwrite each other. Two people editing the same field is different: the later sync wins, silently. That is a reasonable rule for some fields and a data loss bug for others, and the honest answer is to decide per field rather than look for a global setting that makes conflicts go away. Server side plugins count as an editor too: a plugin that recalculates a column on save will beat a technician who has been offline since morning.
| Kind of field | Last-write-wins? | Better choice |
|---|---|---|
| Owned by one role (booking status set by the technician, priority set by dispatch) | Acceptable | Enforce the owner with form rules and security so the other side cannot edit it once work starts. |
| Reference data corrected in the office (address, contact) | Acceptable, office wins | Keep it read-only on the device so the technician cannot create a conflict. |
| Counts, meter readings and measurements | Not acceptable | One child record per reading with its captured time and author; never overwrite a single number. |
| Parts consumed and time worked | Not acceptable | Insert-only lines (work order products, time entries) so every contribution survives. |
| Free text notes and findings | Not acceptable | Append notes as separate records rather than editing one description field. |
| Values two people genuinely co-own | Not acceptable | Detect the conflict, keep both versions, and route it to a person to decide in the reconciliation view. |
How do you reconcile weeks of conflicting edits when crews edited the same job sheets offline?
When crews have worked the same jobs offline for days or weeks, and the back office now holds a version nobody trusts, the goal is not to guess the right answer. It is to recover every contribution, decide the disputed ones deliberately, and leave a trail. We work through it in this order.
- Freeze the damage first: stop reinstalls, sign-outs and device swaps until every device has synced or its pending work has been captured.
- Collect every source: the server records, Dataverse audit history for the affected tables, the pending queues and sync error lists on each device, service reports and photos already produced.
- Build a timeline per job from captured time, author and device, not from the order the server happened to receive changes.
- Split additive data from disputed data: parts, readings, time and notes from different people usually all stand and simply need to exist as separate rows; true disagreements on one value are few once that is done.
- Decide disputed values with the people who own them, and record the decision, the decider and the reason on the record.
- Correct billing and stock only after the job data is settled, so invoices and van stock are adjusted once rather than repeatedly.
- Change the data model and ownership rules before the crews go back out, or the same reconciliation will be needed next month.
What should a reconciliation view show so nothing is lost silently?
Offline failures are expensive mainly because nobody sees them until month end, when work that was done was never invoiced because it never arrived. A reconciliation view turns that into a daily list someone can clear. On Dataverse it is usually a handful of views, a dashboard and a scheduled flow rather than a product. Reading the audit trail on an individual disputed record is easier with a readable audit panel such as our free Easy Audit PCF control.
- Pending on device: the count of unsynced items per technician and the age of the oldest one, visible to the technician before they sign out.
- Last successful sync per person on the dispatch board, with an alert when it is older than a working shift.
- Completed but not received: bookings a technician marked complete, or jobs dispatch expected to close, with no matching completion on the server.
- Captured versus received time gaps, which reveal late syncs and clock skew.
- Exceptions: writes rejected by validation, duplicate detection, a deleted record or a lost security privilege, each with the error text and an owner.
- Resolved conflicts with both values, the decision and who made it.
How do you troubleshoot Field Service mobile offline when technician work is not arriving?
Most reports of offline not working are configuration rather than fault. Three things must be true before a technician is genuinely offline capable: the mobile offline profile has been published after its last change, the user is a member of that profile, and the app has completed a first full sync on that device while it still had signal. A technician with the right license and no profile membership gets no error, just an app that silently works only in coverage, which is why the problem tends to be discovered in a basement. After that, check the playback failures that are not conflicts at all.
- Scope the profile filters to the technician: their own bookings, their territory and a bounded window of service history. A profile that pulls years of work orders per user makes first sync take hours, fills the device and slows every later sync.
- A booking reassigned while the technician was offline can fall outside their profile filter, so their changes come back with nowhere to land.
- A record deleted in the back office cannot be updated, and a duplicate detection rule or business rule added last week can reject the write.
- All of these land in the sync error list on the device, where only the technician sees them, so surface them in the reconciliation view instead.
- Licensing decides who can be offline at all: a full Field Service user license includes the mobile app with offline; Team Members rights do not cover executing work orders; the Field Service Contractor license is deliberately restricted, so check it against the real workflow before relying on it.
- Continuous location tracking leaves gaps while a device is offline or suspended. If arrival and departure evidence matters, stamp the device position onto the booking at the status change, which is a local write that syncs with the queue, and exclude the app from battery optimisation across the fleet.
How do you recover from the CreatedDate in future sync error without losing a day of work?
This error deserves its own runbook because the obvious reaction to it makes the loss permanent. The device created records while its clock ran ahead of the server, the platform rejects a record that claims to have been created in the future, and because the queue is ordered that one record blocks everything behind it while the technician keeps working.
- Confirm the diagnosis: note the last successful sync and the failing record in the app sync status, then compare the device clock with a trusted source and with server time.
- Do not reinstall the app, clear its data or sign the technician out. Each of those discards the local queue, and the unsynced work orders, photos, readings and signatures exist nowhere else.
- Fix the clock properly: date and time set to automatic, correct time zone, then reboot so the clock resynchronises from the network.
- Trigger a manual sync and watch the queue drain; in most cases the rejected record is accepted once the skew is gone and the rest follows.
- If one record stays rejected, capture its contents first (a screenshot if necessary), discard that single change so the queue can move, and re-enter it in the browser.
- Close the hole: enforce automatic network time through Intune or your device management, block manual time changes, and monitor last successful sync per person. A device that keeps drifting belongs out of the rotation.
Should offline field capture run on Dynamics 365 Field Service, Power Apps or a custom application?
We recommend the right solution - whether that's Microsoft Dynamics 365, Power Platform, or a custom-built CRM. Some businesses need the Microsoft ecosystem. Others need full control without licensing. We deliver both. For offline field work, the Field Service mobile app is the natural choice when work orders, assets and scheduling already live in Dynamics 365, and our Field Service implementation partner page describes how that build and its offline design are scoped. A canvas app on Dataverse fits focused capture such as inspections and shop floor checks, covered in how Power Apps replaces paper forms on the shop floor. A custom application on React, Node.js, PostgreSQL or .NET is the better answer when you need full control of the sync engine and conflict model, the device fleet is outside Microsoft licensing, or the offline workflow is the product itself. In that case the durable pattern above is not optional: it is the specification.
Should your field app run on Dynamics 365, Power Platform or a custom-built application?
Can afford licensing and want the Microsoft ecosystem
Dynamics 365
Microsoft 365, Teams and Outlook integration, a mature partner ecosystem, Copilot, and apps for sales, service and field operations that are configured rather than built.
Need full control and zero licensing
Custom CRM
A CRM built on React, Node.js, PostgreSQL or .NET that you own outright: your data model, your hosting, no per-user subscription, and features shaped exactly to your process.
Not sure which fits
We help you decide
A short discovery weighs licensing budget, process complexity, integrations and long-term ownership, then recommends one path. We deliver both, so the recommendation has no reason to lean.
What does fixing an offline data loss problem involve with Solzet?
It starts with a short, remote audit of the live estate rather than a rebuild proposal: the offline profiles and filters, license entitlements per role, the conflict surface in the data model, server side logic touching technician owned columns, device policy, and the sync error backlog nobody has been reading. From that we fix configuration first, then the data model and ownership rules, then add the reconciliation view, and where a canvas app has a hand built queue we rebuild the queue to the pattern above. Solzet delivers remotely from Yerevan, Armenia, with 8+ years of Dynamics 365 and Power Platform work. For manufacturers in Germany and DACH, where works council rules shape what location data a device may capture, see our manufacturing industry page. If offline problems are one symptom of a wider Field Service programme across mixed legacy versions, see transforming Field Service on a legacy estate.
What do people ask us?
Why does our Power Apps or Field Service mobile app lose data when technicians are offline?
Usually one of four causes: a same-field conflict resolved last-write-wins that overwrites an earlier value, a device clock running ahead so the server rejects records and the ordered queue stalls, a reinstall, clear data or sign-out that discards the local queue before it syncs, or a canvas app that keeps submissions in memory and loses them when the app restarts. Each leaves a recognisable symptom and each has a structural fix.
How does Dynamics 365 Field Service mobile resolve sync conflicts?
The offline client tracks changes column by column and plays them back on reconnect, so edits to different fields on the same record do not overwrite each other. When two people change the same field, the later sync wins silently and the earlier value is gone. Give shared fields a single owner, record readings, parts, time and notes as child records, and keep server side plugins off columns a technician owns.
When is last-write-wins conflict resolution acceptable?
For fields with one clear owner, such as a booking status set by the technician, and for reference data the office corrects and the device only reads. It is not acceptable for counts, meter readings, measurements, parts consumed, time worked or free text findings, where each contribution should be its own record, or for values two people genuinely co-own, which should be detected and decided by a person.
How do we stop offline retries creating duplicate records?
Generate a unique key on the device when the work is captured, store it on the record as the row ID or in an alternate key column, and send with upsert by that key rather than a plain create. A resend after a timeout or a double tap then updates the same row. Apply the same key to downstream integrations so they cannot double post either.
What should we do about the CreatedDate in future sync error?
It is device clock skew. Do not reinstall the app, clear its data or sign out, because that discards unsynced work. Set the device to automatic network time with the correct time zone, reboot, and trigger a manual sync. If one record stays rejected, capture its contents, discard that single change so the queue can move, and re-enter it in the browser. Enforce automatic time through device management to prevent it.
Can a canvas app keep submissions safe if the app is closed or the phone restarts?
Only if the queue is persisted. A collection lives in memory and is lost when the app closes. Either use the offline first mode for canvas apps on Dataverse, which persists through the mobile offline profile, or save the queue to the device with SaveData after every change and reload it with LoadData on start. SaveData and LoadData work in the mobile player, not in a web browser.
How do we reconcile weeks of offline edits from crews working the same jobs?
Stop device resets until everything has synced, collect server records, audit history, device queues and service reports, rebuild a timeline per job from captured time and author, keep additive data such as parts and readings as separate rows, decide the few genuinely disputed values with their owners and record the decision, then correct billing and stock once. Change the ownership rules before crews go back out.
Where should you go next?
Dynamics 365 Field Service implementation partner
How a Field Service build is scoped, including offline profile design and a pilot on a real device.
Power Apps vs inspection platforms
Cost, licensing, offline and photo handling compared for field inspection apps.
Power Apps replacing paper forms on the shop floor
Designing capture that validates at entry and works on a poor plant network.
Dynamics 365 for manufacturing in Germany and DACH
Offline first technicians, works council scoping and ERP van stock reconciliation.
Solzet Easy Audit
A free PCF control that makes Dataverse audit history readable when reconciling disputed records.
Custom CRM Development
Field apps with a sync engine you control, on React, Node.js, PostgreSQL and .NET, without Microsoft licensing.
Which solution is right for your business?
Tell us what you need. A senior consultant replies within one business day with a recommendation - Dynamics 365, Power Platform, or a custom-built CRM - not a sales script.