Last updated: 03/08/2026

The short answer

An offline-first app is not an app with a cache bolted on at the end. Google defines it plainly in its own architecture guidance: "An offline-first app is an app that is able to perform all, or a critical subset of its core functionality without access to the internet." The same guide sets out what that obliges you to do, and the obligations are structural rather than cosmetic: the app must "remain usable without a reliable network connection" and must "present users with local data immediately instead of waiting for the first network call to complete or fail".

Read that second clause slowly, because it is the one that decides your architecture. Most apps are built the other way round. A screen opens, it fires a request, and it shows a spinner until the answer arrives. On a good network that is invisible. In a lift, a basement carpark or a rail tunnel it becomes a spinner that never resolves, and every tap the user made is gone. Turning that around means the screen reads from a local store first and treats the network as a background refresh — and that is a decision about where your data lives, made in week one, not a feature you can add in week twenty.

Where Singapore apps actually lose signal

Singapore is one of the easiest places in the world to forget about connectivity, and that is precisely the trap. Coverage here is good enough that the entire build team tests on office Wi-Fi, the demo runs on office Wi-Fi, and nobody discovers the failure mode until a real user is standing somewhere with concrete above them. The published regulatory standards make the gap concrete, because they are not written as promises of perfection.

IMDA measures three things and publishes the results quarterly. Its Quality of Service Performance Results for January to March 2026 state that "mobile operators are required to achieve Nationwide Outdoor Service Coverage of > 99%", that they must achieve "a service coverage of > 85% per building", and that they must reach "> 99% for all road and MRT tunnels". Coverage in all three cases means "the ability of a cellular network to achieve the minimum signal strength of at least -109dBm", sampled with real handsets rather than modelled.

The in-building number is the one worth pausing on. The standard is 85 percent per building, and IMDA is explicit that coverage "is measured at randomly selected buildings and at publicly accessible areas within the tested buildings as a proxy for the coverage in the entire building to avoid disturbing residents in their units". So a fully compliant operator can leave roughly one in seven sampled points below the usable threshold, and the sampling deliberately excludes the interior spaces where people actually live and work. In the Q1 2026 survey, of the same sixty buildings tested across four operators, the pass counts were 59, 60, 57 and 60 — meaning some buildings failed even that 85 percent bar for some operators.

What IMDA measuresCompliance standardQ1 2026 result as published
Nationwide outdoor service coverage"> 99%"Standard published; per-operator outdoor figures are presented separately on the IMDA page
In-building service coverage"> 85% per building"Buildings passed of 60 tested: M1 59, Singtel Mobile 60, StarHub Mobile 57, SIMBA 60
Road and MRT tunnel coverage"> 99% for all road and MRT tunnels"Pass across all listed road tunnels and MRT lines except Downtown Line, where Singtel Mobile and SIMBA are marked Fail

Standards and results as published by IMDA, Quality of Service Performance Results for January – March 2026, survey period Q1 2026, retrieved 3 August 2026. Coverage is defined by IMDA as achieving "the minimum signal strength of at least -109dBm". IMDA's own footnote on the tunnel table reads: "Coverage at Downtown Line is progressively being enhanced. Singtel and SIMBA did not meet the 4G QoS standard of >99% in Q1 2026. Operators are working on completing the enhancement work to improve mobile coverage."

A masked commuter sits in a metro carriage looking down at the phone in her hand, beside a blue priority-seat notice in Vietnamese
A tunnel is the ordinary case, not the edge case. IMDA holds operators to more than 99 percent coverage in road and MRT tunnels — and published two of the four operators as not meeting it on the Downtown Line in Q1 2026. Photo: Pexels.

None of this is a criticism of the networks; a 99 percent standard enforced quarterly is a strong regime. The point for anyone commissioning an app is narrower and more practical. Regulation guarantees a very high floor across a whole city, and your user is not a city. Your user is one person, in one lift lobby, in one cold room at the back of a restaurant, in one basement carpark at the moment they need to close off a job. The delivery rider taking a photo of a doorstep, the technician filling in a service report in a plant room, the retail assistant doing a stocktake in a back room, the nurse recording a home visit in an older HDB block — these are the moments your app is judged in, and they are all indoors, underground or moving.

What offline-first actually means

