Reliable offline job processing for React Native

A local queue for uploads, form submissions, background work and retries when mobile connectivity is unreliable. Jobs are saved to disk before your code continues, run when the network allows, and survive app kills.

Why QueueKit

Saved before it returns

Storage is MMKV, which is synchronous. enqueue() writes the job to disk before it returns, so a crash a millisecond later cannot lose it.

Network aware

Jobs wait while offline and run the moment you reconnect. A connection that drops mid-request does not burn a retry.

Smart retries

Exponential backoff with jitter, per-job attempt limits, Retry-After support and an error type that gives up immediately.

Typed and ergonomic

queue.define() turns a handler into a typed function. Or use decorators on class methods. Payload types are inferred.

Control knobs

Priority, concurrency, per-type limits, rate limits, delays, expiry, de-duplication and cancellation through AbortSignal.

Background ready

Flush on foreground, drain inside OS background tasks, and hand big uploads to native uploaders with ctx.detach().

Observable

React hooks for live UI, plus queue.observe() for Firebase, App Insights, Sentry or your own logging, with durations.

Small and modular

Zero runtime dependencies in the core. Storage and network are plain interfaces. React hooks live in a separate entry point.

Tested

100% statement and branch coverage is enforced on every commit and push.

A 60-second example

That is the whole integration. Offline, the button still "works": the job is stored and sent when a connection returns, even if the app was closed in between.

How it works

Every job is a small JSON object stored under its own key. A scheduler picks the jobs that are allowed to run, runs them through your handlers, and updates the stored state after each step. Completed jobs are deleted. The diagram shows every state and transition.

enqueue() saved to storage pending waiting its turn active handler running completed job deleted failed kept for inspection expired job deleted due + online + free slot handler threw: retry after backoff (offline mid-run: requeued, no attempt used) returned / resolved out of attempts or NonRetryableError queue.retry(id) ttlMs elapsed

What is guaranteed and what is not

GuaranteeDetails
Durable enqueue The job is in storage before enqueue() returns.
At-least-once execution If the app dies while a job runs, it runs again next launch. Make handlers idempotent. QueueKit hands you job.id as a ready-made idempotency key.
No lost failures Jobs that run out of attempts stay as failed with the last error until you retry or remove them.
Priority, then FIFO Higher priority first, then earliest due time, then oldest. Strict ordering across retries needs an orderKey.
JavaScript required The queue runs in your JS runtime. While the app is suspended it pauses, unless you use background tasks or native uploaders. See Background and native tasks.

Where to go next

Getting started

Install, set up MMKV and NetInfo, create your first queue and job.

Jobs and handlers

Every way to define a job, every handler form, and all enqueue options.

Reliability and scheduling

Retries, backoff calculator, timeouts, network rules, limits, expiry.

React hooks

Live status, progress bars, retry buttons and sync banners.

Background and native tasks

Foreground flush, background drain and OS-level uploads.

Cookbook

Over thirty ready-to-copy recipes for real app flows, APIs and media.