AWRA OpsHub Search

Counting Offline: Why the Count Was the Hard One

A branch pharmacy in a mall basement, stocktake night, two staff and a phone each. The signal in that basement comes and goes. Our app holds a sale, a count line, a check-in, a check-out, a transfer, an asset movement and an approval through a dead connection and pushes them when the bars come back. The count was the hard one, and the reason it was hard is the useful part.

Pharmacy & Pharmaceutical Distribution Washingtone Aura 12 min read

Every offline demo is run in a room with good wifi. Somebody switches the phone to aeroplane mode, taps three things, switches it back, and everyone watches a little counter go from three to zero. It is a genuine capability and it is genuinely worth having. It also tells you almost nothing about the operation you are actually worried about, which is the one where two people spend four hours on a basement floor with a clipboard and a phone, counting every box in the branch.

So here is the specific answer, in one sentence, before the reasoning. Our mobile app queues the work of the floor offline — sales at the till, stock count lines, inventory check-ins and check-outs, stock transfers, asset movements including verification, and approvals — and a stock count is one of them. A count session is opened with a connection; every line counted inside it is held on the phone through a dead spot and pushed when the signal returns. Receiving against a purchase order is being brought offline next.

The rest of this post is the part that is more useful than the sentence: what the offline queue actually does, why counting is a different shape of problem from the other things that queue, how that difference was answered, and what a pharmacy should still plan for on the night.

What the phone will hold for you

Operation Queued as What it means on the floor
Sale at the till pos-sale Ring up a sale and hand over a receipt with no signal
Count line count-line Record a counted quantity against an open count session
Inventory check-in and check-out checkin, checkout Receive stock into, or issue it out of, a location offline
Stock transfer stock-transfer Move stock between warehouses or locations, and approve, dispatch or receive a transfer
Asset movement asset-movement Check out, check in, transfer, relocate, verify, mark damaged, mark lost or retire an asset
Approvals decision types Approve a count line or a variance, an adjustment, a transfer, a leave request or an invoice

The asset row is broader than it looks — eight distinct asset actions ride on one queued operation type, including verification, which is the one a pharmacy doing an equipment walk-round would use most.

The queue underneath all of these is properly built, and it is worth describing because it is the part that determines whether offline capture is trustworthy or merely present.

  • Every operation carries an idempotency key. If the phone pushes and the response is lost, the retry does not create a second transfer.
  • Order is preserved on a transient failure. If a push fails for a reason that might succeed later — the network drops mid-sync — the operation stays pending and the sync stops there rather than skipping ahead and applying later work first.
  • Permanent failures are separated from transient ones. An operation the server has definitively rejected is marked failed and set aside, with the error message kept against it.
  • You are told, app-wide. An orange strip across the top of every screen reads "Offline mode", and once you are back online it keeps showing while anything is queued or failed, with the counts.
  • You can inspect the queue. There is a screen listing every queued and failed operation, and a detail screen for any one of them showing what it was and why it failed.
  • The subscription is checked before anything is pushed. On reconnect the app verifies the plan with the server first; if it has lapsed, queued work stays put rather than being pushed into a closed account.

One boundary before we go further

All of this is the mobile app. The browser has no offline mode. If your branch staff work on a desktop in a back office, a dropped connection means a dropped connection, and nothing is queued anywhere. Offline capture is a phone capability in this product, full stop.

Counting on the phone, with or without the bars

There are four inventory count screens in the mobile app: the list of count sessions, the setup form, the counting form itself and the session detail. A pharmacy technician can run a full count session from a phone — see their assignment, enter counted quantities, submit, watch variances resolve.

When the signal drops, the counting form keeps working. A line entered in a dead spot is saved on the phone, shown on the session as waiting to sync, and pushed with its own idempotency key when the connection returns. The session itself is opened with a connection, and the phone keeps a copy of it, so a counter who walks into the basement with the session loaded can count the whole room.

The other operations that queue are deltas. A count is not a delta. It is an assertion about absolute state at a specific moment, and a stale absolute is worse than none.

Why a count is a different shape of problem

