FaceClass is a face-recognition attendance system for coaching centres: a tablet at the entrance recognises a student and records check-in and check-out. It went through two versions, and the difference between them is the most useful part of the story.
Version 1: a vendor SDK prototype
The first version started from a commercial face-recognition SDK and its sample attendance app. The vendor's native library did the detection, liveness check and matching on the device, and my Flutter code talked to it over a platform MethodChannel.
That got a working demo fast, but it had real costs:
- A black box. I couldn't tune or inspect how recognition worked. I could only call it.
- Licensing and dependency. The core of the product belonged to someone else.
- Little of it was mine. The part that mattered most was the part I hadn't built.
Version 2: TensorFlow, ML Kit and a local vector database
The current FaceClass replaces the vendor SDK entirely:
Camera → Google ML Kit (find the face) → TensorFlow model (face → embedding)
→ local vector database (nearest match) → check-in / check-out
- ML Kit detects the face in the camera frame.
- A TensorFlow model turns the face into an embedding: a list of numbers that describes it.
- The embedding is compared against enrolled students in a local vector database on the tablet, and the closest match above a threshold is the student.
Everything runs on the device, so recognition doesn't depend on the network. This version is running daily at 4–5 institutes on their own hardware.
The parts around recognition
These carried over from the first version and matter as much as the model:
- Enrollment: capturing a student's face and storing their embedding.
- Attendance rules: check-in vs check-out, with a minimum gap between the two so a student lingering in front of the camera doesn't instantly check out.
- Kiosk mode: the tablet runs as a locked, single-purpose device, using Android device-owner and lock-task mode with a PIN to exit.
- Backend: NestJS and PostgreSQL, with multi-centre tenancy and role-based access (more in NestJS Without an ORM).
What I'd build next
In the first version, check-ins were written to the server first. The local record updated only after the API confirmed, so without a network no new marks were recorded. The improvements I'd make:
- An offline outbox: queue marks locally with a client-generated ID, and sync them when back online.
- Idempotent writes: a unique constraint on (student, session, date) plus the client ID, so retries can never double-mark.
- Low-confidence handling: send uncertain matches to a staff confirmation screen instead of guessing.
- Measured accuracy: track false matches and misses per institute, instead of relying on "it works".
Takeaway
A vendor SDK is a great way to prove a product idea quickly. But once the product is real, owning the recognition pipeline (detection, embeddings and matching) gives you control over accuracy, cost and licensing. The model is only half the system, though. The kiosk, the attendance rules and the data sync have to be designed just as carefully.