"Biometric attendance: why we ship our own SDK wrapper"
RFID, face and fingerprint trade-offs, offline-first edge sync, and what tier-2 internet does to your assumptions.
A school in Karimnagar takes morning attendance for 1,400 students between 7:55 and 8:10 am. Fifteen minutes. Three gates. The internet at gate two drops out for 90 seconds at 8:02. The principal expects the report on her phone at 8:11. Every architectural decision in our biometric attendance stack is shaped by that 90-second window, repeated some variant of every day, across hundreds of campuses. Off-the-shelf vendor SDKs assume constant connectivity. Our wrapper assumes the opposite.
The three modalities and what they're actually for
We support RFID, face recognition and fingerprint. They are not interchangeable.
- RFID — fastest by an order of magnitude. A student walks past a reader at 0.3 metres with a card in their bag and the read is done. Throughput at a gate is 30+ students per minute. The trade-off is the card itself: lost cards, swapped cards, and the proxy-attendance problem (a friend swipes for an absent student).
- Face recognition — slower per student (1.5–2 seconds for capture, match, confirm) but tamper-resistant. We use it primarily for high-stakes points: exam halls, examination duty registers, hostel exit gates. The matcher runs on a Jetson Nano at the gate, not in the cloud. Network round-trips at the gate are unacceptable.
- Fingerprint — slow (3–5 seconds), unhygienic in a post-2020 world, but deeply accurate. We mostly see it in staff attendance and lab access where the user is willing to wait.
Most schools end up running RFID at main gates with face-rec at a single high-throughput verification point. The mix is configurable per campus.
The vendor SDK problem
The biometric reader hardware in the Indian market is a fragmented mess. Mantra, Morpho, Realtime, eSSL, Suprema, ZKTeco. Each ships an SDK. Each SDK assumes:
- A Windows desktop with a wired connection to the device.
- Synchronous API calls that block until the device responds.
- A vendor cloud that the device pushes events to.
- No standard event schema across vendors.
We wrap all of this. Our wrapper exposes a single event interface — attendance_marked
with a normalised schema (student_id, modality, gate_id, timestamp, raw_vendor_payload) —
and handles vendor-specific quirks internally. Adding a new vendor takes about two days of
adapter work. Our gates can mix vendor brands behind the same wrapper, which matters for
schools that bought hardware before they bought us.
Offline-first is the only workable design
The wrapper runs on an edge box at each gate — usually an Intel NUC or a Raspberry Pi 4 in a metal enclosure, depending on the modality. The edge box is the source of truth during the attendance window. It:
- Maintains a local copy of the student roster, synced down at 6:00 am.
- Buffers attendance events to a local SQLite WAL.
- Pushes events to the cloud over a long-lived gRPC stream when connectivity is up.
- On disconnect, keeps marking attendance to the local store, emits a UI signal that the gate is operating in "offline buffered" mode, and resyncs on reconnect.
The buffer can hold 48 hours of events safely. We've seen it actually used for 11 hours during a regional fibre cut in coastal Andhra. Zero attendance was lost.
A biometric reader that requires the cloud to be up is a biometric reader that's useless on the day it matters most. Edge-first is the only design that survives Indian internet.
Conflict resolution: simpler than you'd expect
Two questions come up repeatedly: what if the same student is marked at two different gates within seconds, and what if a gate's clock drifts?
The first is dedup-by-event-window. If we receive two attendance_marked events for the
same student within 90 seconds at different gates, we keep the earlier timestamp and tag
the later one as gate_redundant. The school's policy decides whether redundant marks are
ignored or flagged. We don't try to reconcile which gate was "real" — both happened, both
get logged, the policy decides what counts.
The second is solved with NTP and skepticism. Every edge box runs chrony against a pool, but we also include the cloud-receipt timestamp in every event. If the gate-reported timestamp and the cloud-receipt timestamp differ by more than 5 minutes after accounting for buffer flush, the gate is flagged for clock-drift inspection. In practice this fires for one or two gates a year, usually after a power cut reset the box's RTC.
What we got wrong on the first try
We initially trusted vendor SDKs to do the matching for face-rec. That worked until a school deployed in monsoon-season Hyderabad where humidity affected camera optics, vendor match scores dropped, and false-rejects spiked. We now run our own matcher (an embedding model fine-tuned on Indian-school cohorts) on the Jetson Nano and use the vendor only for capture. False-reject rates dropped from 4.8% to 0.6%.
We also initially tried to push every event to the cloud immediately, with the local buffer as a "fallback". That meant the system was always one bad ten-second connectivity blip away from the principal's morning dashboard being wrong. Inverting the design — local is primary, cloud is async — was a rewrite, but the right one.
If you want this in your school, /campus covers the full attendance stack. Specifics for your hardware mix: admin@airanexus.in.