โ†Back to HomeCASE STUDY 02 // IDENTITY / CUSTOMER DATA // DETERMINISTIC MATCHING
CROSS-DEVICEโ€ขPUBLISHED 2025-09-12

Identity Resolution

Architected deterministic identity resolution across email, device ID, cookie, phone, push token, and platform customer IDs to unify pre-purchase sessions across devices and channels โ€” so a customer leaving an email in a promotional popup on browser, then purchasing later on mobile, had all their prior activity correctly attributed to them.

IDENTIFIERSEmail, Device ID, Cookie, Phone, Push Token, Platform ID
MATCHINGDeterministic, key-based
RESOLVED ATRead-time, across legacy distributed DBs
STATUSLive ยท Profile renovation v2 planned
MERCHANTS
200-300+
CONTACT MERGE RATE
~15%+
Matched into existing identity vs. new user
IDENTIFIERS UNIFIED
6
RENOVATION V2
Architected, not shipped
01 // ROLE & CONTEXT

My Role

Owned the architecture and rollout of identity resolution across a legacy, highly-distributed customer-profile system serving 200-300 merchants. Worked with data, product, and platform teams to surface unified customer identities at read-time across existing per-service databases โ€” no migration, no single identity store, but a deterministic key-based join across email, device IDs, cookies, phone numbers, push tokens, and internal platform customer IDs (Shopify, BigCommerce, etc.).

The problem: customers shopped across devices and channels, but merchant systems tracked them as separate individuals. A customer who left an email in a promotional popup on a browser, then purchased on mobile hours later, would show up as two different users โ€” losing all signal from the browser session (pages viewed, cart adds, engagement) for downstream features like segmentation and recommendations.

02 // THE PROBLEM

Fragmented Customer Identity Across Devices

The customer-profile system was legacy and highly-distributed: customer data lived across multiple databases maintained by different services, each storing its own subset of identifiers (email in one system, device ID in another, platform customer ID in a third). Matching a single customer across these systems required joining across database boundaries at query-time โ€” expensive, slow, and unmaintained.

BEFORE
  • Customer email on browser session
  • Same customer device ID on mobile purchase
  • Two separate user profiles
  • Signal from browser session lost
WHY IT MATTERED
  • Incomplete customer profiles
  • Personalization based on false premises
  • Segmentation and recommendations off-target
  • ~15%+ of customers unidentified as duplicates
03 // ARCHITECTURE

Deterministic Matching at Read-Time

Instead of migrating to a single identity store (a risky, expensive rewrite on legacy systems), identity resolution ran at read-time: when a customer was retrieved for segmentation, recommendations, or reporting, a deterministic join across six identifiers (email, device ID, cookie, phone, push token, platform customer ID) matched them against existing customer records. If any identifier matched, the records were unified in-memory, creating a single, merged customer profile.

FRAGMENTED โ†’ UNIFIED: A CUSTOMER ACROSS DEVICES
Browser Session
Email: user@example.comDevice: iPhone (cookie)3 pages viewed, cart addโ†“ (no connection)
Mobile Purchase
Same Email DetectedSame Device IDPurchase: $45
Unified Identity
Email: user@example.comDevice ID + Phone: 2 matchesโ†’ Same PersonFull Customer ProfileBrowser: 3 pages, cart addMobile: purchase $45Now used for segmentation
POWERED BY: Customer retrieval โ†’ Deterministic identifier join (Email, Device ID, Cookie, Phone, Push Token, Platform ID) โ†’ Unified in-memory profile โ†’ Sent to segmentation, recommendations, analytics
04 // KEY DECISIONS

Decisions & Tradeoffs

  • Read-Time Join, Not Migrate-First

    Legacy profile system was highly distributed across service databases. A full migration to a single identity store would have been expensive, slow, and risky โ€” we would have shipped slower. Read-time deterministic join added latency per query but avoided the migration entirely, letting us ship identity resolution without blocking on infrastructure renovation.

  • Deterministic Matching Only

    Scoped out probabilistic/fuzzy matching (e.g. email-similarity heuristics, ML-based clustering) to ship faster and keep resolution auditable โ€” if two records matched, it was because an exact identifier was shared, not a guess. Probabilistic matching would have higher recall but lower precision, risking false merges that are hard to debug in production.

  • No Conflict Resolution (v1)

    Deterministic matching assumed clean data โ€” a shared email meant the same person. In reality, email can be reused (e.g. a shared account, a person using a generic email across merchants). Handling conflicts (determining which identity wins, handling merges/splits) was designed for v2 (a full profile-system consolidation) but not shipped in v1 โ€” the v2 renovation would have also unified schema, reduced read-time join complexity, and solved conflicts structurally.

05 // EXECUTION

Rollout & The Hard Part

Started by adding identity resolution to the segmentation query engine โ€” the most critical consumer of unified identity. Tested with a subset of merchants, measured merge rate (proportion of contacts resolved into an existing identity), and checked for correctness via spot-checks on known multi-device customers. Expanded to recommendations and analytics once confident, then rolled out to all 200-300 merchants.

โš The Hard Part: Matching Across Distributed Databases

Each identifier lived in a different database: customer emails in MySQL (order records), device IDs in a time-series store (event log), cookies in an in-memory cache (session data), platform customer IDs in a MongoDB document (merchant sync). Matching a single customer required joining across these stores simultaneously โ€” coordination overhead was high. A cache helped, but the join still happened at read-time for every customer retrieval until the identities were resolved. Later optimization: we added an identity cache that pre-warmed common identifier pairs, reducing the number of cross-DB joins per query. (Full cache to resolution would have required the profile-system renovation planned for v2.)

06 // RESULTS & RETROSPECTIVE

Impact

Identity resolution lifted contact merge rate by ~15%+ โ€” meaning ~15% of contacts that would have been counted as separate individuals were correctly resolved into an existing customer identity. Segmentation immediately got richer (audiences now included prior cross-device activity), recommendations improved (training data included a customer's full history, not a fragmented view), and analytics became more accurate.

What I'd change today: The read-time join cost never went away โ€” every customer retrieval paid the latency penalty until resolution was cached. The planned profile-system renovation (consolidating customer data into one store, handling conflicts structurally) would have solved this at the root, but was architected and scoped for v2, which didn't ship before the role transitioned. If building this again, I'd either (a) invest in the infrastructure renovation upfront, or (b) build a smarter identity cache that handles edge cases (email reuse, account takeovers) earlier, rather than deferring to v2.