RFID scan vs stock count: how tag reads become a number you can trust
A handheld sweep tells you which tags answered. It does not tell you what is on the shelf, and the gap between those two is where wrong reorders come from.
RFID scan vs stock count: what is the difference?#
An RFID scan is the set of tag IDs one sweep happened to see, while a stock count is that set reconciled against the stock record with every difference explained. The scan tells you what replied in the last few minutes. But the count tells you how many of each product the store holds. So four steps sit between them: drop repeats, decode each ID, compare with the record and label every gap. Without them, a fast scan only moves the error faster. For example, a University of Arkansas study from August 2009 found that "both systems lost inventory accuracy over the 13-week period". And one of those two systems was the fast one.
Deduplicate
Keep each EPC once, whatever its seen count.
Decode
Turn each EPC into a GTIN (Global Trade Item Number) and a serial.
Compare
Count the EPCs per GTIN and subtract the record's quantity for that GTIN.
Label
Mark each gap as unread, misplaced, unexpected or truly missing.
What is a faster RFID count actually worth?#
In the University of Arkansas Bloomingdale's study published in August 2009, counting 10,000 items took two hours with RFID against 53 hours with barcodes. Also, that 2009 release gives 4,767 counted items per hour with the faster system and 209 items per hour using a barcode system. In short, a count stops being a project and becomes a routine.
2 hours
RFID
53 hours
Barcode
RFID counted 10,000 items in two hours; barcodes took 53.
| Option | hours to count 10,000 items |
|---|---|
| RFID | 2 hours |
| Barcode | 53 hours |
Source: University of Arkansas RFID Research Center, August 2009
Our multi-store stock scanning case study shows the same shift. There, a stock audit that took two to three staff a full weekend now takes 10 minutes. However, the hours saved only pay once the sweep is reconciled. Otherwise a fast count sends the wrong stock to the wrong store, sooner.
What does an RFID reader actually record during a scan?#
An RFID handheld records the tag IDs it singulated during a sweep, and the Gen2 session it runs decides whether a tag already seen answers again or stays quiet. In Zebra's inventory tutorial for its SDK for Android 4.0.0.9, the app calls getReadTags(100). Then it gets back an array of reads. Each read carries an ID, and none carries a quantity per product.
But the air protocol decides the repeats. GS1 ratified Release 3.0.1 of its EPC Gen2 standard in February 2026. There, a tag's "inventoried flags shall have the set and persistence times shown in Table 6-21". In that February 2026 table, session S0 keeps it quiet only while it stays powered. In that table, S1 holds for 500 ms to 5 seconds. And sessions S2 and S3 hold for more than 2 seconds after power is lost. So the same tag can answer once or many times in one sweep. It depends on the Gen2 session the handheld app picks with setSession. As a result, the raw stream counts reads, not items.
| Gen2 session | How long a tag stays quiet |
|---|---|
| S0 | Only while the tag stays powered |
| S1 | 500 ms to 5 seconds |
| S2 and S3 | More than 2 seconds after power is lost |
Why can one scan over-count and under-count at the same time?#
In an illustrative 10,000-item store, a sweep that reads 98% of tags reports 200 items missing, even if stray reads from the stockroom add others that are not there. When reads are missed, items look missing, while re-reads and stray reads from another zone make others look present. So a raw total can be wrong in both directions and still land near the record.
Field read rates can also sit far below a demo. For example, CEPR published a discussion paper on a trial in Sri Lankan shops. Its authors report that "on average we were able to read only about one-quarter of the products tagged".
Take the illustrative case step by step. Say the record holds 10,000 tagged items and a sweep sees 98% of them, both numbers chosen as an example. Then the sweep returns an illustrative 9,800 unique EPCs, so 200 items look missing before anything has left the store. At an illustrative 95% read rate, the same store shows 500 false gaps.
Show data table
| Stage | Items wrongly flagged missing |
|---|---|
| 99% | 100 items |
| 98% | 200 items |
| 95% | 500 items |
| 90% | 1,000 items |
False gaps grow from 100 at a 99% read rate to 1,000 at 90%.
Items that look missing from unread tags alone
Set the items on your stock record and your sweep's read rate; the defaults are the illustrative 10,000 items at 98%.
Items that look missing
200
- Unique EPCs the sweep returns
- 9,800
Arithmetic: items x (1 - read rate). Modelled, not measured.
What does reconciliation do between the scan and the stock record?#
Reconciliation deduplicates the EPCs, decodes each one to a product, compares the per-product totals with the stock record and labels every difference before anything changes. In an RFID cycle count reconciliation, each step has one job:
- Deduplicate. Keep each EPC once, whatever its seen count. Zebra's developer guide notes one setting for this. Turning off antenna IDs can give "a single unique tag even though they were multiple entries of the same tag".
- Decode. Turn each EPC into a GTIN (Global Trade Item Number) and a serial. GS1's Tag Data Standard, Release 2.3 of October 2025, sets the SGTIN layout.
- Compare. Count the EPCs per GTIN and subtract the record's quantity for that GTIN.
- Label. Mark each gap as unread, misplaced, unexpected or truly missing.
So only an explained difference should reach the stock record. Until then, an unexplained one waits for a second sweep or a person in the right aisle. Everything the product builds around the reads is a separate job.
What did field studies measure about RFID and stock accuracy?#
Ten retailers in a 2018 ECR Retail Loss study typically moved from 65% to 75% inventory accuracy up to 93% to 99%, figures self-reported by the companies. In its guide to that 2018 report, ECR Retail Loss says companies "improved from 65%-75% to 93%-99%".
Show data table
| Dimension | Before RFID | After RFID |
|---|---|---|
| Low end of the reported range | 65% | 93% |
| High end of the reported range | 75% | 99% |
Both ends of the reported range moved into the 90s.
But a controlled design gives a smaller number. Hardgrave, Aloysius and Goyal published a field study in Production and Operations Management in March 2013. Across 13 stores, they found a "significant decrease in IRI of approximately 26%". In particular, IRI means inventory record inaccuracy. In their 62-store experiment from that 2013 paper, the effect by category ranged from no significant gain up to 81%.
Show data table
| Item | Value |
|---|---|
| 13-store field experiment, one category | 26 |
| 62-store experiment, best category | 81 |
A controlled design measured 26% across 13 stores, and 81% only in the best category.
In short, the gains are real, but each study reports a better record, not a perfect count.
Why did accuracy still fall in the store that had RFID?#
Over 13 weeks in a 2009 University of Arkansas study, accuracy fell 3.13% in the RFID store and 4.24% in the control store, so faster reads alone kept nothing accurate. Because the scan data never updated the store's own system during the trial, the record still drifted.
Show data table
| Item | Value |
|---|---|
| RFID-enabled test store, reads not written to the record | 3.13 |
| control store | 4.24 |
The RFID store lost accuracy too, only less than the control store.
Then the researchers fed the scan data into a simulated copy of the system as the master record. In that 2009 simulation, the University of Arkansas found overall accuracy improved by more than 27 percent. Therefore the gain came from writing counts back, not from reading faster.
Which official pages should a reconciliation be built from?#
Build from the Zebra RFID SDK for Android tutorials for reading tags and the GS1 Tag Data Standard for decoding each EPC into a product identifier. Open them in this order:
- 1
Zebra's inventory tutorial
Inventory tutorial: Inventory.perform() to start, and getReadTags inside eventReadNotify to collect.
- 2
The Zebra developer guide
Developer guide: TagStorageSettings, the fields that decide unique reporting.
- 3
Zebra's singulation tutorial
Singulation tutorial: setSession, the Gen2 session for the sweep.
- 4
GS1's Tag Data Standard
Tag Data Standard: the SGTIN-96 layout that turns an EPC into a GTIN.
- 5
GS1's RFIDcoder API
RFIDcoder API: /api/tag/epc/epchex, to check a decode.
The five pages, in order: inventory tutorial, developer guide, singulation tutorial, Tag Data Standard and RFIDcoder API.
Still, that SDK is only the example here. If your handhelds come from another vendor, its SDK has its own calls, and the four steps stay the same.
What is the smallest code that reconciles a scan?#
The smallest working reconciliation collects tag IDs in eventReadNotify into a set, decodes each to a GTIN and subtracts the per-product totals from the stock record. The code assumes reader is a connected RFIDReader, set up as in the inventory tutorial. It also assumes the standard Java math and collection imports.
// Step 1: start the sweep (reader set up as in Zebra's inventory tutorial)
reader.Actions.Inventory.perform();
// Step 2: keep each tag ID once; repeat reads collapse in the set
Set<String> seen = new HashSet<>();
public void eventReadNotify(RfidReadEvents e) {
TagData[] myTags = reader.Actions.getReadTags(100);
if (myTags != null) for (TagData t : myTags) seen.add(t.getTagID());
}
// Step 3: SGTIN-96 EPC (hex) to GTIN-14, per the GS1 Tag Data Standard
static String gtinOf(String epcHex) {
BigInteger v = new BigInteger(epcHex, 16);
if (v.shiftRight(88).intValue() != 0x30) return null; // not SGTIN-96
int p = v.shiftRight(82).intValue() & 7; // partition value
int[] cpBits = {40, 37, 34, 30, 27, 24, 20};
int cpDigits = 12 - p, irBits = 44 - cpBits[p];
long cp = v.shiftRight(38 + irBits).longValue() & ((1L << cpBits[p]) - 1);
long ir = v.shiftRight(38).longValue() & ((1L << irBits) - 1);
String c = String.format("%0" + cpDigits + "d", cp);
String i = String.format("%0" + (13 - cpDigits) + "d", ir);
String body = i.charAt(0) + c + i.substring(1); // indicator digit first
int sum = 0;
for (int k = 0; k < 13; k++) sum += (body.charAt(k) - '0') * (k % 2 == 0 ? 3 : 1);
return body + (10 - sum % 10) % 10; // GS1 check digit
}
// Step 4: per-GTIN difference, counted minus record; zero means it matches
static Map<String, Integer> diff(Set<String> epcs, Map<String, Integer> record) {
Map<String, Integer> counted = new HashMap<>();
for (String epc : epcs) {
String g = gtinOf(epc);
if (g != null) counted.merge(g, 1, Integer::sum);
}
Map<String, Integer> out = new TreeMap<>();
Set<String> all = new HashSet<>(record.keySet());
all.addAll(counted.keySet());
for (String g : all) {
int d = counted.getOrDefault(g, 0) - record.getOrDefault(g, 0);
if (d != 0) out.put(g, d);
}
return out;
} GS1's coder API documentation uses the example EPC 3034257BF7194E4000000190, and for it gtinOf returns 80614141123458, the GTIN the API prints. After that, each entry diff returns is a gap to label, never a number to write straight into the record.
When is it safe to let a scan drive a reorder?#
A scan may drive a reorder only after reconciliation has labelled the shortfall as truly missing, never straight from the raw total of one sweep. In the illustrative store at a 98% read rate, the raw total shows 200 items missing. So an automatic reorder would buy stock already on the shelf. Instead, reorder on a gap that survived reconciliation and a repeat sweep, at a preset quantity.
The University of Arkansas published a JCPenney pilot in April 2010. It credited part of the gain to "weekly use of RFID replenishment reports to make in-store decisions". In practice, a person or a rule acts on a report, not on a beep. The build in our case study works that way too, because scans meet the stock record before any reorder.
What did a multi-store RFID build learn about reconciling scans?#
On the multi-store build in the case study, weekly scans compared with the stock record flagged missing or misplaced stock within five working days. The product belongs to a software vendor that sells RFID inventory tracking to small multi-store retailers. It runs on a PHP service layer, a job queue and a native Android app.
But every handheld vendor behaved differently, with its own re-reads and read range. As a result, the reconciliation had to absorb vendor behaviour, and hardware testing took far longer than planned. Next time, a device lab with every supported handheld belongs in week one. Because stock accuracy was not measured as a number on this build, none is claimed. The full account of the multi-store build covers the rest.
| What the build met | What belongs in the next one |
|---|---|
| Every handheld vendor behaved differently, with its own re-reads and read range | A device lab with every supported handheld in week one |
| Stock accuracy was not measured as a number | None is claimed |
When is an RFID count the wrong tool?#
An RFID count is the wrong tool when items are few, cheap or hard to tag, because a barcode cycle count of the few lines that matter gives the same answer for less. Three cases stand out.
Where should you go next?#
For the device side, read the Zebra printer troubleshooting guide, and for the stock side, read about custom logistics and supply chain software. If you are building the scanning app, the mobile app development page covers that side. For the stock service that reconciles and reorders, see custom software development. Otherwise, the Zebra and GS1 pages above are enough to build a first version on your own.