Offline Mode Configuration

5 min read

This guide covers the technical architecture of WittyForm's offline mode, including the PWA service worker, IndexedDB storage, sync protocol, conflict resolution, and how sync status is surfaced on the device. Offline mode requires the Enterprise plan.

PWA service worker

When offline mode is enabled for a form, WittyForm registers a service worker scoped to the form's URL path (/form/[formId]/). The service worker uses a cache-first strategy for static assets and a network-first strategy for the form configuration endpoint.

On the first visit while online, the service worker pre-caches:

  • The form HTML shell and all referenced CSS bundles.
  • The JavaScript runtime required to render and validate the form.
  • The form configuration JSON (field definitions, conditional logic rules, theme data).
  • Any static assets referenced by the form (logo images, background images, custom fonts).

After the initial cache is populated, subsequent visits serve from cache immediately and update the cache in the background (stale-while-revalidate for the configuration endpoint). If the network is unavailable, the cached version is served without delay.

The service worker checks for configuration updates every 60 seconds while the form tab is active and online. If an update is detected, the new configuration is cached and applied on the next form load.

IndexedDB storage

Offline data is stored in a single IndexedDB database called WittyFormOfflineDBthat is shared across every form on the device. It holds several tables, including submissions (queued responses), forms (cached form configurations), syncQueue, pendingFiles, and syncLog. Each submission record looks like this:

{
  "id": 12,
  "formId": "form_abc123",
  "responses": {
    "field_name": "Jane Doe",
    "field_email": "[email protected]",
    "field_rating": 5
  },
  "timestamp": 1726410730000,
  "synced": false,
  "retryCount": 0,
  "idempotencyKey": "form_abc123-1726410730000-a1b2c3"
}

The idempotencyKey is generated when the submission is queued. It is what keeps the same response from being saved twice if a sync is retried, so there is no separate device identifier to manage.

Sync protocol

The sync manager runs a periodic poll every 30 seconds while online, and also runs as soon as connectivity is restored. Each pass works through the queue like this:

  1. The sync manager detects an online event, or the 30 second poll fires.
  2. All unsynced records in IndexedDB are read from the submissions table, ordered by timestamp (oldest first).
  3. Each submission is sent as a POST request to /api/forms/[formId]/responses with the headers X-Idempotency-Key (the record's idempotency key) and X-Submission-Source: offline.
  4. If the request succeeds, the record's synced flag is set to true and it is removed from the pending queue.
  5. If the request fails, retryCount is incremented and the submission is left in the queue for the next pass.
  6. After retryCount reaches the maximum of 3 attempts, the record is marked as permanently failed and the form UI prompts the user to check their connection and retry manually.

File uploads attached to an offline submission are uploaded whole through /api/files/upload when the submission syncs, then the stored URLs are written into the response.

Conflict resolution

Offline mode uses a last-write-wins strategy for conflict resolution. Since each offline submission is a unique response (not an edit to an existing response), true conflicts are rare. The main scenario where conflicts can occur is:

  • Duplicate detection: If the same submission is sent twice (e.g., due to a network timeout where the server received the data but the client did not receive the acknowledgment), the server uses the submission's idempotencyKey to deduplicate. The retried request returns the existing response instead of creating a new one.
  • Form version mismatch: If the form was updated while the device was offline, submissions made against the old form version are still accepted. The server maps fields by their stable IDs. New fields added since the cached version will be empty in the response. Deleted fields in the submission are preserved as archived data.

Storage limits

IndexedDB storage is controlled by the browser. The following table shows typical limits across major browsers:

BrowserStorage quotaNotes
Chrome / EdgeUp to 80% of disk spaceEvicted under storage pressure (LRU)
FirefoxUp to 50% of disk space (max 2 GB per origin)Prompts user if exceeded
Safari~1 GB per originData may be evicted after 7 days of inactivity
Safari (Add to Home Screen)~1 GB per originPersistent storage, not subject to 7-day eviction

For text-only submissions, each response typically uses 1 to 5 KB of storage. A form can accumulate thousands of offline responses before hitting storage limits. File uploads consume significantly more space: plan accordingly when using offline mode with file upload fields.

Offline-capable vs connectivity-required field types

Field typeWorks offlineNotes
Text, Email, Number, PhoneYesFull functionality including validation
Multiple choice, Dropdown, CheckboxYesOptions are cached with form config
Date, TimeYesBrowser native pickers work offline
Rating, ScaleYesFull functionality
Long text, StatementYesFull functionality
File uploadPartialFiles stored locally, uploaded on reconnect (up to 100 MB on Enterprise)
SignatureYesSignature canvas works offline, saved as PNG blob
Payment (Stripe)NoRequires active connection to payment processor
Address (autocomplete)PartialManual entry works offline only when Address Validation and Google location-type rules are not required
Distance / live Maps pricingNoRequires a live route and signed fare; incompatible Offline mode is publish-blocked
reCAPTCHA / TurnstileNoChallenge verification requires network

Monitoring sync status

Sync status lives on the device that captured the submissions, not on the server, so there is no remote endpoint to query it. The offline indicator in the form shows how many responses are still pending, and the offline manager UI lets the person on that device watch pending, synced, and failed counts and trigger a manual sync. Once a response syncs, it appears in your dashboard like any other response, so the dashboard is where you confirm everything has come through.

Testing offline mode

To verify that offline mode is working correctly before deploying to the field:

  1. Enable offline mode for the form and publish it.
  2. Open the form in Chrome and wait for the service worker to install (checkchrome://serviceworker-internals or the Application tab in DevTools).
  3. In Chrome DevTools, go to the Network tab and select Offline from the throttling dropdown.
  4. Reload the page: the form should load from cache with the offline indicator visible.
  5. Fill out and submit the form. The thank-you page should confirm the response was saved locally.
  6. Disable the offline throttle. The submission should sync automatically within a few seconds.
  7. Verify the response appears in your dashboard with the "Offline" tag and the correct original submission timestamp.

Ready to Build Forms That Actually Convert?

Get lifetime access for just $37. No subscriptions or recurring fees. Create beautiful forms and own the tool forever.

14-day money-back· Instant access
Offline Mode Configuration