Counting was not the last item on a list. It came later than the movements because it needed answers the movements did not, and a buyer evaluating any offline count is better served by knowing what those answers are.

Look at what the movement operations have in common. Every one is a change relative to whatever is there. Move five boxes from A to B. Issue three units. This asset is now with that person. Those instructions are still correct six hours later. They can be applied in order against whatever state the server has reached in the meantime, and they land where they should. That property is what makes them safe to hold in a pocket.

A count says something categorically different: there are forty-two of these here, right now. That statement is only true at the instant it is made. Push it six hours later, against a system where four have been dispensed and a delivery of thirty has arrived, and you are not applying a delta — you are overwriting the truth with a photograph of the past, and generating a variance that describes nothing that happened.

Two counters, one dispensary, no signal

19:10 — Counter A records 42 boxes of paracetamol in the dispensary held on device A
19:40 — Counter B, working the other side, records 38 of the same item in the same location held on device B
20:15 — a pharmacist dispenses two boxes from that shelf server state changes
21:00 — both phones reconnect and push two absolute claims arrive
What the system should conclude genuinely unclear — and that is the point

With deltas there is no ambiguity: they add up. With two conflicting absolutes and a live movement in between, there is no correct automatic answer. Any product that queues counts offline has picked a rule for this — last write wins, or first, or highest — and you should ask which, because you will be living with it. Ours: each line is one item in one location, measured against the expected figure fixed when the session opened; while a line is unreviewed the later figure replaces the earlier one, and every figure stays on the session’s trail with who counted it; once a line has been approved, a late figure is refused and shows as failed in the queue rather than quietly moving an approved variance.

The lock, and why the phone does not need to hold it

There is a second, harder question, and it is specific to how counting is built here rather than a general observation about distributed systems.

A count session in this product can freeze the stock it is counting. It is an option on the session, with a start and an end, and while a session holding that freeze is open, counting, submitted or awaiting approval, the items in it are locked. That is not advisory. Any attempt to move locked stock through the inventory service raises an error and refuses: this item is locked by an active inventory count session.

That lock is a promise the server makes to every other user at once — to the till, to the receiving bay, to the other branch requesting a transfer. A phone with no connection cannot hold that promise, so it is not asked to. The session, and any freeze it carries, is opened with a connection and held by the server for as long as the session is live. Counting moves no stock, so a dark phone entering lines inside a frozen session breaks nothing — the till and the receiving bay are still refused by the server, and the counted figures land in the session when the phone reconnects.

And a blind count pulls the other way entirely

Sessions can be run blind, which means the counter is not shown the expected quantity — the whole point being that they count what is there rather than confirming what they were told. The masking is enforced on the server, before anything reaches the phone: a blind session arrives with the expected figures already blanked, so the copy the phone keeps for offline work holds nothing for a counter to find. Offline counting and blind counting are in genuine tension, and any product offering both should be asked how it resolves that.

What the device carries

It is worth seeing what sits on the phone, because it tells you how much of stocktake night survives a dead spot.

The app caches a substantial reference set on the device: the item list, item form data, locations, warehouses, units of measure, adjustment reasons, assets, custodians, asset policy, recent asset movements, recent adjustments, and inventory levels. It also caches custom field definitions for nine modules — and one of the nine is inventory count sessions.

So the phone holds the items, the locations and the sessions a counter needs with no signal, and the queue that carries the results is the same one the movements use, with idempotency and ordering. The banner that tells the counter what state they are in is on every screen, and a line waiting to sync is marked as such on the session itself.

What to actually do on stocktake night

