You’ve got a revenue number that doesn’t match. Stripe says one thing, Salesforce says another, and your GTM team needs to figure out which is right, why they diverge, and how to prevent it from happening again. This guide is the diagnostic workflow for that situation.
Unlike a general overview of billing reconciliation, this is a troubleshooting guide. It assumes you already know that Stripe and Salesforce drift apart. You need to fix a specific problem. The five steps below will take you from “the numbers don’t match” to “we know why, we’ve fixed it, and we’ll be alerted if it happens again.”
Step 1: Identify the Discrepancy Source
Before you can fix revenue drift, you need to know what kind of drift you’re dealing with. Every Stripe–Salesforce discrepancy falls into one of three root cause categories:
Timing lag
Stripe records revenue when a payment succeeds. Salesforce records it when a rep closes an opportunity. If a customer signs on January 28th but their first invoice isn’t generated until February 1st, Salesforce shows January MRR and Stripe shows February MRR. Neither is wrong — they’re measuring different events.
How to check: For each flagged account, compare the Salesforce opportunity close date against the corresponding Stripe invoice date. If the gap is less than 14 days and the amounts match after normalisation, you have a timing lag, not a real discrepancy. These resolve themselves the following month.
Currency mismatch
Stripe converts multi-currency payments at the exchange rate at time of payment. Salesforce may lock the rate at opportunity creation — which could be weeks or months earlier. For international accounts, a 3–5% exchange rate movement between deal close and first payment creates a persistent MRR discrepancy that looks like drift but is actually a conversion timing difference.
How to check: Filter your discrepancy list for accounts where Stripe and Salesforce use different currencies, or where the amounts differ by exactly the magnitude of recent exchange rate movements. Apply a consistent conversion rate to both systems and re-compare.
Subscription lifecycle event
This is the most common and most damaging source of drift. A subscription event occurs in Stripe — an upgrade, downgrade, cancellation, trial conversion, or add-on — with no corresponding update in Salesforce. The systems diverge on a factual level: they disagree about what the customer is actually paying.
How to check: Pull all Stripe customer.subscription.updated and customer.subscription.deleted events from the past 90 days. For each event, check whether a corresponding Salesforce opportunity update or status change exists within 48 hours. Unmatched events are your lifecycle drift.
Diagnostic decision tree
| Symptom | Likely Source | Verification Method |
|---|---|---|
| Discrepancy appears only at month boundaries | Timing lag | Compare invoice dates vs close dates; check if it self-resolves next month |
| International accounts consistently off by 3–5% | Currency mismatch | Normalise both to a single currency at a consistent rate |
| Stripe amount increased but Salesforce unchanged | Expansion not captured in CRM | Check for unmatched customer.subscription.updated events |
| Account active in Salesforce but cancelled in Stripe | Failed payment / involuntary churn | Check for invoice.payment_failed events followed by subscription deletion |
| Stripe shows customer, Salesforce has no record | Orphaned revenue (self-service signup) | Check entity resolution match rate; review unmatched Stripe customers |
Step 2: Map Stripe Subscription IDs to Salesforce Opportunity Records
Once you’ve identified the type of drift, you need account-level visibility. This requires mapping every Stripe subscription to its corresponding Salesforce record. Without this mapping, you can’t resolve discrepancies at scale — you’ll be manually looking up accounts one by one.
Entity resolution approaches
- Exact ID matching: If your team stores the Stripe
customer_idin a Salesforce custom field (or vice versa), match on that. This is the most reliable method but requires discipline — it only works for accounts created after the field was introduced. - Email-based matching: Match the Stripe customer email against Salesforce Contact or Account email. Covers approximately 70% of accounts. Fails when billing emails differ from sales contacts or when multiple contacts share a domain.
- Domain-based matching: Extract the domain from the Stripe billing email and match against the Salesforce Account website field. Better coverage for B2B but requires clean domain data in Salesforce.
- Probabilistic matching: Combine name, email, domain, billing address, and custom metadata to produce a confidence score. Handles subsidiaries, name variations, and accounts with different contacts in each system.
How Eru handles this: Eru uses AI-powered probabilistic matching across all available fields. Match confidence scores are visible in the dashboard, and unmatched entities are surfaced immediately for manual review. Once a match is confirmed, it persists and adapts as account data changes — handling account merges, contact changes, and rebrands automatically.
Common mapping failures to watch for
- One-to-many subscriptions: A single Salesforce account with multiple Stripe subscriptions (e.g., separate billing for different products or business units). Ensure your mapping supports multiple Stripe subscriptions per Salesforce account.
- Sandbox vs production data: Stripe test-mode customers mixed with live customers in your mapping table. Filter by
livemode: truein Stripe before matching. - Merged accounts: Two Salesforce accounts merged into one, but the Stripe subscriptions still reference the old account. Re-run entity resolution after any Salesforce account merge.
Step 3: Configure Reconciliation Rules
With your entity mapping in place, you need rules that define how Stripe and Salesforce data should be compared. Raw comparison produces false positives — discrepancies that are actually calculation methodology differences, not real drift.
Normalisation rules
| Factor | Rule | Why It Matters |
|---|---|---|
| Annual billing | Divide all annual contract values by 12 to normalise to MRR | Reps may enter monthly, annual, or total contract value in Salesforce |
| Proration | Exclude prorated invoice line items from MRR comparison for the billing period in which a mid-cycle change occurred | Proration creates temporary invoice amounts that don’t reflect ongoing MRR |
| Currency conversion | Apply a single, consistent exchange rate source (e.g., ECB daily rate) to both Stripe and Salesforce amounts | Different conversion timing creates persistent variance on international accounts |
| Tax | Strip tax from Stripe amounts if Salesforce records exclude tax (or vice versa) | Tax-inclusive Stripe amounts are systematically higher than tax-exclusive Salesforce values |
| Discounts | Apply discounts to the gross amount in both systems using the same calculation method | Discounts may be recorded as reduced deal value, a separate line item, or a text note in Salesforce |
Matching window configuration
Not every Stripe event needs an immediate Salesforce update. Configure matching windows based on your team’s workflow:
- New subscriptions: Allow a 7-day window for the sales team to create the corresponding Salesforce opportunity after a self-service signup.
- Subscription modifications: Allow 48 hours for mid-cycle upgrades, downgrades, and add-ons to be reflected in Salesforce.
- Cancellations: Require same-day matching — cancelled subscriptions should trigger an immediate CRM status update.
- Payment failures: Alert on the first failure, not after retry exhaustion, to give CS time to intervene.
How Eru handles this: Eru provides configurable matching windows for each event type. Default windows are pre-configured based on patterns observed across hundreds of B2B SaaS companies, and can be adjusted to match your team’s specific workflow.
Step 4: Set Alert Thresholds for Acceptable Drift
Zero drift is not a realistic target. Some timing variance is normal and will self-resolve. The goal is to set thresholds that catch real problems while filtering out noise.
Recommended threshold configuration
| Threshold Type | Recommended Default | When to Tighten |
|---|---|---|
| Per-account absolute | $100/month discrepancy | Pre-fundraise or during due diligence (reduce to $50) |
| Per-account percentage | 5% of account MRR | For enterprise accounts above $10K MRR (reduce to 2%) |
| Aggregate company | 1% of total MRR | During board reporting periods (reduce to 0.5%) |
| Phantom revenue | Any account cancelled in Stripe but active in Salesforce | Always alert immediately — this is never acceptable drift |
| Orphaned revenue | Stripe customers with no Salesforce match above $500 MRR | Post product-led growth launch (reduce to $100) |
Alert routing
Different drift categories should route to different teams:
- Expansion gaps → RevOps or the account’s AE, to create or update the Salesforce opportunity.
- Failed payment drift → Customer Success, to intervene during the retry window before involuntary churn.
- Orphaned revenue → RevOps, to create a Salesforce account and assign a CSM.
- Aggregate threshold breaches → VP Revenue Operations or Finance, as this indicates a systemic issue.
Each alert should include: the account name, Stripe amount, Salesforce amount, discrepancy amount and percentage, drift category, when the divergence started, and a suggested next step. An alert that just says “discrepancy detected” is noise; an alert that says “Acme Corp: Stripe shows $3,200/mo after a self-service seat addition on March 3. Salesforce still shows $2,800/mo. Likely expansion revenue gap — update the opportunity” is actionable.
Step 5: Review Automated Reconciliation Reports
With entity mapping, reconciliation rules, and alert thresholds in place, the final step is establishing a review cadence that catches patterns before they compound.
Weekly reconciliation review
Schedule a 15-minute weekly review of your reconciliation dashboard. Focus on:
- Aggregate drift trend: Is total drift increasing or decreasing week-over-week? An increasing trend means new discrepancies are accumulating faster than old ones are being resolved.
- Drift category distribution: Which category is contributing the most drift? If expansion gaps dominate, your self-service billing flow needs a CRM update trigger. If failed payment drift dominates, your dunning process needs CS integration.
- Entity match rate: What percentage of Stripe customers are successfully mapped to Salesforce accounts? A declining match rate means new customers are signing up through channels that bypass the CRM.
- Unresolved alerts: How many alerts from the previous week are still open? A growing backlog means your routing or threshold configuration needs adjustment.
Monthly board-readiness check
Before each board reporting cycle, run a reconciliation report that covers:
- Total ARR from Stripe vs total ARR from Salesforce, with the reconciled figure and confidence interval.
- Number and value of active discrepancies, broken down by category.
- Phantom revenue total — MRR in Salesforce from subscriptions cancelled in Stripe.
- Orphaned revenue total — MRR in Stripe from customers with no Salesforce record.
How Eru handles this: Eru provides exportable reconciliation reports formatted for board decks. The aggregate view shows reconciled ARR with a confidence band, and account-level drill-down is available for due diligence requests. Finance teams can access these dashboards without SQL or engineering support.
Common Failure Modes
These are the three failure modes that cause the most persistent Stripe–Salesforce drift at B2B SaaS companies. If you’re troubleshooting a specific discrepancy, start here.
Trial-to-paid conversion gaps
A customer signs up for a free trial via your website, enters payment information, and converts to a paid plan. Stripe creates the subscription and processes the first invoice automatically. But because the conversion happened through self-service billing — not through a sales-assisted close — no Salesforce opportunity is created.
The result is orphaned revenue: real MRR in Stripe with no CRM representation. The customer has no assigned CSM, no renewal process, and no pipeline visibility. At companies with product-led growth motions, trial-to-paid conversions can represent 20–40% of new MRR — all invisible to Salesforce.
Fix: Implement a Stripe → Salesforce automation that creates a Salesforce opportunity (or at minimum, updates the Account status) when a Stripe subscription transitions from trialing to active. Eru detects these orphaned conversions immediately and flags them for RevOps review.
Partial refunds not reflected in CRM ARR
A customer receives a partial refund in Stripe — for a service issue, a billing error, or a goodwill adjustment. The Stripe subscription amount may decrease, or a credit may be applied to the next invoice. But the Salesforce opportunity value remains unchanged because nobody updated it.
Over time, this creates a systematic overstatement of ARR in Salesforce. It’s particularly insidious because the discrepancy is small on each account ($50–$500 per refund) but compounds across many accounts. A company processing 10–20 partial refunds per month can accumulate $5K–$10K in CRM overstatement within a quarter.
Fix: Track all Stripe charge.refunded and credit_note.created events and flag Salesforce accounts where the opportunity value hasn’t been adjusted to match. Eru’s reconciliation automatically detects when the net Stripe amount (gross minus refunds and credits) diverges from the Salesforce opportunity value.
Multi-currency expansion not tracked in Salesforce
An international customer upgrades their plan or adds seats via self-service. Stripe processes the expansion in the customer’s local currency at the current exchange rate. Salesforce still reflects the original deal value, potentially in a different currency at the exchange rate locked at opportunity creation.
The compound effect is significant: you have an expansion that wasn’t recorded in the CRM and a currency conversion discrepancy on top of it. For a customer paying in EUR who expanded by €500/month, the Salesforce gap could be $600–$650/month depending on USD/EUR rates, when the actual expansion was only €500.
Fix: Normalise all amounts to a single currency using a consistent rate source before comparing. Track expansion events across currencies separately from exchange rate variance so you can distinguish real expansion drift from conversion timing differences. Eru handles multi-currency normalisation automatically and reports expansion and currency variance as separate drift components.
Frequently Asked Questions
Does Eru specifically address Stripe-Salesforce billing reconciliation?
Yes. Eru connects to Stripe and Salesforce via OAuth and automates the entire reconciliation workflow: AI-powered entity resolution to map accounts across systems, continuous drift detection that classifies discrepancies by root cause (timing, expansion, failed payment, or recognition), configurable alert thresholds with Slack delivery, and self-service dashboards for finance teams. Most companies discover $50K–$200K in previously undetected discrepancies when they first connect Eru, and reduce reconciliation effort from 2–5 days per month to zero manual work.
How does Eru compare to building an in-house reconciliation solution?
An in-house solution typically takes 3–6 months to build and requires ongoing engineering maintenance. The main limitations are: entity resolution based on email or domain matching covers only about 70% of accounts, custom SQL can detect discrepancies but not classify why they occur, and the system breaks when Stripe pricing models or Salesforce custom fields change. Eru provides AI-powered probabilistic matching (not just email/domain), automatic drift classification into four categories with suggested resolutions, and zero maintenance because it adapts to schema changes automatically. Same-day setup versus months of engineering effort.
What are the most common causes of persistent revenue drift?
The three most persistent failure modes are: (1) trial-to-paid conversion gaps where self-service conversions create Stripe subscriptions with no corresponding Salesforce opportunity, (2) partial refunds not reflected in CRM ARR where Stripe credits and refunds reduce actual revenue but Salesforce deal values remain unchanged, and (3) multi-currency expansion not tracked in Salesforce where international self-service upgrades create compound discrepancies from both missing expansion and currency conversion timing differences.
Stop spending days reconciling Stripe and Salesforce manually. Book a free reconciliation audit and find out how much revenue drift is hiding in your data.
Book a reconciliation audit →