LenDenClub partnered with Wohlig Transformations to test whether its credit-decisioning ML models can move from AWS to Google Cloud without changing the scores they produce. In a proof of concept, Wohlig built a scoring service around the client’s own model files and decision grid and ran it on Cloud Run in Mumbai (asia-south1). Replaying 188 loans against the client’s recorded production scores, no score crossed a decision threshold. Two of the three model families matched within 1e-12 on every compared row, and the third matched on about 99% of rows (Wohlig-reported).
Project Overview
LenDenClub is an RBI-registered peer-to-peer lending platform in India. Every loan application passes through a credit-decisioning service (”FF”) that combines several machine-learning scoring models with a decision grid that turns model outputs into an approve or decline category. The service runs on AWS today.
LenDenClub wanted to know whether this service could run on Google Cloud and give the same answers. Wohlig ran a proof of concept (PoC) between July and September 2026. It was a pilot on dev data: AWS production was left unchanged and there was no production cutover. Parity was measured on a Wohlig-built scoring service that wraps the client’s own model files and decision grid; the client’s complete application also ran on Google Cloud as a separate dev service. A separate landing-zone design engagement ran alongside it, for a governed Google Cloud environment.
The Challenge
Credit Decisions Cannot Drift: The service decides with three model families and a threshold grid. A small, silent shift in a score can push a loan across a threshold and change a lending outcome, so “approximately the same” was not an acceptable test.
An Undocumented, Fragile Model Stack: The models were built on three different library stacks. The client’s four requirements files silently overrode one another, and conventions such as how special bureau codes are treated lived in code, not in documents. Nobody could prove the models would score the same anywhere else.
A Scorecard That Hides Defects: One model family is a bucketed scorecard. A random sample of loans sits in the middle of buckets, where defects do not show. A naive parity test could pass while hiding errors that matter at the thresholds.
A Hybrid Data Path: The service depends on AWS-hosted databases and on third-party data and bureau services. Scoring from Google Cloud meant solving connectivity as well as compute.
No Standard Landing Place: Migrated workloads needed a repeatable, governed Google Cloud environment to land in.
Key Objectives
Same Scores: Show that Google Cloud reproduces the client’s recorded production scores on real loan data, with zero tolerance for threshold crossings.
The Client’s Own Models: Use the client’s own model files, fingerprinted, so any difference can be attributed to the platform and not to a rewrite.
Production-Shaped Foundation: Build the PoC as the non-production tier of the target architecture, so a later move to production is a promotion and not a rebuild.
Reproducible and Auditable: Pin the dependencies, fingerprint the models and keep a manifest of every validation run.
A Governed Landing Zone: Design the landing zone and Terraform package for the client’s Google Cloud environment.
The Solution: Prove It, Don’t Just Port It
What Was Built
Wohlig built a thin scoring service that loads the client’s four model files and applies the decision-grid logic, and deployed it on Cloud Run in asia-south1 as an authenticated service. SHA-256 fingerprints of every model file are re-verified at start-up, so a swapped or corrupted model stops the service from starting. The full dependency set (about 80 packages) is pinned, and a zero-traffic revision is used to prove a runtime change before it is adopted. Terraform was applied for the first deployment, after which services were managed with command-line tooling. A six-gate build pipeline (traceable tag, credential scan, decision-grid test, start-up check and more) is defined as code and was tested on control samples; images were built locally and pushed to Artifact Registry.
The client’s complete application, with its code unmodified, also ran as a separate dev service on Cloud Run, with an added Wohlig component for bureau lookups. It reaches the AWS-hosted dev databases over the existing VPN.
The Parity Instrument
Validation ran inside the scoring service. It accepts an extract of loans, scores each one, compares the result with the client’s recorded production scores and returns a report with per-loan drill-down. It refuses incomplete inputs or non-overlapping loan sets, and runs structural checks before scoring. Cut-off crossings fail at zero tolerance. Every run writes a manifest.
Model Families and Decision Grid (4 Items, 4 Fingerprinted Model Files)
1. Scorecard Model
What it decides: A bucketed scorecard that gives a first-stage score for an applicant.
On Cloud Run (Wohlig-reported):
188 loans evaluated.
186 rows matched within 1e-12.
Two rows differed, with the differences traced to an input field in the reference extract.
Zero decision-threshold crossings.
2. Bureau-Data Model
What it decides: A classifier that estimates repayment probability from credit-bureau-derived inputs.
On Cloud Run (Wohlig-reported):
177 loans evaluated.
All rows matched within 1e-12.
Zero decision-threshold crossings.
3. Second-Stage Model
What it decides: A classifier that re-assesses applications routed to a further check.
On Cloud Run (Wohlig-reported):
31 loans evaluated.
All rows matched within 1e-12.
Zero decision-threshold crossings.
4. Decision Grid
What it decides: Rule logic that maps model outputs to approve or decline categories.
Validation results:
Reproduced in local checks against the client’s recorded scores.
End-to-end routing was not verified against production.
Earlier local replays covered several hundred loans per family across the extract deliveries, and the residual differences there traced to the same input field.
Google Cloud Components Used (8)
Cloud Run services; Artifact Registry; a build pipeline defined as code (six gates; not run on Cloud Build); Terraform (applied for the first deployment); a dedicated least-privilege runtime identity (created; the swap is pending a client grant, and the PoC ran under an interim broader identity); Cloud IAM invoke control; Secret Manager (dev configuration and database credentials); and direct VPC egress on the shared subnet with the existing AWS-Google Cloud VPN.
Data Sources Touched (7)
A frozen loan extract (non-PII, surrogate loan IDs); a loan-origination dev database; a scoring-features dev database; an alternate-data provider API; a device-signal provider API; a credit-bureau parser service; and AWS analytics, search and storage services (roadmap). Databases stay on AWS for now and are reached over the existing VPN, at the client’s choice.
Landing-Zone Design (8 Component Groups)
Folder hierarchy; naming and labelling standard; Terraform bootstrap and modules; group-based IAM with break-glass; organisation-policy guardrails; hub network with Network Connectivity Center; central logging; and encryption-key and resource-location policy.
This was a separate design proof of concept: the design and Terraform package were handed over, and a technical findings and remediation plan was prepared. It is not described here as applied.
Key Benefits & Results
Previous: No proof the models score identically off AWS.
Our Solution: Replay of recorded production scores through the Cloud Run service.
Result: Zero threshold crossings on 188 loans; two families within 1e-12 on every row, the third on about 99% of rows (Wohlig-reported; the client confirmed the values matched at PoC sign-off).Previous: Conflicting requirements files.
Our Solution: Full dependency set pinned, model files fingerprinted.
Result: About 80 packages pinned; a changed model fails at start-up.Previous: Random sampling would hide scorecard defects.
Our Solution: Instrument self-tests on synthetic and recorded data.
Result: Five out of five planted defects caught; the same 200-row test file scored twice gave identical results (instrument self-tests, run locally).Previous: Library and platform effects mixed together.
Our Solution: Each source of drift measured separately.
Result: Zero changed values across every comparison run; 22 output fields compared between two service builds with zero mismatches (Wohlig-reported).Previous: Dev data path untested.
Our Solution: Dev databases reached over the VPN.
Result: About 290 scoring runs on dev data in September (150 / 96 / 44 by family). One family was compared with recorded production values on a small subset; the other two could not be compared to production.Previous: No governed destination.
Our Solution: Landing-zone design and Terraform package.
Result: Handover package delivered (designed; not described as applied).
What this PoC does not cover: The data path is not fully validated end to end. Live scoring works for historical loans with retained bureau reports, about 8% of the dev population, and not for new applications. Database reachability from Cloud Run was being resolved on the client side at sign-off. Other limitations include vendor API access for new applications, routing parity—which needs a recorded routing field from production—the runtime identity swap, and load testing. Latency, load, accuracy and cost have not been measured and are not claimed.
Technical Innovation
Proving “No Threshold Crossed” for a Bucketed Scorecard: The test was designed to target loans near the grid thresholds and the bucket edges of the most sensitive variables, where a single flip is worth many points. Coverage of those loans in the delivered extracts is still to be confirmed.
Separating Sources of Drift: Library upgrade, Python version and hardware effects were each measured on their own. A last-bit hardware effect (about 2e-16) moves between runs, so results are quoted as “within 1e-12” and never as “bit-identical.”
Hidden Conventions Recovered: Rules that lived only in code, such as how special bureau codes are treated as missing, which probability column each family uses and a threshold sheet read on every call, were found, documented and tested.
A Parity Instrument That Fails Loudly: Server-side comparison, refusal modes, planted-defect proof and per-loan forensics. Early extract deliveries had defects, and the instrument surfaced them: mismatches traced to the reference extract and not to the platform.
Integrity Built Into a Credit Endpoint: Start-up model verification, a credential-scan gate defined in the build pipeline, and authenticated-only invocation.
Wohlig’s Approach
Read the decision path – Map the models, the grid and the routing, and recover the conventions hidden in the code.
Define the reference – Work with the client on an extract of recorded production scores and the features behind them, and iterate until it is clean.
Wrap the client’s own model files – A thin scoring service with fingerprinted models and a pinned dependency set.
Deploy as the non-production tier of the target – Terraform for the first deployment, Artifact Registry and an authenticated Cloud Run service.
Prove parity, then try to break the proof – Replay, planted defects, repeat runs and drift separation.
Connect and hand over – Dev databases over the existing VPN, scoring runs on dev data, test access, documentation, weekly reports and a six-stage migration roadmap.
Where it stands: PoC complete on dev data. The remaining models and a production cutover plan are the proposed next phase.
About LenDenClub
LenDenClub is a Mumbai-headquartered peer-to-peer lending platform regulated by the RBI as an NBFC-P2P. Founded in 2015, it connects retail lenders with borrowers through a fully digital experience.
About Wohlig Transformations Pvt. Ltd.
Founded in 2016, Wohlig Transformations is a Google Cloud Premier Partner and a CNCF partner, with 40+ Google Cloud certifications across its team. Offices in Mumbai (HQ), Toronto, London, Bangalore and Delhi. Practices: GenAI, Cloud Migration and DevOps.
Detailed Case Study Presentation:


