Stripe VO (2026–2027): Payment Transaction Risk Linkage System in 3 Progressive Parts
Stripe VO coding recap: finding risk-linked payment transactions — Part 1 attribute matching, Part 2 configurable weighted scoring, Part 3 second-degree indirect links with BFS — with a layered code design and what the interviewer focused on.
Business context
Stripe's risk system: given a target transaction, find other transactions with a risk link to it.
The problem has 3 progressive parts: simple attribute matching, then weighted scoring, then indirect links over a graph. It's modeled on real payment risk work — mining the risk network between transactions to catch organized fraud.
Part 1: Basic attribute matching
Requirement: two transactions are linked if any one risk attribute matches, for example:
- The same card number
- The same IP address
- The same device ID
Approach: essentially a set-intersection problem. Take the target's risk attributes and check every transaction for any overlap.
Key clarifications:
- Can fields be empty? Empty attributes don't participate in matching.
- A transaction may carry several attributes.
Part 2: Risk confidence scoring
Requirement: some risk fields are more suspicious than others, so each field gets its own weight. When two transactions match on a field, add its weight; they're linked only if the total exceeds a threshold.
Approach: make it configuration-driven and avoid piles of if-else. Keep a weight map from attribute name to risk score; add scores for matches and compare with the threshold at the end.
What the interviewer focused on: how to make weights configurable so new risk fields can be added without touching the core matching logic.
Follow-ups:
- If an attribute matches multiple times, does its score count more than once?
- How do you handle fields with weight 0?
Part 3: Indirect risk links
Requirement: find not just directly linked transactions but also second-degree ones.
- Direct (first degree): transactions that match the target directly.
- Indirect (second degree): transactions that match a direct match.
Return all first- and second-degree links, deduplicated, excluding the target itself.
Approach: it's a graph search, and BFS fits best.
- First BFS layer: all directly linked transactions.
- Expand from that layer once more to get the second-degree links.
- Deduplicate and exclude the original transaction ID.
Pitfalls:
- Cycles: e.g. A links to B and B links back to A — keep a
visitedset to avoid infinite loops. - Empty results.
- Lots of duplicate transaction IDs.
Reference implementation: iterating through the three parts
Split "field matching, scoring rules, graph search, deduplication" into separate functions, so new requirements only swap the rule, never the search:
RISK_FIELDS = ("card", "ip", "device")
def matched_fields(a, b, fields):
"""Risk fields that are non-empty and equal on both transactions"""
return [f for f in fields if a.get(f) is not None and a.get(f) == b.get(f)]
# Part 1: related if any field matches
def any_match(a, b):
return bool(matched_fields(a, b, RISK_FIELDS))
# Part 2: score with configurable weights; related only above the threshold
def make_weighted_rule(weights, threshold):
def rule(a, b):
score = sum(weights[f] for f in matched_fields(a, b, weights))
return score > threshold
return rule
# Part 3: BFS for related transactions within max_depth hops
def related_transactions(target_id, txns, is_related, max_depth=2):
by_id = {t["id"]: t for t in txns}
visited, frontier, result = {target_id}, [by_id[target_id]], []
for _ in range(max_depth):
nxt = []
for cur in frontier:
for other in by_id.values():
if other["id"] not in visited and is_related(cur, other):
visited.add(other["id"])
nxt.append(other)
result.extend(t["id"] for t in nxt)
frontier = nxt
return result
max_depth=1covers Parts 1 and 2;max_depth=2covers Part 3.- With lots of data, build an inverted index from "field value → transaction IDs" so you only look at transactions sharing a value instead of scanning everything.
What the interviewer focused on
Stripe's engineering problems aren't about optimal complexity. They look at:
- Code layering
- Readability
- Modular design
During the interview, make sure to:
- Explain your thinking as you code
- List test cases proactively
- Avoid coding in silence
The interviewer keeps adding requirements to see how well your code extends, for example:
- Limiting the maximum search depth
- Adding risk scores to link chains
- Filtering out low-scoring links
Found this helpful? Let's talk.
Happy to swap interview notes, do mock interviews, or share referral info.

Scan to add me on WeChat
More Stripe notes
View all ›- Stripe SDE VO | How the Integration Round WorksStripe · 2026-10-04›
- Google 2027 SWE Intern VO, Fresh Recap: HashMap + Sliding Window and Graph BFSGoogle · 2026-10-04›
Amazon New Grad Interview Question: TaskScheduler, Fully Analyzed (Topological Sort)Amazon · 2026-10-02›
Amazon New Grad Four-Round VO: What Changed This Year + Three Business-Scenario Coding Questions + Bar Raiser Deep DiveAmazon · 2026-10-04›