← All Case Studies

Memora AI

Distributed Image Clustering Engine

1. Core Problem & Scope

Manual event photo sorting scales quadratically — O(N²) — in friction for users. After a wedding or large event, photos scatter across 10-20 phones and a shared Drive folder turns into 1,000+ unsorted images, and finding your own becomes a manual search problem. The scope was to build an automated, privacy-first, identity-grouped sorting system that could take a single shared upload link and return personalized, per-guest photo sets without manual tagging or signup.

2. Comparative System Research

Three approaches were evaluated for the face-grouping core:

  • Manual tagging / crowd-sourced labels — zero infrastructure cost, but doesn't scale past a handful of guests and reintroduces the exact friction the product is meant to remove.
  • Cloud vision APIs (managed face grouping) — fast to integrate, but per-image pricing at event scale (thousands of photos per event) made unit economics unworkable, and clustering behavior wasn't tunable to this use case's lighting and pose variance.
  • Self-hosted embedding + clustering pipeline (chosen) — FaceNet embeddings with DBSCAN clustering gave full control over the distance threshold and cluster density parameters, at the cost of owning the infrastructure.

The self-hosted path won on both unit economics at scale and on the ability to tune verification thresholds against real event photos, which have far more pose and lighting variance than the datasets managed APIs are typically benchmarked against.

3. Architectural Pipeline Layouts

Client Upload → Redis Queue → YOLOv8-Face / MTCNN → FaceNet Embedding Extraction → DBSCAN Clustering → S3 Segmented Retrieval

Uploads land in a Redis-backed queue consumed by Celery workers. Each image passes through a face detector (YOLOv8-Face, with MTCNN as a fallback for difficult crops), face crops are embedded into 128-D vectors via a Triplet-Loss fine-tuned FaceNet backbone, and DBSCAN (ε = 0.55, MinSamples = 3) clusters the embedding space per event. Each guest's personalized set is retrieved from segmented S3 prefixes keyed by cluster ID.

4. Trade-off Engineering Logs

Why DBSCAN over k-means: k-means requires knowing the number of clusters (guests) in advance, which is never known ahead of time for an arbitrary event. DBSCAN's density-based approach discovers the number of clusters organically and — critically — has a built-in notion of "noise" points, which maps naturally onto blurry or partially-occluded faces that shouldn't be forced into any cluster.

Verification threshold (d ≤ 0.6): Set empirically by evaluating false-merge rate (two different people grouped together) against false-split rate (same person split across two clusters) on real event photo sets. False merges are far more damaging to trust in the product than false splits, so the threshold was tuned conservatively toward fewer merges even at the cost of some over-splitting.

5. Scaling & Production Failures

The first concurrency ceiling appeared around 150 simultaneous uploads, where Celery workers began queuing faster than they could drain — traced to synchronous S3 writes blocking the worker event loop. Moving to async S3 client calls and increasing worker concurrency per pod resolved the bottleneck and pushed sustainable concurrency to 500 workers under load testing. A second failure mode surfaced with extreme backlighting at outdoor events, where the face detector's recall dropped sharply enough to leave guests out of any cluster; this was mitigated with a CLAHE contrast-normalization pre-processing step ahead of detection.