Skip to content

Offline Queue

Warehouse WiFi is rarely 100% reliable. ScanPick’s mobile app is designed to tolerate network interruptions without losing data or requiring workers to re-scan.

Mobile Device ScanPick API
┌──────────────────┐ ┌──────────────────┐
│ Camera → Scan │ │ /api/picking/ │
│ ↓ │ online │ submit-scan │
│ Validate locally │ ───────────→ │ Deduplicate │
│ ↓ │ offline │ by idempotency │
│ Queue (MMKV) │ ───[wait]──→ │ Update pick │
│ ↓ │ │ task │
│ Drain on │ └──────────────────┘
│ reconnect │
└──────────────────┘

When a barcode is scanned, the app validates it against the expected barcode on the device, before any network call. If the barcode doesn’t match, the scan is rejected immediately — it never enters the queue.

This works even when the device is completely offline.

When the network is available, validated scans are sent to the API via POST /api/picking/submit-scan:

{
"pickTaskId": "picktask-001",
"barcode": "5901234567890",
"scannedAt": "2026-06-19T10:30:00Z",
"idempotencyKey": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"workerId": "worker-003"
}

If the API is unreachable, the scan is stored in MMKV (local key-value storage on the device). The IdempotencyKey preserves the original scan UUID from step 2.

When connectivity returns, the queue drains automatically:

  1. Pending scans are sent to the API in order
  2. Each scan carries its original idempotencyKey
  3. The server deduplicates — if a scan was already processed (e.g., it was submitted before going offline), the server returns success without double-counting
  4. Successful scans are removed from the queue
  5. Failed scans (network error) are retried with 1-second backoff
  6. Scans that exhaust the retry budget are flagged as failed

The server maintains a set of processed idempotency keys. If a scan arrives with a key that was already processed, the server returns a success response without modifying state. This makes replaying the queue safe.

PropertyGuarantee
No lost scansScans always persist to MMKV before submission
No double-countingIdempotency keys prevent duplicate processing
Correct barcodeValidation happens on-device before queuing
No data lossQueue persists across app restarts
Automatic recoveryQueue drains when network returns
StateDescription
PendingScan in queue, not yet submitted
InFlightScan is being submitted to the API
CompletedScan submitted successfully, removed from queue
FailedRetry budget exhausted, flagged for review

Queue behavior is configured on the mobile client:

  • Retry budget: 3 attempts per scan (default)
  • Backoff: 1 second between retries
  • Drain interval: triggered on network status change + periodic timer