Offline-first is a data architecture, and Google states the minimum bar in one sentence: "In an offline-first app, there must be at least one data source that does not need network access to perform its most critical tasks." It follows that up with the floor everyone should hold their build to — "At a minimum, an offline-first app must be able to perform reads without network access" — and then removes the excuse most teams reach for, noting that "offline-first apps don't need to be able to write data when offline to be considered offline-first".

That last line matters commercially, because it means offline-first is not all-or-nothing. There is a cheap tier and an expensive tier, and knowing which one you need is most of the scoping conversation. Read-only offline — the catalogue, the schedule, the price list, the previously loaded order, the customer record you opened five minutes ago — is comparatively inexpensive and covers a large share of real-world frustration. Write-capable offline, where a user creates or edits data with no network and the app reconciles it later, is a different order of work because it drags in queuing, retries, conflict resolution and a much larger test matrix.

The useful way to scope this is to walk each screen and ask what it should do with no signal, rather than deciding "the app should work offline" as a single line item. The answers vary enormously within one product, and paying for write-sync on a screen that only ever displays a read-only report is waste.

What the user is doingTypical build, no signalOffline-first build, no signal
Opening a list they viewed earlier todaySpinner, then a generic error; list is emptyLocal copy renders immediately, with a marker showing when it was last refreshed
Searching their own recordsFails; search is a server callRuns against the local database; results are instant even with full signal
Filling in a long form or job reportSubmit fails; entered data is often lost on the error screenSaved locally on entry, queued, sent when connectivity returns
Taking and attaching photos in the fieldUpload fails or hangs; user re-shoots later, or does notStored on device, uploaded as a background transfer under set conditions
Reading a document, manual or ticketUnavailable unless already openPre-fetched while on Wi-Fi, available regardless of signal
Paying or confirming a bookingFailsStill fails, and correctly so — this is an operation that must be confirmed by the server

Reading aid, not a specification. The behaviours in the right-hand column are architectural patterns described in Google's offline-first data layer guide and in Apple's and Firebase's published documentation, cited in Sources. The last row is deliberate: not every action should work offline, and a good scope says so explicitly.

The local database becomes the source of truth

The structural change in an offline-first build is that the screen stops talking to the network. It talks to a local store, and something else keeps that store fresh. Google puts the rule bluntly: "The local data source is the canonical source of truth for the app. It should be the exclusive source of any data that higher layers of the app read. This ensures data consistency between connection states." That last clause is the real prize — the app behaves the same way whether the signal is full, weak or absent, because the code path does not branch on connectivity at all.

Underneath, this is less exotic than it sounds, because the storage engine is already on every device you ship to. SQLite's own site notes that it is found in "Every Android device", "Every iPhone and iOS device" and "Every Mac", and describes its purpose in terms that could have been written for this article: "SQLite strives to provide local data storage for individual applications and devices", and it "thrives at the edge of the network, fending for itself while providing fast and reliable data services to applications that would otherwise have dodgy connectivity". You are not adopting an experimental technology. You are using the one that is already there.

On Android the recommended route is Room, and Google's justification for it is the offline case verbatim: "The most common use case is to cache relevant pieces of data so that when the device can't access the network, your users can still browse that content while they're offline." Google adds that Room "provides an abstraction layer over SQLite" and that "we recommend using Room instead of using the SQLite APIs directly". For small key-value settings rather than records, Google points elsewhere and is clear about the limits: DataStore "is ideal for small datasets and does not support partial updates or referential integrity", and if you need "large or complex datasets, partial updates, or referential integrity, consider using Room instead". On Apple platforms the equivalent framing appears in Apple's own SwiftData documentation, which describes an app that "fetches data from a remote web service" using SwiftData "to implement a lightweight caching mechanism and provide limited offline functionality".

The piece that holds it together is the repository. Google's data layer guide states that "other layers in the hierarchy should never access data sources directly; the entry points to the data layer are always the repository classes", and lists "resolving conflicts between multiple data sources" among the repository's responsibilities. In practical terms this is the thing to look for when someone hands you an architecture diagram: if screens call the API directly, the app is not offline-first and cannot be made so cheaply, whatever the proposal says.

