Offline web app for field work: how to work without a signal
A web application can keep working where there is no signal – in a basement, on a construction site, in a warehouse or out in the countryside. The condition is that offline mode is designed as part of the work process, not bolted on just before launch. Technically, it consists of a service worker that stores the application on the device, a local database in the browser for records in progress and an outgoing queue of changes that the application sends to the server once the connection returns.
Success, however, depends on the rules: what data a field worker carries along, what they may do without the server, how long unsent records may stay on the phone and what happens when the office changes the same record in the meantime. This article is for business owners and managers who are planning an application for service technicians, site surveys, stocktaking or inspections and are considering how an offline web app should work.
Example: boiler inspections in basements without a signal
Illustrative example; the company is fictional. A service company carries out inspections of gas boilers, often in boiler rooms and basements without mobile signal. Today, the technician writes findings on paper, retypes them into the system in the evening and sends photos through a private chat.
Target state: in the morning, on the company Wi-Fi, the application downloads the day’s schedule, addresses, equipment history and inspection report forms. On site, the technician fills in the report, attaches photos and the customer signs on the screen. The record is saved on the phone with the status „Waiting to be sent“. When the signal returns, the application sends it, the server confirms receipt and the status changes to „Sent“. If the office has cancelled the job in the meantime, the technician sees a conflict to resolve, not a silent overwrite of their work.
What offline mode must handle – and what it must not
The first decision is not technical. For each task, decide whether it is done fully offline, as a draft that the server confirms, or online only. Leave everything that needs a single authoritative state – invoice number sequences, stock, prices – on the server.
| Task | Offline | Why |
|---|---|---|
| View the day’s schedule and equipment history | Yes, from data downloaded in advance | The technician needs context even without a signal |
| Fill in a report, attach photos and a signature | Yes, saved locally and sent later | The main reason for introducing offline mode |
| Create a new job on site | Yes, as a draft with a temporary identifier | Only the server assigns the job number |
| Issue an invoice or reserve goods | No, only prepare the documents | The server controls number sequences and stock levels |
| Change the price list or permissions | No | This data should have a single source of truth |
Every „yes“ in the table means extra development and testing. Offline mode should therefore include only the tasks that genuinely happen without a signal.
Technical building blocks and their limits
Service worker and the stored application
A service worker is a script that runs in a separate thread. When it is installed, it can store the application’s pages, styles, scripts and images in a local cache and then intercept its requests – either cache first, or network first with the cache as a fallback. According to MDN’s guide to offline and background operation, the right strategy depends on the specific application. For a field application, we recommend serving the application interface itself from the cache with clear versioning and keeping job data in a local database that the application refreshes from the server whenever it is connected.
Local database: IndexedDB, not localStorage
localStorage stores only string key–value pairs and, according to MDN’s documentation on storage quotas, is limited to 5 MiB per origin. That is not enough for photos and a queue of changes. IndexedDB is designed for larger structured data, and the origin private file system (OPFS) for files.
Quotas and storage eviction
By default, data is stored in „best-effort“ mode, meaning without a guarantee of persistence: it stays as long as the origin is below its quota, the device has enough space and the user does not delete it. When space runs low, the browser deletes the data of the least recently used origins – always all of an origin’s data at once, never just part of it (MDN).
Quotas are high, but they are not a guarantee. Chromium-based browsers allow an origin up to 60% of total disk capacity, Firefox in best-effort mode the smaller of 10% of the disk or 10 GiB, and Safari from version 17 around 60% of the disk (MDN). However, the calculation uses total capacity, not free space, and according to the WebKit blog post on storage policy, the quota is an upper limit with no guarantee. The application must therefore handle the QuotaExceededError.
In addition, when cross-site tracking prevention is turned on, Safari deletes script-created data if the user has not interacted with the site during the last seven days of browser use. Persistent storage, which the application requests via navigator.storage.persist(), protects against eviction when space runs low. Firefox asks the user, Safari and most Chromium-based browsers decide automatically based on the history of interaction, and WebKit also considers whether the site is launched from the Home Screen. According to research by the Chrome team cited by MDN, browsers very rarely delete the data of regularly visited sites. Still, treat the phone as a temporary buffer, not as the place where company data should stay.
Connection status and background sync
The navigator.onLine property is not reliable: a connection to a local network is generally considered online even if that network has no internet access. MDN therefore advises against disabling features based on it and recommends only hinting that the user may be offline. Treat a record as sent only once the server has confirmed receiving it.
The Background Synchronization API makes it possible to defer sending to the service worker until the connection is stable. However, MDN marks it as having limited availability, and it works only in a secure context (HTTPS). The request can be registered only while the application is open, the browser may retry only a limited number of times and it stops an operation that takes too long, after which the next attempt starts from the beginning (MDN). Background sync is therefore a bonus. The basis should be sending when the application opens, after the connection is restored and via a „Send now“ button, in small batches that can be safely repeated.
Implementation in seven steps
- Map the field work. Find out where and for how long people have no signal, which devices they use (company or personal, iPhone or Android) and how many records and photos are created each day.
- Define the offline scope. For each task, decide according to the table: fully offline, draft for confirmation or online only.
- Prepare the data model. Every record gets a unique identifier (for example a UUID), a version and a sync status while still on the device. The server must recognise a repeated submission and not create a duplicate.
- Build the outgoing queue. A change is first written to the local database and the queue, and only then sent – in order of creation, in batches and with retries. Photos are uploaded only once the server has accepted the record itself.
- Take care of storage. Request persistent storage, monitor the usage estimate via
navigator.storage.estimate(), downscale photos before saving to the resolution the process really needs and delete local copies once the server confirms them. - Show the sync status. Every record should show whether it is waiting to be sent, has been sent or has a conflict. The application must warn before logout, and an expired login must not stop work or delete the queue.
- Test in real conditions. Try airplane mode, Wi-Fi without internet, closing the application while sending, full storage and deploying a new version with unsent data – on both iPhone and Android.
Conflicts: who wins when a record has changed in two places
A conflict arises when a technician edits a record offline and someone else changes it on the server in the meantime. The „last write wins“ rule is the easiest to program, but it silently discards one person’s work. Define the rules in advance for each type of data.
| Situation | Recommended rule | Trade-off |
|---|---|---|
| The technician completes the report, the office corrects the customer’s contact details | Merge field by field; each field has its owner | Field ownership must be defined precisely |
| The office cancelled the job, the technician carried it out in the meantime | Do not overwrite; flag the conflict for the dispatcher to decide | Someone has to resolve conflicts regularly |
| Two technicians edited the same record | Accept the change made to the current version, return the other one as a conflict | The second technician has to review their change |
| Photos, notes and signatures | Append only, never overwrite | More stored data, but nothing gets lost |
| Price lists and reference data | The server is the only source; the device only reads them | Offline, the device may hold an older version |
In a conflict, keep both versions together with the author and time. Otherwise, a dispute about what the technician actually recorded on site cannot be resolved afterwards.
Web application (PWA) or native app?
A web application has one codebase for all devices, is distributed via a link, and you deploy a new version to the server without app stores. However, you accept the browser’s rules: best-effort storage unless the browser grants persistent mode, limited background sync and a service worker that the browser stops when it considers it appropriate. A native app can store data in its own storage outside the browser, so these quotas and eviction rules do not apply to it. On the other hand, it means developing for both iOS and Android and distributing through app stores or through company device management.
- A web application is usually enough if the work involves forms, checklists, photos and signatures and the devices connect at least once a day.
- Consider a native app if people work without a connection for whole days, need large volumes of data on the device, such as maps or videos, or data must be sent in the background without opening the application.
Decide before development. Switching approach halfway through the project means reworking storage and synchronisation – the very core of offline mode.
Common mistakes
- Offline mode only after launch. A data model without local identifiers and versions is hard to rework later.
- Relying on
navigator.onLine. Wi-Fi without internet looks like a connection and records get stuck. - Data in
localStorage. Text only and small capacity – unsuitable for photos and the queue. - The phone as the only copy. Unsent records sit on the device for days, even though the browser can delete the site’s data all at once.
- Invisible sync status. The technician does not know what has been sent and logs out or clears the browser data.
- A new version without migration. The update cannot read the unsent queue or deletes it.
- Private browsing. Data is usually deleted when the private browsing session ends, so do not use it for field work.
Pre-deployment checklist
- The task table (offline, draft, online only) has been approved by both the field team and the office.
- Every record has a local unique identifier, a version and a sync status.
- The server recognises a repeated submission and does not create a duplicate.
- Records and photos are stored in IndexedDB or OPFS, not in
localStorage. - The application requests persistent storage, monitors its usage and copes with full storage.
- Successful sending is confirmed by the server, not by the browser’s connection status.
- Synchronisation also works without the Background Synchronization API.
- Conflict rules are written down and tested, and someone is responsible for resolving conflicts.
- Neither logout nor an expired login deletes unsent data without a warning.
- Devices hold only the data needed for current jobs, and phones have a screen lock.
Frequently asked questions
Does an offline web app work on iPhone?
Yes. Since version 17, Safari fully supports the Storage API, and a web app added to the Home Screen has the same quotas as in the browser. When deciding on a request for persistent storage, WebKit takes into account whether the site is opened as a Home Screen web app (WebKit). We therefore recommend adding the application to the Home Screen and syncing at least once a day. In the EU, browsers with a different engine can also run on iOS from version 17.4, and they apply their own storage rules (MDN).
How much data can the application store on a phone?
It depends on the browser and the device. The upper limits are high, but they are calculated from total disk capacity, not free space, so the real constraint may be a full phone. The application should monitor the usage estimate, downscale photos and delete local copies once the server confirms them.
What happens if the technician closes the application before sending?
Records saved in IndexedDB stay on the device and the application sends them the next time it is opened. If the browser supports the Background Synchronization API and the request was registered while the application was open, it can send them even after the application is closed. However, this feature is not available everywhere and the browser limits both the number and the duration of attempts, so the technician should always see what is still waiting to be sent.
Do we need a native app because of offline mode?
For forms, photos and signatures with daily synchronisation, usually not. Consider a native app for days without a connection, large volumes of data on the device or the need to send data in the background. Make the decision before development starts.
How to get started
If you want your field staff to stop retyping paperwork and sending photos through chat, start with the task table and one real working day in the field. Visit Webiant to see how we build custom web applications, or get in touch via our contact page. We will help you define the offline scope, design synchronisation and conflict rules and test the application in the conditions in which you will use it. If the reports need to flow on into an ERP or CRM, we can also prepare the API integration. You will find more practical guides on our blog.
Sources
- Storage quotas and eviction criteria – MDN Web Docs
- Offline and background operation – MDN Web Docs
- Background Synchronization API – MDN Web Docs
- Navigator: onLine property – MDN Web Docs
- Updates to Storage Policy – WebKit blog