This is the practical section, and it assumes you are running the count in a place where signal is unreliable — a basement, a back store, a rural branch on a mobile hotspot.

  1. Test the signal where the stock is, not where the counter sits

    Walk the actual route with the app open a week before. The strip at the top of the screen turns orange the moment the connection drops, so you get a free survey by watching it. Note the dead spots.

  2. Open the session and load it before anyone goes underground

    The session is created with a connection, and each counter should open it on their phone where the signal is good. From then on the lines they count in the dead spots are held on the phone and pushed when they come back up. Agreeing that in advance turns an outage into a procedure. Discovering it mid-count turns it into an argument.

  3. Bring a frozen session up to the signal to finish it

    If the session holds a stock freeze, the freeze lasts until the session is submitted and settled, and the till and the receiving bay are refused for as long as it takes. Counting can happen in the dark; closing the session should happen where the phones can reach the server, so the freeze is not held a minute longer than the count.

  4. Use the rest of the queue freely

    Sales, transfers, check-ins, check-outs, asset movements and approvals really do survive a dead connection. If part of stocktake night is moving stock between locations or verifying equipment, that part is safe offline and you should lean on it.

  5. Check the queue is empty before anyone goes home

    The strip shows pending and failed counts, and the queue screen shows each one. An operation sitting failed is a movement that did not happen, and the morning after a stocktake is the worst possible time to discover one.

Survives a dead connection

  • Counting lines in an open count session, and approving or recounting them
  • Sales at the till, with a receipt
  • Stock transfers, inventory check-ins and check-outs
  • All eight asset movement actions, including verification
  • Approvals: adjustments, transfers, leave and invoices
  • Seeing that you are offline, what is waiting to go, and retrying anything that failed

Done with a connection

  • Opening a count session, and taking or releasing a stock freeze
  • Revealing a masked quantity in a blind count
  • Receiving against a purchase order — being brought offline next
  • Anything in a desktop browser

The question worth asking every vendor

Offline is the single most over-claimed capability in this category, because the demo is easy and the boundary is invisible. These questions find the boundary in about two minutes, and they work on us as well as on anyone else.

Ask these, and ask for the screen

  • Name every operation with stock and asset movement captured offline. Not "inventory" — the specific list.
  • Is offline mobile only, or does the browser do it too?
  • Show me a full stock count started, entered and submitted in aeroplane mode.
  • Two counters count the same shelf offline and get different numbers. What does the system do when both reconnect?
  • If stock moved while I was offline, does my queued work still apply correctly, or does it overwrite?
  • Show me the screen where I can see what failed to sync, and why.
  • What happens to a queued operation if my subscription lapses before it pushes?

The fourth question is the one that separates products that thought about offline from products that added a queue. There is no free answer to it. A vendor who answers immediately and specifically has been through it; a vendor who says "it syncs automatically" has not.

Offline capture: what ships today, and what we can add

Built and verified in the mobile client

  • Offline capture of the floor’s work. Sales at the till, stock count lines, inventory check-in and check-out, stock transfers, asset movements — check-out, check-in, transfer, relocate, verify, mark damaged, mark lost and retire — and approvals.
  • Offline inventory counting. Lines counted inside a session opened with a connection are held on the phone, marked as waiting, and pushed on reconnect; a late figure on an approved line is refused rather than applied.
  • Blind counts that stay blind offline, because the server blanks the expected figures before the session reaches the phone.
  • Idempotency on every queued operation, so a lost response does not become a duplicate record.
  • Ordered replay with transient-failure handling. A network failure leaves the operation pending and stops the sync there; a definitive server rejection marks it failed and keeps the reason.
  • An app-wide status strip showing offline state plus pending and failed counts on every screen.
  • An inspectable queue — a list screen and a per-operation detail screen with the error message.
  • A subscription gate on reconnect, verifying the plan with the server before any queued write is pushed.
  • A cached reference set on the device: items, locations, warehouses, units, adjustment reasons, assets, custodians, asset movements, adjustments, inventory levels and custom field definitions for nine modules.
  • Count sessions on mobile: list, setup, counting form and session detail, with the session cached for offline counting.
  • Offline approvals, including count-line approval, recount requests and applying a count’s adjustments.
  • Offline sales at the till, with a receipt shown while the sale waits to sync.

More we can add — each one verified against the code

  • Receiving against a purchase order offline, which is being brought offline next.
  • Offline capture in the browser. Offline capture is a mobile-app capability today.
  • A configurable conflict rule for two counters on one line. Today the later unreviewed figure replaces the earlier one, both stay on the session’s trail, and an approved line refuses a late figure.
  • Opening a count session and taking a stock freeze offline. The freeze is a promise the server makes to every other till and bay, so it is taken with a connection; the counting inside the session runs offline.

