A Real-World AI Case Study
A Regenerative Story
A live system, rebuilt — without a human needing to understand a line of its code.
Jon Leahy
Staff Engineer, Operations UI
Pismo, A Visa Company
July 2026 · v1.0.0
AI, at Pismo
Go
Case Study
A Regenerative Story
A Visa Company
Let me tell you that story.
The problem — one unowned legacy service
AI as the developer — inside a structured, verifiable process.
No human reads the old code. Every request proves the match.
This is the story of getting to that goal.
And at the end, a thought to leave with: this would be worth a pilot on another real microservice.
Before we start
A case study, not a sales pitch — and fair warning: the slides make it look smooth.
It wasn't. A rough pass, like most real development — and not every edge case got pressure-tested.
Everything you'll see happened — in production, on a live system.
The one claim left to prove: that it generalizes.
Built before standards existed. It served the customer data our largest banking client used to populate their CRM — the backbone of that relationship.
Our largest banking client used it every single day — steady or growing, it never stopped.
Pismo moved its attention to other things. Nobody noticed the knowledge leaving.
And with the team went the knowledge of what actually mattered.
Retiring it had been proposed — always too much, always backlogged.
It took a change of ownership to bring it back into focus.
The change of ownership
And with Visa came a stricter bar for security.
Groovy runtime. Patching meant deep Groovy/Java surgery — and nobody on the team wrote either.
The new security regime set a deadline.
No Groovy expertise in-house: the way out was a totally new version.
The deadline moved back a couple of times — twelve months passed before the issue closed for good.
A sprawling API — the surface described everything, prioritised nothing.
The endpoints that mattered were the most complex ones.
The company's default language had moved to Go — and nobody on the team wrote Groovy or Java.
Meanwhile, on other teams
Upgrading the version for security was a major challenge in itself —
even for a well-understood service, actively maintained by its own squad.
And at the end of it: still Groovy. Still legacy.
For an unowned service with incomplete docs? That road wasn't even open.
Track one
Migrate the API
Replace Groovy with modern Go.
Like-for-like. Invisible to callers.
Track two
Move the clients off
Help consumers migrate away —
so the system could one day retire.
Fix the risk now. Retire the system eventually. Both happened.
Track one began as a standard manual rewrite — AI wasn't the plan yet.
def mapStatus(customer) {
// TODO: review this later
return customer.status == 7 ? "ACTIVE" : "INACTIVE"
}
7 — Why seven? What are the other six? Nobody could tell us.
27,000 lines of this — and none as simple as the sample above.
We reverse-engineered by hand — it's where the manual months went. The responses carried
200 properties. That's a lot of archaeology.
Access logs, tracked over time, showed which endpoints actually mattered.
10 migrated — the other 40 were never ported.
50 → 10 ported → 2–3 live by the end: track two — the client-facing teams —
kept switching endpoints off, even after cutover.
On the org chart
“Minor, at Pismo's scale”
Resourced — but minor next to the big platform services.
Incomplete docs. Day to day, a single developer.
In reality
calls a day
A bank's backbone.
Getting it wrong wasn't an option.
Low on the radar — yet failure would cost real money.
The perfect proving ground is exactly this shape.
How many services in your estate have exactly this shape?
Months in, one thing was clear: uncertainty doesn't shrink with headcount.
Not the AI — me. Behavior, not comprehension,
became the source of truth.
The running system IS the specification.
The AI references both systems — old and new — works out each difference,
runs the tests, fixes it, and loops. All the code: AI. Every merge: human-gated.
The new system: Go, hexagonal architecture, test-driven from the first line.
A fair question
Because we couldn't — AI at Pismo was patchy until early 2026.
Experimental access. Inconsistent tooling. Consistent AI arrived in January —
and this project's development stopped within a couple of months.
Enough time to finish the port. No time to design a process.
AI has been my personal passion for the last two to three years — which is how
I knew this was the only sensible route. The process took shape in hours outside work.
$ curl legacy-api/customer/38412
{
"status": "ACTIVE",
"document": "00123456000189"
}
# → Golden test case captured
Each response becomes a golden test case — quirks and all.
Status codes, zero-padded documents, magic values: captured, not explained.
The endpoint tests needed real customers to run the queries against.
$ ./probe --surname "aab" # 3-letter search minimum
→ 0 matches
$ ./probe --surname "smi"
→ 12 customers found
$ ./probe --surname "zzz"
→ search space exhausted
90 customers recovered — via the test platform's own API
The customer table was protected — unqueryable. Without it: hand-populating hundreds
of customer test cases. So an AI-written script walked
every surname from aaa to zzz instead.
Test platform, sanctioned — and yes, that's an enumeration vector. We flagged that too.
90 recovered customers, 180 tests run across our few endpoints.
The golden test corpus was live — the spec nobody ever wrote.
Like-for-like means bugs too. We weren't fixing the system.
We were replicating it exactly.
They weren't even known bugs. Only we knew they were wrong.
To our customers, they were the contract.
Testing: /customer/38412
Legacy: { status: "ACTIVE", document: "00123456000189" }
Modern: { status: "ACTIVE", document: "00123456000189" }
✓ EXACT MATCH
Testing: /customer/search?surname=smi
Legacy: 12 results, same order
Modern: 12 results, same order
✓ EXACT MATCH
Everything still needed landed within the two-month AI phase.
Customers always got the legacy answer. Always. Read-only query traffic — nothing to double-fire.
Ran for months, day and night — an autonomous feedback loop.
Edge cases no hand-written test would ever cover.
The cutover gate: zero diffs — sustained.
Started locally — landed in production: the new version ran as a shadow process, zero effect on prod.
Grafana — crystal-clear feedback on every turn.
Part ideal, part early-days — the rough version worked; this smooth is well within reach.
Unattended: capture, diffing, test generation. Human-gated: every PR merge, every canary promotion.
Bare infrastructure — so AI reverse-engineered the pipeline too.
Tagging
auto-create release tags
Codefresh
trigger CI/CD pipelines
Auto-deploy
straight to ext, scripted
ArgoCD
promote deployments
Grafana
query logs, feed back
A huge time compression: every turn of the loop went from
hours to minutes — the AI running the loop with scripts it wrote itself.
Looks easy here. It wasn't — getting these scripts reliable was its own rough, iterative slog.
12 months in a fintech, red tape included
Seven of those months were the price of not yet having the method.
Run it again: 6–8 months — no stalled port — ~1 engineer at the core,
plus a few teammate-weeks and the same review gates.
The harness isn't hardened yet — a rerun is real engineering, not a button press.
15× faster
The 3,000 ms was a fixed async fan-out window — downstreams that missed it were dropped,
and the old system returned incomplete results.
Testing felt it too: on a mismatch, the test re-ran — to rule out an incomplete legacy response.
The new system doesn't wait on a timer. Not just faster — more reliable.
The customer never noticed the switch.
Then traffic grew 2.7× — and the new system didn't blink.
Bonus: the old system's docs were incomplete. The new one shipped complete Swagger docs from day one — generated.
Full disclosure
Months of graft. Trial and error. Dead ends. Sweat and tears.
Shadow diffs meant real customer data — every logged difference went through PII redaction.
And done again? We'd reach for the strangler pattern from day one.
A rough pass, like most real development —
but it revealed a process. A change of direction.
And the methodology meant confidence at every step —
I always knew, provably, where I stood.
That's the trade.
The behavior was the specification.
The tests were the proof.
The code was just the output.
Step back
TDD. Golden master testing. Canary releases.
Shadow traffic. Code review. Iterative feedback.
Gold-standard software engineering — every practice
decades old and battle-tested.
Faster. Tirelessly. Overnight.
The discipline is what made the AI safe.
Gold-standard practice turns AI from
a code generator into a developer.
A closed, limited interaction surface — easily testable.
Fanned out to other microservices, collated one complex JSON.
The complexity was in the interface — and interfaces can be captured.
Pick a system whose behavior lives at its edges.
And that's how Pismo works: microservice-based, complexity in the interactions —
EventBridge, queues, contracts — not inside each service. The playbook should generalize — the pilot proves it.
Scope: read-path services with mirrorable traffic — write paths are a different game.
Not yet official process. Proven once — where failure costs money.
The migration is fact. That it generalizes is the one claim left to prove — a pilot turns that into fact too.
The takeaway
Same bar: 100% shadow match before cutover.
Scope includes hardening the harness into shared tooling — a permanent home
for the golden tests and contracts, so it stops being one person's tooling.
Honestly? It was a lot of work — I'm not sure I'd rush to do it again myself.
But for the company, this is the right direction.
Alone, it gives you variable results.
In a verification harness, it gives you verifiable results.
The system was rebuilt. The live system, replaced.
Security resolved — without incident.
The system is gone. The playbook remains.
As with all fintech development, this was truly a team process — many thanks:
to the team who built the core and took the endpoint slices,
the reviewers across security, architecture and governance,
and the client-facing teams whose migrations kept shrinking the surface.
And to my manager — and his — for the room to push boundaries:
staying close to the cutting edge really does work in software development.
Jon Leahy
Staff Engineer, Operations UI · Pismo, A Visa Company
One closing thought
This one was minor — and it's already gone. The key systems are still out there.
The difference now: we have a way to let them retire gracefully.
So the only question left —
which of yours goes first?
Jon Leahy
Staff Engineer, Operations UI
Pismo, A Visa Company · July 2026 · v1.0.0