Quest1

Untangling Multi-Cloud Billing for a Self-Service MongoDB Atlas Portal

A Fortune 10 healthcare group restructured its self-service infrastructure portal to attribute MongoDB Atlas costs cleanly across AWS, GCP, and Azure — replacing a hardcoded provisioning flow with a configuration-driven hierarchy that survives every future PaaS or environment change.

$ cat case-study/details.yaml
Industry
Healthcare
Service
DevOps and Automation
Partner
MongoDB
$ read /case-study/01-the-problem.md

The Problem.

The client operates an internal self-service portal that lets teams across the organization provision their own infrastructure on demand. The portal is built on a custom workflow engine, with a separate flow for each provisionable product. One of those flows handles MongoDB Atlas, and that flow had a structural billing problem.

When the MongoDB Atlas integration was first built, it was set up against a single MongoDB-paying organization — the one originally created when the client deployed Atlas on Azure. That setup was fine when Azure was the only PaaS in scope. But over time, teams across the organization began provisioning Atlas clusters on AWS and GCP through the same portal, and every one of those clusters still rolled up to the original Azure-anchored paying org.

The clusters and projects were properly segregated at the technical level — the architecture was clean. But because billing flowed through a single paying organization, finance couldn't separate MongoDB Atlas spend by underlying cloud provider. Every dollar of Atlas usage looked, on the invoice, like it came from one place. Cost attribution back to AWS, GCP, and Azure as distinct PaaS lines was effectively impossible without manual reconciliation, and the manual approach didn't scale to the portal's provisioning volume.

Underneath the billing problem sat an engineering problem. The provisioning workflow had grown an if-else ladder that hardcoded which paying org and which environment to target for each PaaS. Every change — a new environment, a new cloud provider, a new sandbox tier — meant editing code paths and shipping a new portal release. The architecture didn't have a clean place for the team to express "this PaaS uses this paying org for this environment" without touching code.

$ read /case-study/02-what-we-built.md

What we built.

Quest1 engineers re-architected the MongoDB Atlas provisioning flow to fix both problems in the same change set: cost attribution at the billing layer, and configurability at the engineering layer. The work was co-delivered alongside MongoDB consulting engineers, with a Quest1 team of two engineers and a lead, across a 15-week engagement.

Two new MongoDB-paying organizations, one each for AWS and GCP.
The original Azure-anchored paying org stayed in place for Azure-provisioned Atlas clusters. New paying orgs were established for AWS and GCP, and approximately 1,500 existing non-Azure projects were migrated across the three paying orgs. After the migration, every cluster lived under a paying org that matched its underlying PaaS — restoring clean billing attribution at the source.
A new sandbox environment.
Alongside the billing restructure, the team added a sandbox environment to the portal's provisioning options, expanding the matrix of supported environments without entangling sandbox usage with production billing.
A configuration-driven paying-org hierarchy in YAML.
The biggest engineering investment. The full mapping of paying orgs, environment-specific child orgs, PaaS providers, and the relationships between them was lifted out of code and expressed as a tree in a YAML configuration file, loaded dynamically at runtime. The provisioning workflow now reads the configuration at request time and routes each Atlas cluster to the correct paying org based on the PaaS and environment selected. This pattern eliminated the if-else ladder entirely — the code became generic, and the cluster placement logic became a configuration concern.
Adding a new PaaS or environment is now a configuration edit, not a release.
That was the structural goal: everything that used to require a code change to support a new cloud provider, a new tier, or a new paying-org rearrangement is now expressible in YAML, validated at load time, and live without redeployment.

The stack: Go for the workflow engine and APIs, React for the portal UI, MongoDB Atlas Admin APIs v1 and v2 for the orchestration layer. The portal itself remains owned and operated by the client; Quest1's contribution was the workflow re-engineering, the migration, and the configuration-driven pattern.

$ read /case-study/03-the-impact.md

The Impact.

The MongoDB Atlas provisioning flow now attributes costs cleanly across AWS, GCP, and Azure. Finance can read MongoDB Atlas spend by underlying PaaS provider directly from the invoice, without manual reconciliation. The portal version was bumped from v1.x to v2.0 to reflect the scope of the change.

The engineering posture improved as much as the billing did. The configuration-driven hierarchy means future changes to the PaaS-and-environment matrix — a new cloud provider, a new tier, a paying-org reorganization — are configuration edits rather than code releases. The hardcoded ladder the original implementation had grown is gone, and the surface area for the next change is dramatically smaller.

  • A MongoDB Atlas provisioning flow that attributes spend correctly across AWS, GCP, and Azure, separately for each provider.
  • A configuration-driven paying-org hierarchy in YAML — new PaaS providers, environments, or paying-org structures are configuration edits, not code changes.
  • A sandbox environment integrated into the portal's provisioning matrix.
  • A migration of approximately 1,500 non-Azure projects across the three new paying orgs, completed without disrupting active workloads.
  • A v2.0 release of the MongoDB Atlas portal flow, replacing the v1.x line.
$ cat metrics.summary
migrated across AWS, GCP, Azure
~1,500 projects
one per cloud provider, clean billing attribution
3 paying orgs
major-version release of the Atlas flow
v1.x → v2.0