Where the line falls

  • If your offline need is moving, issuing, selling and counting stock in places with poor signal, this is well covered today and the queue underneath it is careful work.
  • If your offline need is a full stocktake in a basement, open the session where the signal is good, count in the dark, and close it where the phones can reach the server. That is better to have in writing now than at 21:00 on the night.
  • Offline capability lives in the app rather than the browser, and that should shape which device your staff are given.

A different conflict rule for your counters — first figure wins, a second count required when two disagree — is a design decision we would rather agree with you than guess, and it sits on a queue that already carries the counts.

First verified against the Laravel API and the React Native client on 7 August 2026, and updated on 14 October 2026 after offline counting, sales at the till and approvals joined the queue. The list was established by finding every call site of the queueing function and every case in the sync handler, and confirming the two lists match.

More we can add to your workspace

Anything above that you need, we can build for you

Everything listed above as something we can add describes what ships in the standard product today — it is a starting point, not a limit on what AWRA OpsHub can do for your organisation. Kenya's eTIMS integration and its maintained payroll engine are both in the product because clients needed them and commissioned them; neither appeared by itself, and the same door is open for whatever you just read about. One qualification so this is worth what it claims: a small number of things on this blog we deliberately leave to a specialist rather than build — a statutory ledger we will not sign our name to, a rule that would decide a tax question for you, a clinical or member-funds record that belongs in a regulated system — and where that is true the post says so in those words. Everything else is a scope, a timeline and a price.

The operational work, which is what most commissions actually are

An extra approval stage in a chain that does not match the standard one, a custom field set on employees or assets that only your sector needs, an expiry that has to block an order rather than send an email, a report your board asks for in a shape nothing produces, or a scanner or weighbridge feeding the goods-in door. These are the commissions we are asked for most often and the smallest ones we quote — and unlike a revenue-authority pipeline, none of them waits on a regulator.

The module-shaped additions, which are the ones readers ask for most often

A price list with real discount authority, a customer-facing quotation that expires, a bill of materials or recipe costing, a staff advance that is issued, acquitted and chased, a member or unit ledger, a matching rule that holds a payment. Each of these is a build rather than a setting, and each has been quoted before — a bigger piece of work than a custom field, with a written spec and a date instead of a roadmap slide.

The report, document or pack nothing currently produces

The board pack in the shape your board actually asks for, a donor or funder layout, an invoice or receipt template carrying what your regulator or your customer expects, a dataset the report builder cannot reach yet. Usually the fastest thing on this list to deliver, because the data is already in the system.

Systems, rails and hardware you already run

The accounting package, CRM, online store, core banking or custom database you intend to keep — connected through our API so a fact is entered once and appears everywhere it is needed. Plus the physical edge: a scanner, a scale, a weighbridge or a till peripheral feeding the door it belongs to.

How it works: you describe the requirement, we return a written scope, timeline and cost, and once agreed it is built into your environment and maintained as part of the product. Nothing here waits on a regulator or a published specification, which is why operational builds are the ones we quote fastest. Tell us the requirement that would otherwise rule us out — that is a better first conversation than a demo.

Tell us what your operation needs

An offline capability that is honestly described is worth more than a broad one that is vaguely described, because you can plan around the first and you cannot plan around the second. Sales, counts, movements and approvals, mobile only, with a real queue underneath — that is the shape of it, and now stocktake night can be planned against a fact.

Tell us where the signal dies

If you run branches where connectivity is genuinely unreliable, describe the worst one and what has to happen there. We will tell you which parts work offline today, which parts need paper, and whether the gap is worth building out for your operation.

Talk to us about a multi-branch deployment

Share this article

LinkedIn X WhatsApp

Help Center

Need a quick answer while you read?

Run inventory, procurement, assets, sales, and field work with approved AWRA guidance for setup, migration, integrations, security, pricing, and support.

Search all approved AWRA public help articles.

Open Help Center