Building blockWhat its publisher says it doesWhere it fits
SQLite"provide local data storage for individual applications and devices"; present on every Android and iOS deviceThe engine underneath almost every on-device store
Room (Android)"an abstraction layer over SQLite"; caches data "so that when the device can't access the network, your users can still browse that content while they're offline"The local source of truth for structured records
DataStore (Android)"ideal for small datasets and does not support partial updates or referential integrity"Settings and small key-value state, not records
SwiftData (Apple)used "to implement a lightweight caching mechanism and provide limited offline functionality"The local store on Apple platforms
WorkManager (Android)work is "stored in an internally managed SQLite database" and persists "across device reboots"; supports network constraints and "a configurable exponential backoff policy"Draining the outgoing queue when conditions allow
Background URLSession (Apple)"makes it possible for transfers to continue even when the app itself is suspended or terminated"Uploads and downloads that outlive the screen
Cloud Firestore offline persistence"caches a copy of the Cloud Firestore data that your app is actively using"; on "Android and Apple platforms, offline persistence is enabled by default"A managed option where the sync layer is provided

Every description is quoted from the publisher's own documentation, retrieved 3 August 2026 — SQLite, Google (Room, DataStore, WorkManager, Firestore) and Apple (SwiftData, URLSession). This is a map of what each component is for, not a recommendation of one over another; the right combination depends on the product, and no claim is made here that any option is faster, cheaper or better than another.

Writes have to queue

Reads are the easy half. The moment a user can create something without a network, you owe them a guarantee that it will not evaporate, and that guarantee is what costs money. Google's guidance describes the pattern in one line — "write to the local data source first, then queue the write to notify the network at the earliest opportunity" — and the interesting word there is queue, because a queue implies durability, ordering, retries and a component that survives the app being closed.

On Android that component is WorkManager, and Google recommends it precisely for work "that will continue to run even if the app leaves the visible state", noting that it "features a robust scheduling mechanism that lets tasks persist across app restarts and device reboots". Two details from Google's documentation are worth writing into a specification rather than leaving to a developer's judgment. First, constraints: you can "declaratively define the optimal conditions for your work to run", for example "when the device is on an unmetered network, when the device is idle, or when it has sufficient battery". Second, failure handling: WorkManager "offers flexible retry policies, including a configurable exponential backoff policy", where the default policy is exponential and the backoff delay "can be no less than 10 seconds".

Apple's equivalent guarantee lives in background sessions. Apple's documentation for background URLSession configurations states that "in iOS, this configuration makes it possible for transfers to continue even when the app itself is suspended or terminated", and that a relaunched app "can use the same identifier to create a new configuration object and session and to retrieve the status of transfers that were in progress at the time of termination". There is a limit worth knowing before you promise anything to a client: "if the user terminates the app from the multitasking screen, the system cancels all of the session's background transfers". Apple also suggests marking time-insensitive transfers as discretionary "so the system can wait for optimal conditions to perform the transfer, such as when the device is plugged in or connected to Wi-Fi".

There is also a smaller, cheaper fix that many apps never apply. By default, an iOS network request fails the instant connectivity is missing. Apple's waitsForConnectivity flag changes that: it is "a Boolean value that indicates whether the session should wait for connectivity to become available, or fail immediately", and when it is false "the connection fails immediately with an error". In its session Optimizing Your App for Today's Internet, Apple explains why this beats checking reachability first: "there is a race condition where the system might tell you that you have connectivity to a server but by the time you create and send your request, you've lost your chance and you're no longer connected to the server. We recommend using waitsForConnectivity which will simply send out your request as soon as a connection to the server is available." This is a single configuration line, and on its own it converts a class of instant failures into brief waits.

Reconciling when the network comes back

Everything above buys you a new problem, and it is the one that separates a demo from a product. Google names it: "when an offline-first app restores its connectivity, it needs to reconcile the data in its local data source with that in the network data source. This process is called synchronization." And then the sharp edge: "if, when offline, the app writes data locally that is misaligned with the network data source, you must resolve the conflict before synchronization can happen. Conflict resolution often requires versioning."

Conflict is not a rare event in the businesses that most need offline support. Two supervisors update the same job sheet. A stock count is edited on a tablet in the warehouse and on a desktop in the office. A price changes on the server while a rep is quoting from a cached list underground. Somebody has to decide which version wins, and if nobody decides deliberately, the framework will decide for you. Google describes the common default: "for mobile apps, a common approach is 'last write wins'", where "devices attach timestamp metadata to the data they write to the network" and the server "discards any data older than its current state". Firebase applies the same rule to Cloud Firestore, stating that "for multiple changes to the same document, it's last write wins".

Last-write-wins is a legitimate choice and often the right one. What it must never be is an accident. If your app records safety inspections, stock levels or anything a regulator or an insurer might ask about later, silently discarding an earlier edit is a business decision that deserves to be made by the business, not inherited from a default. The alternatives — field-level merging, keeping both versions and asking a human, or making certain records append-only so nothing is ever overwritten — all cost more, and all are cheaper than an argument about missing data eighteen months after launch. The question belongs in the scope document, in writing, per record type.

A masked courier stands among stacked parcels in a depot, holding a labelled package in one hand and a smartphone in the other
Depots, warehouses and cold rooms are where write conflicts are born: the same record edited on a handheld with no signal and on a desktop with one. Deciding which version wins is a business decision, not a default. Photo: Pexels.

Firebase is a useful illustration of how much of this a managed platform will do for you, and of where it stops. Its documentation states that offline persistence "caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline", that "you can write, read, listen to, and query the cached data", and that "when the device comes back online, Cloud Firestore synchronizes any local changes made by your app to the Cloud Firestore backend". It also flags the behaviour that catches teams out: "if you get a document while the device is offline, Cloud Firestore returns data from the cache. When querying a collection, an empty result is returned if there are no cached documents. When fetching a specific document, an error is returned instead." An empty list and a real, current, genuinely empty list look identical to a user unless you design for the difference — which is why Firestore exposes a staleness signal, and why someone has to remember to use it: "if fromCache is true, the data came from the cache and might be stale or incomplete".

What the user sees while they wait

Offline handling is at least as much an interface problem as a data problem, and this is the part that gets cut when a deadline tightens. Apple's guidance is unusually direct about the correct response to a stalled connection. Its documentation for the delegate callback that fires when a task is waiting for connectivity states that "the delegate can use this opportunity to update the user interface; for example, by presenting an offline mode or a cellular-only mode". Apple is not describing a nice-to-have; it is describing the intended use of the callback.

The same session quoted earlier makes the user-experience argument explicitly, recommending that you "optionally... implement the taskIsWaitingForConnectivity delegate method which gets called when your task does not have connectivity", because "this can be helpful to present the user with a different flow or an offline UI for better user experience". Apple's Human Interface Guidelines put the underlying principle more broadly, advising designers to "show something as soon as possible", because "if you make people wait for loading to complete before displaying anything, they can interpret the lack of content as a problem with your app or game". An app that shows a stale list with an honest timestamp is read as working. An app that shows an empty screen is read as broken, and the review that follows says so.

Three interface rules follow from that, and none of them are expensive if they are specified up front. Show the data you have, and label how old it is. Show the state of anything the user created that has not yet reached the server, so a queued job reads as pending rather than as done or lost. And be explicit about the actions that genuinely cannot work offline — a payment, a confirmed booking, a final submission — so the user understands the boundary instead of tapping a dead button. Ambiguity is what generates support tickets; a clear "saved on this device, will send when you have signal" generates none.

Where offline data meets the PDPA

Caching data locally moves personal data onto a device that leaves your premises, and Singapore law addresses that directly. Section 24 of the Personal Data Protection Act 2012 requires that "an organisation must protect personal data in its possession or under its control by making reasonable security arrangements to prevent" both "unauthorised access, collection, use, disclosure, copying, modification or disposal, or similar risks" and, in its own separate limb, "the loss of any storage medium or device on which personal data is stored". A phone in a taxi is exactly the scenario the second limb describes.

Section 25 pulls in the same direction. It requires an organisation to "cease to retain its documents containing personal data, or remove the means by which the personal data can be associated with particular individuals, as soon as it is reasonable to assume that" the purpose for collection "is no longer being served by retention" and retention "is no longer necessary for legal or business purposes". A local cache that is never pruned quietly becomes a retention question, and an offline queue holding records for a user who left the company six months ago is a worse one.

None of this argues against caching, and none of it is legal advice — the specifics depend on your data and belong with a qualified adviser. What it does mean is that three engineering decisions stop being optional once you go offline-first: encrypting the local store rather than leaving it as a plain file, pruning cached records on a defined schedule rather than never, and clearing local data on logout and on remote wipe rather than only on uninstall. We cover the wider obligations in our guide to mobile app security and PDPA compliance; the offline-specific point is simply that the device is now part of your storage estate, and section 24 names it as such.

How to test this before your users do

Offline behaviour cannot be verified on office Wi-Fi, and it will not be verified by accident. Apple's advice on this is emphatic to the point of repetition: in the WWDC session cited above, its engineers say "you should build your app running Network Link Conditioner right from the start" and "don't think you can add in performance at the end because it's too late", and then, more forcefully, "always, always, always run and test your app using Network Link Conditioner and that way if you make a programming mistake that has horrible performance implications, you see it right away and you can fix it right away".

Google treats loss of connectivity as a standard test condition rather than a special case. Its core app quality guidelines instruct testers, while exercising the app, to "introduce interruptions from other apps, such as receiving a notification or a phone call" and to "apply transient changes to device attributes, such as network connectivity, battery function, GPS availability, and system load". It is worth being precise about what that does and does not say: it establishes network loss as something you are expected to test, alongside the stated criterion that an app "does not crash or block the UI thread causing ANR (Android Not Responding) errors". Neither Apple's App Store Review Guidelines nor Google's core quality guidelines contain a rule requiring an app to function offline, and anyone telling you the stores mandate offline support is overstating it.

What the stores do enforce is the visible consequence. Apple's App Store Review Guidelines state under App Completeness that "we will reject incomplete app bundles and binaries that crash or exhibit obvious technical problems", and separately require that "apps must be fully functional on IPv6-only networks". Guideline 4.2.3 adds that if an app "needs to download additional resources in order to function on initial launch", you must "disclose the size of the download and prompt users before doing so". A reviewer on an unfamiliar network who meets a screen that never loads is looking at an obvious technical problem, whatever caused it.

Three tests belong in every release checklist, and they take minutes. Put the device in airplane mode and open every primary screen — nothing should show an infinite spinner. Fill in your longest form with the network off, force-quit the app, reopen it, and confirm the work is still there. Then restore connectivity and confirm the queue drains, once, without duplicating anything. That third test is the one that finds the expensive bugs, and it is the one most often skipped. Because this is behaviour that regresses silently as features are added, it belongs in the recurring test pass rather than in a one-off launch checklist — the same discipline we describe in release management and staged rollout.

What this changes in your build budget

Offline capability is a scope decision with a real price, and it is one of the clearest examples of why a fixed quote depends on answering architecture questions before the estimate rather than after. Our published starting points on the Namtech pricing page are SGD 20,000 for a Starter or MVP build, SGD 38,000 for a Business app and SGD 90,000 for an Enterprise platform, and where a product sits on that list is driven by exactly this kind of structural requirement — not by the number of screens.

The cost is not evenly distributed, which is the useful part. Read-only offline is close to free if it is designed in from the start, because you are choosing where a screen reads from rather than adding a subsystem; the local store is going in anyway. Write-capable offline is a genuine addition: a queue, retry policy, conflict rules per record type, and a test matrix that has to cover the states between online and offline as well as the two ends. And retrofitting either into an app whose screens already call the API directly is the most expensive version of all, because it is not a feature, it is a rewrite of the data layer with every screen touched.

Two practical consequences follow. Decide per screen, not per app, and write the decision down; the phrase "the app should work offline" in a brief is a budget risk precisely because it can mean anything from a cached product list to full bidirectional sync. And treat this as an ongoing concern rather than a one-off, since every new feature can quietly reintroduce a direct network call on a critical path — the kind of work that lives in maintenance, which we publish from 15% of build cost per year. If you are still deciding how much to build in the first release, our comparison of an MVP against a full app build covers where this trade-off usually lands, and we scope offline behaviour screen by screen during the scoping call so the quote reflects what your users will actually hit.

Questions to ask before you sign anything

  • Which screens must work with no signal, and which must not? Ask for the answer screen by screen, in writing. "The app works offline" is not a specification.
  • Do screens read from a local store or call the API directly? If it is the API, the app is not offline-first, and changing that later is a data-layer rewrite rather than a feature.
  • What happens to data entered offline if the app is force-quit? The only acceptable answer is that it is already on disk.
  • Which record types can conflict, and who wins? Get last-write-wins stated explicitly if that is the choice, rather than inherited from a default.
  • How does the interface show stale data and pending work? Cached content with no timestamp and queued items with no status both read as bugs to users.
  • Is the local store encrypted, pruned and cleared on logout? PDPA section 24 names the loss of a device as a risk you must guard against.
  • Has anyone tested with the network off, then back on? Ask to watch it, on a real device, before sign-off.

Coverage standards are written for a city and your app is used by one person at a time, so the only sound assumption is that the signal will be gone at the exact moment your user needs the app most — and what happens in that moment is decided by where your data lives, in week one, not by a fix in week twenty.

Sources

All external statements below are quoted from the organisation that publishes them, retrieved 3 August 2026. Namtech pricing figures are our own published starting points. Nothing here is legal advice.

  • IMDA — Quality of Service Performance Results for January – March 2026 (survey period Q1 2026): "mobile operators are required to achieve Nationwide Outdoor Service Coverage of > 99%"; "mobile operators are required to achieve a service coverage of > 85% per building"; coverage "is measured at randomly selected buildings and at publicly accessible areas within the tested buildings as a proxy for the coverage in the entire building to avoid disturbing residents in their units"; "mobile operators are required to achieve a service coverage of > 99% for all road and MRT tunnels"; "the ability of a cellular network to achieve the minimum signal strength of at least -109dBm"; in-building results 59/60, 60/60, 57/60, 60/60 across M1, Singtel Mobile, StarHub Mobile and SIMBA; tunnel footnote "Coverage at Downtown Line is progressively being enhanced. Singtel and SIMBA did not meet the 4G QoS standard of >99% in Q1 2026."
  • Google — Build an offline-first app: "An offline-first app is an app that is able to perform all, or a critical subset of its core functionality without access to the internet"; "Remain usable without a reliable network connection"; "Present users with local data immediately instead of waiting for the first network call to complete or fail"; "In an offline-first app, there must be at least one data source that does not need network access to perform its most critical tasks"; "At a minimum, an offline-first app must be able to perform reads without network access"; "The local data source is the canonical source of truth for the app"; "Offline-first apps don't need to be able to write data when offline to be considered offline-first"; "Write to the local data source first, then queue the write to notify the network at the earliest opportunity"; "When an offline-first app restores its connectivity, it needs to reconcile the data in its local data source with that in the network data source. This process is called synchronization"; "you must resolve the conflict before synchronization can happen. Conflict resolution often requires versioning"; "For mobile apps, a common approach is 'last write wins.'"
  • Google — Data layer: "Other layers in the hierarchy should never access data sources directly; the entry points to the data layer are always the repository classes"; repositories are responsible for "Resolving conflicts between multiple data sources".
  • Google — Save data in a local database using Room: "The most common use case is to cache relevant pieces of data so that when the device can't access the network, your users can still browse that content while they're offline"; Room "provides an abstraction layer over SQLite"; "We recommend using Room instead of using the SQLite APIs directly".
  • Google — DataStore: "DataStore is ideal for small datasets and does not support partial updates or referential integrity"; "If you need to support large or complex datasets, partial updates, or referential integrity, consider using Room instead".
  • Google — Persistent work (WorkManager): "When you want to execute tasks that will continue to run even if the app leaves the visible state, we recommend using the Jetpack library WorkManager"; "WorkManager features a robust scheduling mechanism that lets tasks persist across app restarts and device reboots"; "Declaratively define the optimal conditions for your work to run using work constraints. For example, run only when the device is on an unmetered network, when the device is idle, or when it has sufficient battery"; "Scheduled work is stored in an internally managed SQLite database"; "WorkManager offers flexible retry policies, including a configurable exponential backoff policy". Backoff detail from Define your work requests: the default policy is "EXPONENTIAL with a delay of 30 seconds" and the backoff delay "can be no less than 10 seconds".
  • Google — Core app quality: testers should "introduce interruptions from other apps, such as receiving a notification or a phone call" and "apply transient changes to device attributes, such as network connectivity, battery function, GPS availability, and system load"; stability criterion "App does not crash or block the UI thread causing ANR (Android Not Responding) errors". Note: this page contains no requirement that an app function offline; it is cited only for the test condition and the stability criterion.
  • Firebase — Access data offline: "Cloud Firestore supports offline data persistence. This feature caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline"; "For multiple changes to the same document, it's last write wins"; "For Android and Apple platforms, offline persistence is enabled by default"; "If you get a document while the device is offline, Cloud Firestore returns data from the cache. When querying a collection, an empty result is returned if there are no cached documents. When fetching a specific document, an error is returned instead"; "If fromCache is true, the data came from the cache and might be stale or incomplete". Cited as one platform's published behaviour, not as a recommendation over any alternative.
  • Apple — Optimizing Your App for Today's Internet (WWDC 2018, session 714, transcript published by Apple): "You should build your app running Network Link Conditioner right from the start. Don't think you can add in performance at the end because it's too late"; "Always, always, always run and test your app using Network Link Conditioner"; "waitsForConnectivity will simply wait instead of failing the load when your task does not have connectivity"; "there is a race condition where the system might tell you that you have connectivity to a server but by the time you create and send your request, you've lost your chance and you're no longer connected to the server"; "This can be helpful to present the user with a different flow or an offline UI for better user experience."
  • Apple — App Store Review Guidelines: 2.1 App Completeness, "We will reject incomplete app bundles and binaries that crash or exhibit obvious technical problems"; 2.5.5, "Apps must be fully functional on IPv6-only networks"; 4.2.3(ii), "If your app needs to download additional resources in order to function on initial launch, disclose the size of the download and prompt users before doing so." Note: the Guidelines contain no clause requiring offline functionality; no such claim is made in this article.
  • Apple — URLSessionConfiguration.waitsForConnectivity: "A Boolean value that indicates whether the session should wait for connectivity to become available, or fail immediately"; "If the value of the property is false and connectivity is unavailable, the connection fails immediately with an error"; "This property is ignored by background sessions, which always wait for connectivity." Also urlSession(_:taskIsWaitingForConnectivity:): "The delegate can use this opportunity to update the user interface; for example, by presenting an offline mode or a cellular-only mode." Note: these developer.apple.com documentation pages render their text via JavaScript; the wording above was verified on 3 August 2026 against Apple's own JSON endpoints for the same pages under developer.apple.com/tutorials/data/documentation/.
  • Apple — URLSessionConfiguration.background(withIdentifier:): "In iOS, this configuration makes it possible for transfers to continue even when the app itself is suspended or terminated"; a relaunched app "can use the same identifier to create a new configuration object and session and to retrieve the status of transfers that were in progress at the time of termination"; "If the user terminates the app from the multitasking screen, the system cancels all of the session's background transfers." Discretionary transfers from Downloading files in the background: "For time-insensitive tasks, enable the isDiscretionary property, so the system can wait for optimal conditions to perform the transfer, such as when the device is plugged in or connected to Wi-Fi." Same JavaScript-rendering note as above applies.
  • Apple — SwiftData: "an app that fetches data from a remote web service might use SwiftData to implement a lightweight caching mechanism and provide limited offline functionality." And Human Interface Guidelines: Loading: "Show something as soon as possible. If you make people wait for loading to complete before displaying anything, they can interpret the lack of content as a problem with your app or game." Same JavaScript-rendering note as above applies.
  • SQLite — Appropriate Uses For SQLite: "SQLite strives to provide local data storage for individual applications and devices"; SQLite "thrives at the edge of the network, fending for itself while providing fast and reliable data services to applications that would otherwise have dodgy connectivity". And Most Widely Deployed and Used Database Engine: SQLite is found in "Every Android device", "Every iPhone and iOS device" and "Every Mac".
  • Singapore Statutes Online — Personal Data Protection Act 2012, section 24: "An organisation must protect personal data in its possession or under its control by making reasonable security arrangements to prevent — (a) unauthorised access, collection, use, disclosure, copying, modification or disposal, or similar risks; and (b) the loss of any storage medium or device on which personal data is stored." Section 25: an organisation "must cease to retain its documents containing personal data, or remove the means by which the personal data can be associated with particular individuals, as soon as it is reasonable to assume that — (a) the purpose for which that personal data was collected is no longer being served by retention of the personal data; and (b) retention is no longer necessary for legal or business purposes." Verified against the SSO view for the current version as at 5 December 2025 (as amended by Act 19 of 2025).
  • Namtech — Pricing: SGD 20,000 / 38,000 / 90,000 published starting points; "Maintenance & Support — from 15% of build cost per year".