Special Report
Cyrys: A real-time face detection and tracking system
Face detection, person tracking, identification, and automated watchlist monitoring, built as Python microservices.
By Vedi Gharibian
Charlotte, NC
The problem
Cyrys is a real-time video surveillance and analytics system. It detects faces, tracks people across a video stream, identifies them using face embeddings, and monitors what it sees against a watchlist. The front end is Vue; the back end is a set of Python microservices built on FastAPI, with YOLO doing detection.
A system like this is only useful if it keeps pace with the stream. Work that is merely correct but late is not real-time analytics. Most of the engineering to date has gone into the architecture rather than the models: how many services there are, what they contend over, and which work blocks the detection loop.
The architecture
Cyrys is a real-time video surveillance and analytics system for face detection, person tracking, and identification, with automated watchlist monitoring. It is built as Python microservices with FastAPI and YOLO behind a Vue front end, and identification runs on face embeddings.
A pipeline diagram. A video stream feeds a detector. The detector hands work to asynchronous face processing, which passes results to a unified deduplication service, then to a watchlist check, which emits alerts over WebSockets. Analytics branches off the detector as a separate path.
Cutting 20 services to 12
The system started at 20 services and now runs on 12. The reduction came from finding redundancy between services and improving parallel processing rather than from cutting features.
A second effect showed up once the count came down. With 20 services, several of them were writing to disk at the same time and contending for locks. Consolidating the services reduced that contention directly, which is a cost of a fine-grained architecture that does not appear in a service diagram.
Deduplication was the clearest case. Three separate systems handled it: face-based matching, automatic matching, and profile-enhanced matching. They were merged into one unified service behind a single API. The requirement was that profile-based matching accuracy survive the merge, because profile-based matching is meaningfully better than simple face matching, and consolidation is not worth losing it.
API compatibility was maintained across the refactor through backward-compatible endpoints and migration guides, so consumers did not have to move in lockstep with the internals.
Real-time watchlist alerts
Watchlist monitoring was built into the stream-processing pipeline rather than bolted on beside it. Faces are checked automatically as they come through, and matches raise live alerts over WebSockets.
Alerts also needed cooldowns. Without them, a single person in frame for a sustained period generates a continuous stream of identical alerts, which makes the channel useless exactly when it matters. The cooldown logic suppresses repeats within a window so an alert stays a signal.
The other half of real-time behaviour was getting face processing off the main detection thread. Running it synchronously there was the major bottleneck in the pipeline; moving it to asynchronous processing removed it.
Lessons learned
Consolidate services strategically
Merging the three deduplication systems cut complexity without losing accuracy. Fewer, better-scoped services performed better than more granular ones.
Profile-based matching has to survive refactors
Profile-based matching beats simple face matching, so architectural changes had to preserve it rather than trade it away for a cleaner design.
Real time requires async
Synchronous face processing on the main detection thread is a bottleneck. Moving it to asynchronous processing was the single largest real-time improvement.
Concurrent disk writes cause lock contention
Multiple services writing to disk at the same time contend for locks. Consolidating services reduced that contention as a side effect.
Stack and status
Python microservices with FastAPI, YOLO for detection, face embeddings for identification, WebSockets for live alerts, and a Vue front end.
Cyrys is in active development.
- Repository
- private
Status: In active development