Skip to content
Riel St. Amand

Nine stacks, one platform

Security hardening and a full-stack upgrade for Schwarz Limited Partners' license-key delivery platform, then taking it from nine full per-retailer copies to one multi-tenant platform where every retailer still keeps its own database.

617known vulnerabilities resolved, measured by OSV scans before and after

  • .NET 10
  • Angular 21
  • Azure
  • multi-tenancy
  • security
  • Bicep

Schwarz Limited Partners runs a B2B platform that delivers software license keys to retailers. It has an admin portal, a portal where retailers support their customers' orders and manage keys, an API, and a set of Azure Functions. A separate ordering platform serves convenience stores. I'm the engineer on all of it. The work came in three passes, each making the next one safe: harden it, upgrade it, then change its shape.

Hardening first

I measured the security work with OSV scans before and after: 617 known vulnerabilities resolved, 153 of them in the first week. Each repository got the same treatment, with osv-scanner on source and container images alongside npm audit and dotnet list package --vulnerable. Snyk was replaced by osv-scanner plus gitleaks in every pipeline, so a new vulnerable dependency or a leaked secret now blocks the merge.

Most of it fell out of the upgrade itself. The ordering front end went from 189 findings to zero, and the framework jump alone cleared about 93% of them. The rest was pinning safe versions of transitive dependencies and deleting what nothing used. One API went from 243 packages to 92. A handful were real code fixes, from missing authorization checks to unverified webhook signatures. Adding a test suite to the ordering API took its coverage from 1.4% to 68.6% and found eight bugs along the way.

The upgrade

Nine stacks, one tier

The platform was single-tenant by replication. Every retailer got a full copy of everything: front end, APIs, Logic Apps, Azure Functions, and database. It was a low-volume B2B estate, about 500 requests a month per production API, paying for high-availability infrastructure nine times over.

The move to multi-tenant pools the compute, not the data. Each environment gets one front end, one API, one Logic App, and one Function App, all stateless and shared by every retailer. Each retailer keeps its own database, Key Vault, and blob storage. The keys are the product, so "no shared license-key database" is the rule the design is built around.

The run rate was about $8,000 a month. The consolidated target is $1,200–1,550, 80–85% lower. Tearing down resources that billing and monitoring showed were unused has already saved $1,934 every 30 days, about $23,500 a year. One lesson: a retailer we believed was gone turned out to be dormant, so the teardown now comes with a written recovery path.

All of it is defined in Bicep, 61 files across five services, deployed through Azure DevOps pipelines. Everything is off by default, and production needs explicit approval and at least two instances. The consolidation has been rehearsed end to end on one tenant in QA, with the isolation suite passing 20 of 20. Production cutover is waiting on a few administrative steps on the client's side.