Two transactional tables. One has customer records. The other has service orders. They're not related — no shared foreign key, no common identifier. The only thread connecting them is a free-form address field, and the addresses don't even match. "123 Main Street" in the customer table. "123 Main St" in the service orders. Sometimes "123 main st" lowercase. Sometimes with a unit number, sometimes without.
This is the daily reality of enterprise data integration. CRM has customers. Service desk has tickets. Billing has invoices. Field service has work orders. Each system was built independently, each captured addresses in its own way, and nobody enforced a canonical format. The result: the same physical site appears as 3-5 different strings across 3-5 different systems. You can't JOIN them. You can't build a customer 360 view. You can't tell a dispatcher how many service orders are open for a given site.
Try It Now
The demo below takes two synthetic transactional tables (50 customers, ~150 service orders with fuzzy address variations) and runs the full pipeline: normalize addresses, fuzzy-match via Jaro-Winkler similarity, geocode each unique customer address against the free Nominatim/OpenStreetMap API to validate it against a real-world canonical address, then ask the AI to narrate what it found.
What Just Happened
The demo did four things in sequence, none of which required you to write code or configure a data pipeline:
- Normalized addresses — lowercased, stripped punctuation, expanded abbreviations (St → Street, Ave → Avenue, Rd → Road, etc.), separated unit/apartment suffixes into a separate field so they don't pollute the primary match.
- Fuzzy-matched — for each customer address, computed Jaro-Winkler similarity against every service order address in the same city. Jaro-Winkler is the right algorithm for addresses because it gives bonus weight to common prefixes (which addresses almost always share — "123 Main" is the same in both strings even if the suffix differs). Threshold ≥0.85 = high confidence; 0.65-0.85 = ambiguous (flagged for manual review); below = no match.
- Geocoded — for each unique customer address, called the free Nominatim API (OpenStreetMap's geocoding service, no API key, CORS-enabled, rate-limited to 1 request/second per their usage policy) to fetch the canonical real-world address + latitude/longitude + place_id. This validates that the fuzzy address actually corresponds to a real location — and gives you a canonical form to use for future matching.
- Narrated — Groq analyzed the match results + geocoding success rate and wrote a 4-section executive brief: what happened, why it matters, what to expect, what to do.
The Business Case
This isn't a toy problem. It's the core of Master Data Management (MDM) — the discipline of creating a single, trusted, canonical view of entities (customers, sites, products, suppliers) across an enterprise's siloed systems. Every mid-to-large enterprise has this problem. The addresses are just the most visible symptom of a deeper issue: the systems of record don't share a canonical key, so the only way to link records across systems is fuzzy matching against a volatile free-form field.
| Without fuzzy matching | With fuzzy matching + geocoding |
|---|---|
| Each system reports its own counts — customer count from CRM, service order count from the service desk — but you can't reconcile them to a site level | One canonical site record links every customer + every service order + every invoice + every field ticket — counts reconcile automatically |
| Dispatchers see service orders one system at a time, miss the full picture per site | Dispatchers see all open service orders per site in one view, prioritized by site-level SLA risk |
| Duplicate customers enter the system (sales enters "123 Main St", service enters "123 Main Street") and nobody catches it | Fuzzy match detects the duplicate at entry time, surfaces it for review before it propagates |
| Address quality erodes silently — typos, missing units, outdated formats accumulate | Geocoding validates every address against a real-world canonical source; invalid addresses surface immediately |
| BI dashboards show "customer" counts that don't match across systems — executives lose trust in the numbers | One canonical customer count, reconciled across all systems via the matched site key |
From Demo to Production
The demo runs entirely in your browser — the fuzzy matching is client-side JS, the geocoding goes through Nominatim's public API, the AI narration goes through our Groq proxy. In production, the same pipeline runs server-side against your actual transactional tables:
- Backend-less (static JSON + GitHub Pages) — the pipeline runs as a scheduled job, writes matched + geocoded results as JSON files, the dashboard fetches them. Right for nightly batch matching of ≤10K records.
- Your existing SQL backend — the pipeline reads from your CRM / service desk / billing tables directly via a thin API, writes matched results to a canonical site table that downstream dashboards query. The canonical site key becomes the join key across all your systems.
- Managed warehouse + serverless API — Supabase / Neon / Cloudflare D1 holds the canonical site table, a scheduled serverless function runs the fuzzy match + geocoding, the dashboard queries the matched view. Zero ops on your side.
The match spec doesn't change between topologies. The runtime does.
The Honest Part
This is a concept demo, not a production MDM system. The Groq call is rate-limited to 10 per browser session. The Nominatim API is rate-limited to 1 request/second (their public usage policy) — for 50 unique addresses that's ~50 seconds, hence the progress bar. For production-scale matching (100K+ records), you'd batch-geocode via the US Census Geocoder API (no rate limit, US addresses only) or pay for a commercial geocoder (SmartyStreets, Google Places, Mapbox). The fuzzy matching algorithm itself scales linearly with the product of table sizes — for 100K × 100K records you'd want blocking (pre-filter by city/zip) to reduce the comparison count.
What we're showing is the shape: two siloed tables in, one canonical matched + geocoded view out, AI narrates the gaps. The plumbing underneath is whatever your team already runs.
Want this wired to your data?
Bring two tables that should match but don't — CRM + service desk, billing + field tickets, supplier + warehouse. We'll set up the fuzzy match + geocoding against your actual sources and show you the canonical site view before the meeting ends.
Book a Working Session