Jul 22, 2026
14 min read

This work was developed with support from Deepika Khera and Karteek Chada
As PayPal shifts toward automated decision-making, identity becomes the control plane. Customer Graph is PayPal’s enterprise identity system that links customer records across brands and platforms into a single Unified Customer ID (UCID). It preserves the evidence behind each linkage and supports low-latency lookups, so downstream systems - from fraud detection and risk to Ads, recommendations, support, and analytics - can operate on a “real- world customer” view instead of fragmented accounts.
Every large platform eventually re-discovers the same truth: a 'customer' is not a row - it's a concept spread across systems. Banks and fintechs see it as multiple accounts per person across channels. Marketplaces see it as buyers scattered across devices, addresses, and payment methods. Retailers see it as one shopper appearing as guest checkout, loyalty member, and app user.
PayPal has a particularly hard identity problem: we’re not one monolithic product with one customer table. We’re a portfolio of brands and platforms (PayPal, Venmo, Honey, Xoom, Hyperwallet) that were built at different times, with different data models, different identifiers, and different operating assumptions. Each system works correctly in isolation - but the same real-world person can show up as multiple “customers” across these stacks.
Example: A customer creates a PayPal account in 2015, adds Venmo in 2018, tries Honey in 2022, and links a
card through Braintree in 2024. Are these four people - or one?
Without Customer Graph, those
records can appear as separate customers, fragmenting their transaction history and making it harder for
downstream systems to understand the full customer relationship.
This isn’t just a “join some tables” problem. At PayPal scale, identity resolution is difficult for two practical reasons:
Customer Graph addresses these constraints through multi-stage entity resolution: deterministic candidate generation on contact attributes (email/phone/address), fuzzy name matching with fine-tuned thresholds for each contact attribute and connected components clustering with explicit singleton recovery. Overall, the system resolves 1.4B+ records into 700M identities, processes 300-500K incremental updates every 30-60 minutes.
Entity resolution answers a simple question: when do two different records actually describe the same real-world customer? It’s tricky because real data is messy - one system might have “Alex R.” with an old Gmail, another “Alexander Roberts” with a work email, and a third only a phone number and partial address.
Customer Graph makes this workable at PayPal scale with an end-to-end pipeline:
Note: More on the entire algorithm in the sections below.
Once identities are resolved, we store them in Spanner Graph for real-time queries. Downstream teams can call a simple API to fetch the UCID and Golden Profile, allowing them to answer “who is this customer?” instantly whether they start from a UCID, email, phone number, or address. The heavy lifting - processing large volumes of data and recomputing identities - happens offline, but the results are served in real time so Ads, risk, support, and recommendations can make decisions on the latest unified customer view. Building Customer Graph Step by Step.
At the start, customer data looks like a pile of disconnected records - each system has its own profile, its own ID, and its own incomplete view. E.g: PayPal profile, Venmo profile, Honey profile, etc. all separate. To unify customer identities, we don’t try to “merge everything.” We build connections only when there’s a good reason.
The first step is simply figuring out which records are even worth comparing. At PayPal scale, you can’t compare every profile to every other profile - so we only consider pairs that share an exact, strong-signal attribute, like:
This creates a short list of “possible neighbors” for each record - the only pairs we’ll look at more closely.
Note: Before merging these records, we first measured how often each email, phone, and address value is shared across profiles, because the data distribution tells us where the risk and compute blow-ups live.
This distribution analysis directly informed our blocking strategy: filter out weak placeholders, then confidently generate candidate pairs on strong signals.
Sharing an attribute is necessary, but not always sufficient. So for every candidate pair, we do a second check: Do the names agree strongly enough to treat this as one person?
This is where fuzzy name matching comes in (e.g., handling small spelling differences), and we also add practical safeguards:
If the pair passes these checks, we create a link or edge between the records - and we also store why (evidence) that link was made (attribute_used_for_blocking: EMAIL, attribute_: john.s@email.com).
Once edges exist, identities form naturally. If Record A links to B, and B links to C, then A/B/C are treated as one cluster - even if A and C never directly matched. That whole connected group becomes one resolved customer, and we assign it a stable ID: UCID. This transitivity is powerful - it’s how identity stays continuous as people change emails, move addresses, or appear differently across products. But it also needs guardrails, because a single weak or overly-shared value can accidentally pull unrelated people together.
A simple example with email:
alex@gmail.com (older, unverified)alex@work.com (recent, verified)
The Golden Profile would select alex@work.com, because it’s the verified, recent option - and we
keep a note of why it
won, so the choice is traceable.
Once a UCID and Golden Profile have been created, the next challenge is making that identity usable across PayPal. The next section covers how we store/access these profiles.
In practice, downstream teams ask questions like “which identifier connected these records?”, “what other accounts are connected through this phone/email?”, “when did this edge change?” Those are connection-first questions. A graph model fits naturally because it stores identity as a set of nodes (records + identifiers) and edges (the reasons they’re connected).
A graph model is also the most practical way to serve identity at scale because real traffic patterns look like:
That “local expansion” pattern is common not only in lookups, but also in ongoing updates - when new data arrives, you usually need to recompute only the nearby portion of the identity graph, not the entire world.
Graph storage is critical infrastructure for Customer Graph due to three simultaneous requirements:
Identity resolution is hard to evaluate with a single accuracy number, because the true answer changes over time (people change emails, move addresses, reuse phones), and perfect labels at PayPal scale don’t exist. We use two complementary validation approaches: Synthetic data benchmarking to test algorithm robustness under controlled conditions, and Baseline comparison to validate stability on production data.
If the baseline already considers a set of records to be the same customer, do we also keep that set together?
Through our evaluations, we observed that about 95% baseline customer groups/clusters stayed preserved. That’s the stability signal we want, we generally don’t break apart identities that are already stable, unless the data is messy or inconsistent.
We also looked closely at the cases where our system breaks a baseline cluster into two or more clusters. That difference isn’t automatically “wrong”. In practice, identity resolution is a tradeoff: sometimes the safest choice is to not connect records unless the data gives a clear reason to do so, because accidentally linking two different people can create much bigger downstream problems than leaving one person slightly fragmented.
When we dug into why these differences happen, one signal stood out again and again:0addresses are the hardest field to use reliably at scale. The same location can be written dozens of ways (“Apt 4B” vs “#4B”, “Mirada Dr” vs “Mirada Drive”), profiles may have partial or missing address fields, international formats vary widely, and many addresses are legitimately shared by multiple people (families, roommates, apartment buildings). Since address data is extremely noisy many address normalization tools sometimes miss these nuances during input preprocessing.
In Ads, we build audience segments like Cycling & Bike Enthusiasts, Jewelry & Watches, Streaming Video, SMB owners, and many more. A single person can qualify for hundreds of segments, and within each segment we often track strength or tiering - from “basic” membership to “mid” to “high-intent,” depending on signals like frequency and spend. Without a unified key, segmentation drifts into account-level labeling: the same real-world customer can appear multiple times and measurement becomes noisy. We end up asking uncomfortable questions like: did we really reach 30M customers, or did we reach 30M accounts with duplicates? UCID fixes that by giving Ads a consistent “person-like” anchor. More importantly, Customer Graph gives PayPal something we didn’t really have before: identity as a platform that can be tuned for different business needs, rather than a black-box system we must live with.
Control over the base graph matters because Ads and risk don’t want the same “view” of identity. We build a shared base identity layer that is consistent across the company (so PayPal, Venmo, Honey, Xoom, Hyperwallet all roll up to the same customer view). Then we can safely layer use-case specific policies on top - without rebuilding the whole graph.
Here’s a practical example. Imagine a phone number that shows up across a large number of accounts. Risk often wants that surfaced as-is because it can be a signal of coordinated behavior (e.g., shared credentials, synthetic identities, fraud rings, or account farms). In that world, a “high-degree connector” is valuable: it’s a flag, not just a linkage.
For Ads that same high-degree connector is dangerous in a different way. If we treat that phone as a strong join key, we could accidentally roll many unrelated people into one big blob. Ads may prefer we break those apart, because cleaner identity means cleaner segments, and cleaner segments mean less wasted budget on duplicates and mistargeting.
In short: cloud + real-time serving makes the identity usable in production systems, but customization + control is what makes it valuable - because Ads, risk, and recommendations can all start from the same truth, then apply the right view for their tasks. The lessons from Customer Graph also create a foundation for complementary knowledge graphs that extend identity resolution beyond customers. The next section explores that broader direction in more detail.
Customer Graph is the foundation for a broader set of graph-based capabilities across PayPal. It tells us who is acting across PayPal, Venmo, Honey etc. by giving us a single UCID for the same real-world customer. But to explain what that customer did in a way that’s useful to the business, we also need the merchant side to be equally clean; because merchants have the same problem: one real brand, many representations.
That’s where Merchant Graph comes in. It resolves messy merchant identities so “Disney,” “Disney.com”, “Disney Plus” and “Disney Parks” can be understood as the right set of related entities - rolled up when you want a brand view, and separated when sub-brand detail matters. Without that, any “brand-level” insight is unclear to downstream, because you’re never sure if you’re measuring one brand or multiple name variants of the same brand.
Once both sides are resolved, one could connect customer activity into an end-to-end storyline across products, anchored on UCID (same shopper) and merchant resolution (same brand). Goal is to identify if it’s the same customer across products, and we need to know we’re talking about the same merchant brand across various transaction signals in multiple internal systems, this way we can condense messy events into a unified signals that downstream systems can utilize.
This post is intended as the front door to the topic. In follow-on posts, we plan to explore some of the main components in more detail, the incremental pipeline, graph storage and workflow design, evaluation and monitoring, and downstream integrations such as user segmentation risk. The goal is to gradually unpack both the technical foundations and the practical tradeoffs behind the system.
[1] Köpcke, H., & Rahm, E. (2010). Frameworks for entity matching: A comparison. Data & Knowledge Engineering,
69(2),
197-210.
[2] Hu, W., Qu, Y., & Cheng, G. (2008). Matching large ontologies: A divide-and-conquer approach. Data &
Knowledge
Engineering, 67(1), 140-160.
[3] Elfeky, M. G., Verykios, V. S., & Elmagarmid, A. K. (2002, February). TAILOR: A record linkage toolbox. In
Proceedings 18th International Conference on Data Engineering (pp. 17-28). IEEE.

5 min read

5 min read

5 min read