Two-part series. Gart Solutions covers technical measures; Avitar Legal covers organisational measures.
The gap between "we encrypt" and proof that you do
GDPR Article 32 asks for technical and organisational measures. Most companies treat it as one paperwork task. It is really two tasks. A policy covers the organisational half. The technical half is only covered when your cloud account, pipelines and logs are actually configured.
In January 2026 the French regulator showed what happens when the two halves drift apart.
The CNIL fined France Travail €5 million after a breach. Its findings named weak authentication, access rights "defined too broadly" and logging that could not "detect abnormal behaviour". The key line: most of the needed measures had been identified in impact assessments but "had not actually been implemented".
The paperwork existed. The configuration did not.
This article is the technical half of a two-part series. Gart Solutions covers what has to be configured: encryption, identity and access, logging, backups and testing in the cloud. Our partners at Avitar Legal, a law firm focused on data protection for IT companies, cover the organisational half: policies, DPIA and data mapping. If you need someone to check both halves against your real environment, start with a GDPR compliance audit or Compliance consulting services.
Who this is for: CTOs, heads of infrastructure and DevOps leads who have a privacy policy and want to know whether their AWS, Azure or GCP setup can back it up.
What GDPR Article 32 actually requires
Article 32 does not list mandatory controls. It requires a level of security "appropriate to the risk", judged by the state of the art, the cost of implementation and the nature, scope, context and purposes of processing. The full text is on EUR-Lex. It names four examples in Art. 32(1):
(a) Pseudonymisation and encryption of personal data.
(b) The ability to ensure ongoing confidentiality, integrity, availability and resilience of processing systems and services.
(c) The ability to restore availability and access to personal data in a timely manner after a physical or technical incident.
(d) A process for regularly testing, assessing and evaluating the effectiveness of the measures.
Art. 32(2) names the risks to weigh: accidental or unlawful destruction, loss, alteration, unauthorised disclosure of or access to personal data. Art. 32(3) lets you use an approved code of conduct or certification as one element of proof. Art. 32(4) requires that anyone with access processes data only on instructions.
Three things matter for engineering teams:
The duty applies to processors too. If you run infrastructure for clients, Article 32 is your obligation, not just theirs.
"State of the art" moves. A setup that was acceptable in 2019, such as long-lived access keys or no MFA on admin accounts, may not be acceptable now.
(b), (c) and (d) say "ability" and "process". You show an ability by running it: a restore that worked, an alert that fired, a test with a date on it. A paragraph in a policy does not show any of that.
The test: document or configuration?
Ask one question of each measure: if an auditor asks for proof, do you hand over a file or open a console? If the proof is a decision, a rule or a role, a document covers it. If the proof is a system state, a log entry or a test result, only configuration covers it.
Most Article 32 measures need both. The document sets the rule. The configuration enforces it and leaves evidence. A gap on either side is a finding.
Art. 32 area
What the document covers
What only configuration covers
Evidence an auditor accepts
Encryption (32(1)(a))
Encryption policy, key ownership, which data classes need it
KMS keys, encryption at rest on every store, TLS 1.2+ in transit, key rotation
Config export or CSPM report showing 100% of stores encrypted; key rotation settings
Pseudonymisation (32(1)(a))
Which fields are pseudonymised and who may re-identify
Tokenisation or hashing in the pipeline, separated key storage
Schema of non-production data; access policy on the mapping table
Access control (32(1)(b))
Access policy, roles, joiner-mover-leaver process
SSO, MFA, least-privilege IAM roles, no shared or long-lived keys
IAM report, MFA coverage, last access review with date and sign-off
Network and secrets (32(1)(b))
Architecture standard
Private subnets, security groups, secrets manager, no secrets in code
Network config, secret-scanning results in CI
Logging and monitoring (32(1)(b), Art. 33)
Logging policy, retention period, incident response plan
Audit trails enabled, central log store, immutability, alerts on abnormal access
Sample log entries, retention settings, an alert that fired and was handled
Backup and recovery (32(1)(c))
Backup policy, RTO and RPO targets, DR plan
Automated backups, cross-region copies, immutable vaults
Dated restore test with measured RTO and RPO
Regular testing (32(1)(d))
Testing schedule, owner, method
Policy-as-code, drift detection, vulnerability scans, pentests
Scan history, pentest report, remediation tickets closed
Staff instructions (32(4))
Confidentiality terms, training, need-to-know rules
Role scoping that limits what each person can see
Training records plus IAM scope matching the role
The last row is the reverse case. Article 32(4) is mainly organisational. Configuration only backs it up. That is where Avitar Legal's half of the series picks up.
The sections below go through the configuration column, area by area.
Encryption and pseudonymisation in the cloud
Encryption is the measure most often "covered" by a sentence and least often checked. Cloud providers encrypt many services by default, but not all of them, and not always with keys you control. Under the AWS shared responsibility model, the provider secures the cloud itself. You secure what you put in it, including data encryption and identity settings. Azure and Google Cloud use the same split.
What to configure
At rest, everywhere personal data lands. Databases, object storage, block volumes, snapshots, backups, queues, data warehouses and log stores. Snapshots and old buckets are where gaps usually hide.
Customer-managed keys for sensitive data. Use KMS, Key Vault or Cloud KMS with key policies that separate key admins from data users. Turn on automatic rotation.
In transit. TLS 1.2 or higher on public endpoints and between services. Enforce it with policy (for example, deny unencrypted S3 requests), not only with good habits.
Pseudonymisation outside production. Developers and analysts rarely need real names or emails. Tokenise or hash identifiers before data reaches staging, BI or ML pipelines. Keep the re-identification key in a separate account or vault.
The document's job here
The policy says which data classes need customer-managed keys, who owns the keys and what happens if a key is compromised. It cannot say whether the bucket created last Tuesday is encrypted. A policy-as-code guardrail can, and it can block the bucket before it exists.
Confidentiality and integrity: identity, network and secrets
The France Travail case turned on access: advisers could see records of people they did not support, and that widened what attackers could reach with one stolen login. Your access policy probably already says "need to know". The question is whether IAM says the same thing.
What to configure
One identity source. SSO through Entra ID, Okta or Google Workspace for consoles, CI/CD, databases and internal tools. No local admin users that survive offboarding.
MFA on every human account, and phishing-resistant MFA for admins and anyone who can export personal data.
Least privilege by role. Start from deny, grant per role, and scope production data access to the people who handle it. Our guide to the least privilege access model shows how to roll it out without blocking engineers.
No long-lived keys. Replace static access keys with short-lived roles and workload identity. Store the rest in a secrets manager; for clusters, see Kubernetes secrets management.
Network segmentation. Databases with personal data sit in private subnets, reachable only from the services that need them. No public database endpoints.
Integrity controls. Signed builds, protected branches and RBAC in pipelines, so nobody can push code that reads personal data without review.
The document's job here
The document defines roles and the joiner-mover-leaver process. Configuration enforces them. The bridge between the two is the access review: a dated record that someone checked who has access and removed what was no longer needed. Here is how to run a user access review without spreadsheets.
Logging and monitoring: the measure regulators now name
Article 32 does not use the word "logging". Regulators read it in anyway, because without logs you cannot show ongoing confidentiality and integrity, and you cannot meet the 72-hour breach notice in Article 33. You cannot report what you cannot see. In the France Travail decision, inadequate logging was one of three named failings.
The CNIL's 2021 recommendation on logging is the most concrete guide available. It asks controllers to log access, creation, modification and deletion of personal data, with the user ID, timestamp and device. It recommends keeping these logs for six months to one year in most cases, and analysing them automatically to spot misuse.
What to configure
Turn on the audit trails. CloudTrail (including data events for buckets with personal data), Azure Activity and resource logs, GCP Cloud Audit Logs with Data Access logs. Data access logging is often off by default because it costs money.
Log at the application layer too. Cloud logs show that a service reads a table. Only the app knows that support agent X opened customer Y's profile. That is the event a regulator asks about.
Centralise. Ship logs to one account or workspace that application teams cannot edit.
Make logs tamper-evident. Object lock, write-once storage or log-file integrity validation. A log an attacker can delete is not evidence.
Set retention on purpose. Match the period in your policy, for example 12 months hot or warm, then delete. Logs are personal data too, so keeping them forever is its own GDPR problem.
Keep personal data out of debug logs. Mask emails, tokens and IDs in application logs. A verbose log file is a common source of leaks.
Alert on abnormal access. Bulk exports, access outside working hours, one account reading thousands of records, MFA disabled, logging turned off. Route alerts to someone on call, with a runbook.
The document's job here
The logging policy sets what is logged, who reads it and how long it is kept. The incident response plan sets who decides, within 72 hours, whether to notify. Configuration produces the data both depend on. For the tooling side, see our pieces on what observability means in practice and on cybersecurity monitoring, or our IT monitoring services.
Availability and resilience: a backup is not a restore
Art. 32(1)(c) asks for the ability to restore personal data "in a timely manner". A backup policy describes the intent. Only a restore test shows the ability. Losing data counts as a personal data breach too, even when nothing was stolen.
What to configure
Automated backups for every store with personal data, including managed databases, object storage and SaaS data you depend on.
Copies in a separate account and region, so one compromised admin account or one regional outage cannot take out production and backups together.
Immutable backups. Vault lock or object lock protects against ransomware that targets backups first.
Encrypted backups with separate keys, covered by the same encryption checks as production.
Restore tests on a schedule. At least quarterly for critical systems. Record the date, what was restored, how long it took and how much data was lost. Those are your real RTO and RPO.
Deletion that reaches backups. Erasure requests and retention limits apply to backups as well. Document how expired data ages out of them.
The document's job here
The document sets RTO and RPO targets, ranks systems by priority and assigns the DR owner. The configuration and the dated test report prove you can hit those numbers. For how recovery works in practice, see our complete guide to DRaaS, or talk to us about disaster recovery as a service.
Regular testing: turning "ongoing" into evidence
Art. 32(1)(d) is the clause that ties everything together. It asks for a process for regularly testing and evaluating whether the measures work. A yearly pentest alone does not meet that bar in a cloud estate that changes every day.
What to configure
Policy-as-code in CI/CD. Checks in Terraform or Bicep plans that block unencrypted storage, public buckets, open security groups and missing logs before deployment.
Continuous posture checks. AWS Security Hub, Microsoft Defender for Cloud, Google Security Command Center or an open-source CSPM, mapped to the controls in your policy.
Drift detection. Alerts when someone changes production by hand and it no longer matches code.
Vulnerability scanning of images, dependencies and hosts, with fixed deadlines by severity.
Penetration tests at least yearly and after major changes, with retests of the findings.
Tracked remediation. Every finding becomes a ticket with an owner and a date. A closed ticket is evidence. An open one is a known risk you have accepted, so record that decision.
The document's job here
The document sets the schedule, the owner and the threshold for escalation. The tooling runs the tests and keeps the history.
ENISA's Handbook on Security of Personal Data Processing is a useful bridge here: it links risk levels to concrete measures, which helps justify why a control is in or out of scope. For a structured starting point, see our GDPR compliance checklist.
Where the document still decides: organisational measures, DPIA and data mapping
Configuration without a document fails too, just less visibly. You cannot set the right retention period, encryption scope or access roles until you know what personal data you hold, where it flows and how risky the processing is. Those answers come from the organisational side:
Data mapping and the record of processing (Art. 30) tell engineering which systems hold personal data. That is the scope for every control above. An unmapped data store is an unencrypted, unlogged data store waiting to happen.
DPIA (Art. 35) sets the risk level that Article 32 scales to. It decides whether you need customer-managed keys, field-level encryption or 12-month log retention, rather than the defaults.
Policies, processor contracts (Art. 28), training and staff instructions (Art. 32(4)) define who may do what. Configuration then enforces it.
The France Travail case shows the failure mode in the middle: the DPIA identified the measures, and nobody turned them into configuration. The fix is a handover. Each measure in the DPIA gets a technical owner, a configuration target and an evidence source.
Our partners cover this side in detail in Avitar Legal's companion article on GDPR Art. 32 organisational measures, DPIA and data mapping. Read the two together: theirs tells you what to decide, ours tells you how to enforce it.
10-point technical check for Article 32
If you can answer "yes, and here is the evidence" to each item, your technical half is in good shape.
Every store holding personal data is encrypted at rest, including snapshots and backups.
Sensitive data uses customer-managed keys with rotation on.
TLS is enforced by policy, not just used.
Non-production environments use pseudonymised or synthetic data.
All human access goes through SSO with MFA; no long-lived access keys remain.
An access review was completed in the last quarter, with sign-off.
Audit and data-access logs are on, centralised, tamper-evident and kept for a set period.
Alerts on abnormal access reach someone on call.
A restore test in the last quarter met the documented RTO and RPO.
Policy-as-code and posture scans run continuously, and findings are tracked to closure.
How Gart Solutions helpsGart Solutions runs compliance audits and security audits for cloud environments on AWS, Azure and GCP. We compare what your policies say with what your accounts are actually configured to do, and hand you a prioritised fix list with the evidence an auditor will ask for.Where legal and organisational work is needed, we work alongside Avitar Legal, so both halves of Article 32 are checked against each other.Book a compliance audit
Sources
Regulation (EU) 2016/679 (GDPR), EUR-Lex
CNIL: Data breach, France Travail fined €5 million (29 Jan 2026)
ENISA: Handbook on Security of Personal Data Processing (2018)
AWS shared responsibility model
Short answer
Cloud unit economics measures what your cloud spend buys, per unit of business value. For most SaaS companies, that unit is a customer. To calculate cost per customer, take your production cloud cost (amortized, credits excluded), add each tenant's direct costs to a fair share of shared costs, and divide by active paying customers. Then compare the result with revenue per customer. The median private B2B SaaS company spends 5% of ARR on hosting. If you're well above that, the calculation shows you where the money goes.
Most SaaS teams can tell you their AWS bill to the dollar. Far fewer can tell you what it costs to serve one customer, or which pricing tier is quietly losing money on infrastructure. That second number is what cloud unit economics gives you. It's also what turns "the bill went up 30%" from bad news into a question you can answer: did customers grow faster than that, or not?
This guide shows how to calculate cost per customer step by step. It includes a worked example by pricing tier, benchmarks to judge the result against, and a calculator for your own numbers. It's based on the work our AWS cost optimization consulting team does with SaaS clients, including two projects where unit costs fell by roughly 80%.
5%
median hosting spend as a share of ARR at private B2B SaaS companies
SaaS Capital, 2026 survey
~50%
of cost of revenue went to committed cloud spend at public software companies
a16z, 2021 analysis
~78%
lower monthly infrastructure run-rate for FluentU
Gart case study
~80%
lower cost per video hour for Jewelry AI's vision pipeline
Gart case study
How to read the numbers in this article
Survey benchmarks come from SaaS Capital's 2026 survey of more than 1,000 private B2B SaaS companies and from a16z's 2021 analysis of public software companies. Both links are in the text.
The worked example uses a hypothetical company so that every step can be shown. Its numbers are illustrative.
Benchmark bands (under 3%, 3–7%, 7–12%, over 12%) are our own interpretation, built around the survey median. Gart results come from client billing data, as published on our case study pages. Last checked: October 2026.
In this article
What is cloud unit economics?
How to calculate cost per customer
Worked example
Benchmarks
Calculator
FluentU case
Jewelry AI case
Reduce your AWS bill
Maturity model
What is cloud unit economics?
Cloud unit economics links cloud spend to the business output it produces. Instead of reporting "we spent $24,000 on AWS this month", you report "it cost $4.20 to serve a customer, against $170 of revenue from that customer". The FinOps Foundation treats this as a core capability. In its framework, unit economics is how organizations connect technology spend to the value of what they deliver.
Cost per customer = (direct costs + allocated shared costs) ÷ active paying customers
Unit margin = revenue per customer − cost per customer · Hosting % = cloud cost ÷ revenue
The total bill can't tell you whether you're getting more efficient, because it grows whenever the business grows. A unit cost can. If spend rises 30% and customers rise 60%, efficiency improved. If customers are flat and cost per customer keeps rising, something in the architecture is scaling the wrong way. That's usually an oversized database, logs with no retention, or a non-production estate as large as production.
Cost per customer is the right starting unit for most SaaS businesses. But if your customers vary a lot in size, add a unit of work next to it:
SaaS profileUsual top cost driver on AWSBest unit metricFirst lever
B2B workflow / CRUD appRDS or Aurora, often Multi-AZ with Provisioned IOPSCost per customerDatabase rightsizing, gp3 storage, Reserved Instances
Content and EdTech platformsDatabase plus storage and CDNCost per active learner or userData lifecycle, CDN caching, database design
Data and analytics SaaSPipeline compute, warehouse queries, S3Cost per GB processedSpot for batch, storage tiers, query tuning
Video and AI visionGPU or CPU compute for processingCost per video hour or per inferenceSpot capacity, batch scheduling, right GPU class
Multi-tenant on KubernetesNode overprovisioning, NAT and data transferCost per tenant (namespace)Bin-packing, autoscaling, VPC endpoints
How to calculate cost per customer in 6 steps
You can get a rough number from last month's invoice in five minutes: bill divided by customers. It's a useful first benchmark, but a poor basis for decisions, as the worked example below shows. These six steps turn it into a number you can price and plan with.
Step 1
Choose the right cost basis
The same bill can produce four different unit costs, depending on which view of it you use. Pick one basis and keep it consistent month to month:
ItemRecommendationWhy
Savings Plans and Reserved InstancesUse net amortized cost in Cost Explorer or the CURUnblended cost puts upfront fees into a single month, which makes your unit cost jump and then collapse.
Promotional creditsExclude themCredits expire. If your unit cost only looks healthy because of credits, the problem shows up later.
Support planInclude as a shared costBusiness or Enterprise Support scales with spend, so it's a real cost to serve.
Marketplace softwareInclude if the product depends on itA third-party database or security tool billed through AWS is part of what it costs to serve customers.
TaxExcludeKeeps comparisons clean across regions and entities.
Step 2
Separate production from non-production
Development, staging, CI and demo environments are an engineering cost, not a cost to serve. Keep them out of the production unit cost, and track them as their own ratio (non-production as a share of the total). Separate AWS accounts under AWS Organizations give you the cleanest split. If you can't use separate accounts, enforce an environment tag in Terraform. On bills that have never been split, non-production is often a bigger share than the team expects.
Step 3
Split direct costs from shared costs
A direct cost belongs to one tenant or one pricing tier, such as a dedicated database for an enterprise customer or a tenant-specific S3 bucket. Tag these with tenant_id or customer_tier and activate those tags as cost allocation tags. Everything else is shared: the main database, load balancers, observability, NAT gateways, support.
Shared Kubernetes and ECS clusters used to be a blind spot. On AWS, you can turn on split cost allocation data, which divides each instance's cost across the pods or tasks that ran on it, based on CPU and memory use. If you run one namespace per tenant, that makes container costs directly attributable.
Step 4
Allocate shared costs with a usage driver
Divide the shared pool in proportion to a driver that reflects actual consumption:
Tenant's shared cost = (tenant's driver usage ÷ total driver usage) × shared cost pool
Good drivers: API requests, compute seconds, GB stored, GB transferred. Weak drivers: seat count, revenue share.
Avoid allocating by revenue. It makes every customer look equally profitable, which is exactly what this exercise is meant to test. If one driver doesn't fit everything, split the pool: allocate database costs by queries or storage, and network costs by GB transferred. AWS Cost Categories can apply these split rules automatically.
Step 5
Divide by the right customer count
Use active paying customers in the same month as the cost data. Treat free-tier users as an acquisition cost: put their share of the infrastructure under marketing, or report "cost per free user" separately. Don't fold them into the paying-customer denominator. For usage-heavy products, divide the same cost pool by your unit of work as well, such as video hours or GB processed.
Step 6
Compare against revenue, and track it monthly
A unit cost only means something next to unit revenue. Calculate the margin per customer and hosting as a percentage of revenue, by pricing tier. Then put it on a monthly dashboard: query the Cost and Usage Report in Athena, join it with MRR and customer counts from your billing system, and alert on any month-over-month swing above about 15%. We describe how we run this rhythm with clients in our FinOps cloud cost management experience.
Worked example: cost per customer by pricing tier
Here's the full calculation for a hypothetical B2B SaaS company with three pricing tiers, 1,520 paying customers and $258,500 MRR. Its net amortized AWS bill is $24,000 a month. Non-production is $4,000, which leaves $20,000 in production. Of that, $8,000 is direct (dedicated databases and storage for Growth and Enterprise tenants) and $12,000 is shared, allocated by API request volume.
From total bill to cost per customer
Total bill
$24,000
Non-prod $4,000
Direct (tagged)
$8,000
Shared, by API calls
$12,000
Starter · 1,200 customers · $3,000
$2.50 per customer · 5.1% of revenue
Growth · 300 customers · $7,400
$24.67 per customer · 6.2% of revenue
Enterprise · 20 customers · $9,600
$480 per customer · 12.0% of revenue
Hypothetical example. Production cost $20,000 = $8,000 direct + $12,000 shared.
How the $24,000 bill flows down to cost per customer for each tier.
TierCustomers × priceDirectShared (API share)Total costCost per customer% of revenue
Starter1,200 × $49$0$3,000 (25%)$3,000$2.505.1%
Growth300 × $399$2,000$5,400 (45%)$7,400$24.676.2%
Enterprise20 × $4,000$6,000$3,600 (30%)$9,600$480.0012.0%
Total1,520 · $258,500 MRR$8,000$12,000$20,000$13.16 (blended)7.7%
Three things stand out, and none of them is visible from the total bill:
The naive number misleads. $24,000 ÷ 1,520 = $15.79 per customer. That's six times what a Starter customer actually costs, and a thirtieth of what an Enterprise customer costs. Any pricing decision based on it would be wrong for every tier.
The average hides the problem tier. Blended hosting is 7.7% of revenue in production (9.3% fully loaded), just above the median. But Enterprise sits at 12%, because its dedicated databases were sized for peak load and never reviewed. That's where the optimization work belongs. Starter, at 5.1%, is fine.
It changes the commercial conversation. With $480 a month in infrastructure per Enterprise customer, the company knows its floor price for discounts and can make dedicated infrastructure a paid add-on instead of a free default.
Cloud unit economics benchmarks for SaaS
There's no universal "good" cost per customer. A $20-a-month SMB tool and a $50,000-a-year enterprise platform will never have similar figures. What does carry across companies is the ratio of cloud spend to revenue. SaaS Capital's 2026 spending benchmarks for private B2B SaaS companies survey more than 1,000 companies and put median hosting at 5% of ARR, unchanged from the year before, with a further 4% for DevOps.
At scale, cloud becomes the largest item in COGS. In The Cost of Cloud, a Trillion Dollar Paradox, a16z estimated that committed cloud spend was about 50% of cost of revenue at public software companies that disclose it. That's 2021 data, but the conclusion still holds: every point of hosting spend is a point of gross margin.
Hosting as % of revenueWhat it usually meansWhat to do next
Under 3%Lean. Either the product is light, or FinOps is already mature.Protect it: budgets, anomaly alerts, monthly unit-cost review.
3–7%Around the median for B2B SaaS.Hygiene and commitment coverage. Expect 10–25% savings, not a redesign.
7–12%Above median. Common after fast growth, or with a database-heavy design.Find the one or two services driving the cost. Rightsizing plus Savings Plans or Spot usually closes most of the gap.
Over 12%A structural issue is likely, unless the product is video, AI or data processing at its core.Architecture review: database design, managed-service premiums, where workloads run.
The bands are Gart's interpretation, built around the SaaS Capital median. They are not survey results. Apply them per pricing tier as well as to the blended number.
Cost per customer calculator
Enter four numbers from last month's bill and your billing system. The calculator shows your cost per customer and hosting ratio against the 5% median. It then estimates what each type of fix would save, using savings rates from real Gart projects. For a per-tier view, run it once for each tier, using that tier's allocated cost.
Calculate your cost per customer
Everything is calculated in your browser. Nothing is sent anywhere.
Monthly cloud bill (USD)
Net amortized, credits excluded
Non-production share (%)
Staging, dev, CI, demo environments
Paying customers
Active accounts billed this month
Monthly recurring revenue (USD)
MRR, or ARR ÷ 12
Cost per customer–fully loaded, per month
Production only–per customer, per month
Hosting % of revenue–median B2B SaaS: 5%
Gap to median–per year
Enter your numbers to see where you stand.
What could each type of fix save?
Main lever
Hygiene and containerization (~12%, Entertainment SaaS case)
Commitments + Spot (~25%, Datamaran case)
Database and architecture redesign (~50%, estimate)
Structural fix incl. migration (~78%, FluentU case)
Custom percentage
Custom reduction (%)
New monthly bill–
New cost per customer–
New hosting %–
Annual savings––
Case percentages are what those specific clients achieved, not a promise for your bill. The 50% option is an illustrative middle scenario, not a case result. Savings from different levers don't simply add up, because each one applies to a smaller remaining bill.
Want your unit economics calculated for you?
Our engineers review your Cost Explorer and CUR data with read-only access. You get cost per customer by tier and the services driving it.
Request a cost review
Case 1 · EdTech SaaS
FluentU: how fixing the database cut cost per customer by about 78%
FluentU is a language-learning platform that teaches through authentic video content. It runs a web app, native mobile apps, a Chrome extension, a WordPress blog and a set of scheduled workers. After years of growth, its AWS footprint included multiple app servers behind load balancers, several RDS databases (main platform, blog and demo), ElastiCache, CloudFront, S3, NFS shares and SQS.
Verified Cost Explorer data put the baseline at $9,318.15 a month. The service breakdown was the real finding. RDS alone cost $6,071.87, or 65.16% of the bill. The main Multi-AZ database class accounted for $2,035.58, Provisioned IOPS for $1,400, a second Multi-AZ class for $1,100.73 and PIOPS storage for $625. In unit-economics terms, two-thirds of the cost of serving every learner was a database configuration. Rightsizing a few EC2 instances would never have fixed that.
StageMonthly run-rateChange in cost per customer*
AWS baseline$9,318–
First month after cutover (AWS only, cleanup in progress)$4,690−49.7% on AWS
Combined run-rate: optimized Hetzner (~$1,429) + AWS backups ($600–630)$2,029–2,059~−78%
After AWS backup retention expires$1,599–1,619~−83%
*With the same customer base, cost per customer falls by the same percentage as the run-rate. FluentU's customer count isn't public, so no dollar figure per customer is shown. Source: FluentU case study, AWS Cost Explorer and Hetzner billing. Annualized savings: about $87,100–87,500.
FluentU: monthly infrastructure spend (USD)
AWS baseline
RDS $6,072 (65%)
Other $3,246
$9,318
Combined today
~$2,044 (Hetzner ~$1,429 + AWS backups ~$615) −78%
After retention
~$1,609 −83%
Primary hosting
Remaining AWS (backups, legacy)
Source: Gart Solutions FluentU case study. "Combined today" uses the midpoint of $2,029–2,059.
The savings didn't come from one switch. Over six months, the team designed the target environment, rebuilt it after schema validation found 1,179 missing indexes across 1,474 tables, and ran AWS DMS with change data capture. They aborted the first cutover when CDC latency rose, then succeeded on the retry. After cutover, Hetzner itself was trimmed by another ~$601 a month (29.6%) through app, cron and cache rightsizing, plus orphan cleanup. Moving off AWS was right for this workload. It isn't right for everyone, and our Hetzner vs AWS comparison covers the trade-offs.
Unit-economics signal from this case: if one AWS service makes up more than half of your cost per customer, start with an architecture review, not a tactics checklist. In our experience, that service is usually the database.
Case 2 · AI vision
Jewelry AI: unit economics for AI workloads, measured per video hour
A Thai jewelry manufacturer wanted AI to analyze worker activity across 200–250 workstations, so it could find production bottlenecks. Each workstation records about 9 hours a day. That's around 1,800 hours and 2 TB of video every day, processed overnight with feature extraction and classification.
This project ran on Azure, not AWS. We include it because the cost lesson carries straight over to AWS. The first design, based on a network video recorder setup and on-demand pricing, was estimated at $5,363 a month. Our team redesigned the processing layer around Azure Spot VMs in scale sets, with pipelines built to absorb interruptions. On AWS, the same pattern is EC2 Spot in an Auto Scaling group, or AWS Batch on Spot. The estimated total fell to $1,100 a month, and the compute layer alone went from $4,700 to $430. The case reports that Spot interruptions had zero impact on the video processing workflows.
There's one customer here, so cost per customer tells you nothing. The useful metric is cost per unit of work:
Unit metricOn-demand designSpot designChange
Total per month$5,363$1,100−$4,263
Per workstation per month (200)$26.82$5.50−79.5%
Per video hour (~54,000 a month)~$0.099~$0.020−79.5%
Compute layer only$4,700$430−90.9%
Source: Jewelry AI Vision case study. Per-unit figures are our arithmetic: 200 workstations × 9 hours × 30 days. The case headline cites 81%; the published monthly figures give 79.5%.
For any SaaS company shipping AI or video features, the lesson is to calculate the unit cost while the architecture is still on paper. A per-video-hour cost of $0.099 versus $0.020 decides whether a feature is profitable at your planned price. That's much easier to fix before launch than after the bill arrives. The same applies to GPU and node costs on Kubernetes, where idle capacity hides easily.
How to reduce your AWS bill once you know your unit cost
Once you know your band, and which tier or service is pushing it up, the order of work is fairly predictable. This is how we sequence it in engagements:
Your bandWeeks 1–2Weeks 3–6Typical outcome
3–7%Orphaned resources, log retention, gp2 to gp3, scheduling non-productionSavings Plans and Reserved Instances on the cleaned-up baseline10–25% lower bill; cost per customer flat as you grow
7–12%Spend by service and by tier, top-two cost drivers, tag coverageDatabase and compute rightsizing, Spot for stateless and batch work, VPC endpoints25–40% lower; Datamaran reached 25% with Savings Plans plus Spot
Over 12%Architecture review: data model, managed-service premiums, data transferRedesign the dominant workload, or move it where it's cheaper to run50%+ is possible; FluentU reached ~78%
For individual tactics, with risks and validation steps for each, see our guide to lowering your AWS bill. For the strategic view, read AWS cost optimization strategies and best practices. If the waste is spread thinly across many services, the common cloud cost traps make a good checklist.
From crawl to run: maturing your cloud unit economics
Nobody gets to exact per-tenant costs in one sprint. The FinOps Framework's Crawl, Walk, Run stages are a useful way to plan the path:
StageWhat you measureWhat you needWho uses it
CrawlBlended cost per customer and hosting % of revenue, monthlyInvoice, customer count, MRR; production split from non-productionCFO, CTO
WalkCost per customer by pricing tier, with shared costs allocated by a usage driverTenant and tier tags, Cost Categories, split cost allocation for ECS/EKS, CUR in AthenaFinance, product, engineering leads
RunUnit cost per feature or unit of work, tracked against targetsUsage telemetry joined with cost data, alerts on unit-cost swings, cost checks in design reviewsEvery engineering team; showback or chargeback
At the Run stage, you also decide between showback and chargeback. Showback means teams see the unit costs they generate. Chargeback means those costs land in their budgets. Most SaaS companies under a few hundred engineers do well with showback, because it changes behavior without adding internal billing overhead.
When is AWS cost optimization consulting worth it?
Plenty of teams reach the Crawl stage on their own in a week. Outside help pays off when:
hosting is above 7–8% of revenue and the team can't name the cause;
one service, usually the database, takes more than half of the cost per customer;
the fix needs a migration or redesign you can't risk getting wrong in production;
you need defensible cost-per-customer figures by tier for pricing, fundraising or a board;
engineers are fully booked on product work and cost work keeps slipping.
A good engagement starts read-only, gives you numbers before recommendations, and puts every change into infrastructure as code so the savings hold. Our overview of a cloud cost optimization engagement covers the process. If a workload needs to move, our cloud migration services team handles the cutover.
Gart Solutions · Cloud consulting
Know your cost per customer. Then bring it down.
We build your cloud unit economics, from tagging and allocation to cost per customer by tier. Then we fix what's driving it, without putting production at risk. That covers everything from Savings Plans to a full database redesign or migration.
~78%lower run-rate for FluentU
$4,263saved per month for Jewelry AI
25%lower monthly AWS costs for Datamaran
Unit cost baselineCost per customer and per tier from your Cost and Usage Report
Tagging and allocationTenant tags, Cost Categories, ECS/EKS split cost allocation
Architecture fixesDatabase redesign, Spot-ready pipelines, Kubernetes bin-packing
Migration if it paysAWS, Azure, GCP or Hetzner, with tested cutover and rollback
Explore cloud consulting
Talk to an engineer →
Most US SaaS teams that ask "should we leave AWS?" are really asking three smaller questions: is our bill high for structural reasons or just untidy, can our product live without the AWS services we depend on, and where would we actually go. This guide answers those questions with three real cloud repatriation cases, a weighted decision matrix you can score in 20 minutes, and an honest look at AWS to Hetzner economics after Hetzner's 2026 price increases.
If you need the background on why repatriation is happening at all, start with our explainer on cloud repatriation and the hidden cost of elasticity. This article is the next step: the decision for a US-based SaaS company.
Key takeaways
Leaving AWS pays off when spend is steady and concentrated in "premium" lines: managed databases, provisioned IOPS, egress, NAT. It rarely pays off for spiky, serverless-heavy products or bills under roughly $5K/month.
Real results vary widely by path. 37signals cut about $2M a year by moving compute to owned servers. Gart's US client FluentU reached a projected ~78% lower steady-state infrastructure cost moving from AWS to Hetzner.
Hetzner is not the same bargain it was in 2025. Its June 15, 2026 repricing raised CPX and CCX cloud lines by 113–175%. Dedicated servers and the CX/CAX lines are where the economics still hold.
US SaaS has extra constraints: Hetzner's US locations (Ashburn, Hillsboro) are cloud-only, with no dedicated servers or Object Storage, and Hetzner does not advertise SOC 2 reports or HIPAA BAAs.
Hybrid is the most common winning answer. Keep the edge, identity, and spiky services on AWS; move the steady core.
Why US SaaS repatriation is a different decision
Most cloud repatriation stories come from Europe, where data sovereignty and GDPR give teams a second reason to move. US SaaS companies usually have only one reason, gross margin, and several reasons to stay put:
Your customers are in North AmericaA server in Falkenstein or Helsinki adds a transatlantic round trip (typically around 80–100 ms to the US East Coast) to every uncached request. That is fine for async workloads and a problem for chatty APIs.
Your buyers send security questionnairesEnterprise procurement teams ask for SOC 2 Type II, and healthcare buyers ask for a HIPAA Business Associate Agreement. Your SOC 2 covers your controls, but you will need to explain your subprocessors, and AWS is the easy answer.
Your contracts may assume AWSSavings Plans, an Enterprise Discount Program, or AWS Marketplace co-sell revenue can make leaving expensive in ways your bill doesn't show.
Your team was hired for AWSRunning PostgreSQL replication, backups, and on-call for bare metal is a different skill set from clicking "Multi-AZ" in RDS.
None of these blocks repatriation. They change which version of it makes sense, and that is what the matrix below is for.
What changed in 2026
Two forces now pull in opposite directions.
Leaving AWS got cheaper: the egress waiver removed the "exit tax" that used to cost large data holders six figures (AWS waived roughly $250,000 in egress for 37signals alone).
Arriving at Hetzner got more expensive: after an across-the-board increase of roughly 30–37% on April 1, 2026, Hetzner repriced its cloud lines again on June 15, 2026, citing a "massive increase in procurement costs" for RAM, NVMe, and GPUs.
Hetzner cloud plan (DE/FI, €/month)Before June 15, 2026AfterChangeCCX23 (dedicated vCPU)31.4985.99+173%CCX33 (dedicated vCPU)62.49138.49+122%CPX42 (AMD shared)25.4969.49+173%CAX41 (ARM shared)31.4940.99+30%CX53 (Intel shared)22.4929.49+31%
What this means for an AWS to Hetzner business case: any model built before mid-2026 on CPX or CCX pricing is now wrong, often by more than 2x on compute. Existing instances keep their old price, but new orders and any resize pay the new rate. The economics still work, but they now depend on which Hetzner products you use. Dedicated root servers, ARM (CAX), and Intel shared (CX) lines carry much more of the savings than they did a year ago.
For US SaaS this matters twice over. Hetzner's US locations offer only its AMD shared and AMD dedicated-vCPU cloud types, which are the CPX and CCX families hit hardest in June. Hetzner prices its US locations separately from Europe, so check the current US price list before modeling a US-hosted footprint.
Three cloud repatriation cases, and what each one proves
Each case below took a different path, and each one teaches a different lesson.
Three cloud repatriation cases, and what each one proves
Each case below took a different path, and each one teaches a different lesson.
US SaaS · AWS → owned hardware in colocation
Case 1: 37signals (Basecamp, HEY), the large-scale full exit
Starting point: an AWS bill of more than $3.2M per year, including 18 PB in S3.
What they did: they bought about $700K of Dell servers for compute and moved off AWS compute first, which saved about $2M per year. They then spent $1.5M on Pure Storage arrays (operating cost under $200K per year) to bring the 18 PB home, with a further expected saving of about $1.3M per year. AWS waived about $250K in egress fees, and the company says it needed no extra staff.
What it proves: at multi-million-dollar scale with a steady, predictable workload, owning hardware beats renting it by a wide margin. What it doesn't prove: that a $40K/month SaaS can copy the playbook. 37signals had a seasoned ops team and a product built on a simple, portable Rails stack.
US public SaaS · AWS S3 → custom storage
Case 2: Dropbox, repatriating only the storage tier
Starting point: the bulk of user file storage on AWS S3.
What they did: built its own storage system, Magic Pocket, and moved most user data into its own data centers. Its 2018 S-1 filing attributed about $74.6M in savings over two years to this infrastructure optimization.
What it proves: you don't have to move everything. Repatriating the single most expensive, most predictable tier captures most of the value. Dropbox kept a portion of its storage on AWS rather than forcing a total exit.
US mid-market SaaS · AWS → Hetzner · Gart Solutions client
Case 3: FluentU, an AWS to Hetzner move at the scale most SaaS teams operate
Starting point: FluentU, a Maryland-based language-learning platform (web app, mobile apps, Chrome extension, blog), ran on EC2, RDS, ElastiCache, CloudFront, S3, NFS, and SQS. The verified AWS baseline was $9,318.15/month, and 65% of it ($6,071.87) was RDS, driven by Multi-AZ instance classes and provisioned IOPS.
What we did: moved application servers, self-managed database servers, and shared NFS storage to Hetzner, defined in Terraform, with data replicated through AWS DMS change data capture. CloudFront stayed in place and was re-pointed at the Hetzner origin, so the move was hybrid by design.
What went wrong (and why it matters): the first live cutover was aborted because CDC latency kept rising and table diffs remained. A schema comparison across 1,474 tables found 1,464 column-metadata differences and 1,179 missing target indexes. We rebuilt the target and added a hard schema gate before the next attempt. Core production went live on Hetzner on July 3, 2026. The final content sync ran about 2.5 hours behind a maintenance page.
Result: a combined AWS + Hetzner steady state of about $2,029–$2,059/month, roughly 78% below baseline (about $87K saved per year), projected to reach about 83% once old backup retention expires.
What it proves: a sub-$10K/month US SaaS can repatriate profitably when the bill is dominated by a managed-database premium. It also proves that the database cutover, not the servers, is where these projects succeed or fail. Read the full FluentU AWS to Hetzner case study[cite: 1].
Not sure if your AWS bill is structural or just untidy?
Gart's Cloud Exit Assessment maps every AWS line item to one of three paths: optimize in place, move to a hybrid setup, or repatriate. You get a cost model built on current 2026 pricing, not last year's.
Get a cloud exit assessment
The pattern across all three: none of them moved because "cloud is expensive." Each one found a specific, steady, oversized line item (compute at scale, object storage, managed databases) and moved that first. That is the logic the decision matrix encodes.
The "leave AWS" decision matrix
Score your company from 1 to 5 on each of the eight criteria below. A 5 means the criterion points toward leaving AWS, and a 1 means it points toward staying. Multiply each score by its weight, add the results, and divide by 5 to get an index between 20 and 100.
#CriterionWeightScore 5: favors leaving AWSScore 1: favors staying1Steady-state AWS spend15Over $50K/month (3 = $10–30K)Under $5K/month: engineering time will eat the savings2Workload predictability15Baseline load within ~30% of peak, year-roundLarge seasonal or event spikes you rely on autoscaling for3"Premium" share of the bill15Over 50% in managed DBs, provisioned IOPS, egress, NAT GatewayMostly right-sized EC2 already on Savings Plans4Portability of your stack15Containers, PostgreSQL/MySQL, Redis, S3-compatible APIsDeep use of Lambda, DynamoDB, Kinesis, Cognito, Step Functions5Compliance fit10SOC 2 on your own controls; no HIPAA, FedRAMP, or AWS-specific contract termsHIPAA BAA, FedRAMP, or enterprise contracts that name AWS6Latency and geography10Async or batch-heavy, CDN-cacheable, or customers outside North AmericaReal-time, chatty APIs serving US users with tight latency SLAs7Ops capability10In-house Linux, DB, and on-call skills, or a managed partnerNo one owns backups, patching, or 3 a.m. incidents today8Commitment exposure10Savings Plans or EDP expiring within 6–12 months; no Marketplace co-sellMulti-year EDP, fresh Savings Plans, or meaningful AWS Marketplace revenue
How to read your result:
Worked example (hypothetical): a Series B US B2B SaaS spending $28K/month (score 3), with steady load (4), 55% of spend in RDS and NAT (5), containers on PostgreSQL but Cognito for auth (3), SOC 2 only (4), US customers on a latency-sensitive dashboard (2), a three-person platform team (3), and a Savings Plan expiring in 8 months (4). The weighted index is (45 + 60 + 75 + 45 + 40 + 20 + 30 + 40) ÷ 5 = 71. That is borderline full exit, but the low latency score is a red flag. The sensible move is hybrid, with the core in a US region or with the latency-sensitive API kept on AWS.
Hard stops. Treat any of these as an automatic "not now," regardless of score: an unresolved HIPAA BAA requirement for production PHI, a FedRAMP obligation, an EDP with a large unmet spend commitment, or no one who can own database operations.
Where to go: destination fit for US SaaS
"Leave AWS" is not one destination. Here is how the realistic options compare for a company whose customers are mostly in the US.
FactorStay & optimize AWSHybrid: AWS edge + Hetzner coreHetzner EU (dedicated servers)Hetzner US (cloud only)US colocation / owned hardwareCost reduction potentialModerate (rightsizing, commitments)High on moved workloadsHighest per coreModerate after 2026 repricingHigh at scale, CapEx up frontLatency to US usersBestGood (edge stays local)Transatlantic hopGood (VA, OR)Best (you choose the site)Managed servicesFull catalogKeep what you needMinimal, you run itMinimal; no Object Storage in USNone, you run everythingOps burdenLowMediumHighMedium-highHighest (hardware lifecycle)Attestations for buyersSOC 2, HIPAA BAA, FedRAMPMixed: document bothISO 27001, BSI C5 Type 2Same company-level certificationsDepends on the facilitySpeed to add capacityMinutesMinutes (burst to AWS)Hours to daysMinutesWeeksBest fitSpiky, serverless, small billsMost US SaaS at $10K–$100K/monthBatch, async, data processing, EU customersUS-facing apps on CX/CAX-friendly workloads$1M+/year steady workloadswhere to migrate
Two Hetzner details catch US teams off guard. First, Ashburn and Hillsboro are cloud-only: you can't order dedicated root servers there, and Object Storage isn't offered in the US, so the cheapest Hetzner products are only available in Germany and Finland. Second, traffic between Hetzner's US and EU network zones is billed as regular internet traffic, so a split-region design needs its own bandwidth line in the model.
On compliance, Hetzner holds ISO/IEC 27001 and a BSI C5 Type 2 attestation, but it says it focuses on ISO 27001 instead of SOC 2 and does not mention HIPAA. For many B2B buyers an ISO 27001 subprocessor is fine. For healthcare PHI, plan to keep that workload on a provider that signs a BAA.
If the matrix and this table point you toward AWS to Hetzner, our step-by-step AWS to Hetzner migration guide covers the execution: service mapping, the parallel build, dual-writes, and cutover.
The costs that don't show up on the Hetzner price list
Most repatriation business cases that disappoint get the server price right and miss everything around it. Add these lines before you compare totals:
The double-run period. You pay for both environments for weeks or months. FluentU's AWS bill only fell 49.7% in the first post-cutover month because of cleanup and retained snapshots.
Database operations. Replacing RDS means owning replication, failover, point-in-time recovery, patching, and tested restores. This is the work the managed-DB premium was paying for.
Backups and disaster recovery off-provider. A single-provider setup without a second location is a regression from Multi-AZ. Budget for a second site or provider.
Observability and security tooling that CloudWatch, GuardDuty, and IAM gave you by default.
On-call and runbooks, either internal hours or a managed SRE contract.
Repricing risk. Hetzner changed prices four times in 2026. Model a 30% buffer on compute and recheck before every resize.
Remaining AWS commitments. Unused Savings Plans or EDP shortfalls are sunk costs you still pay.
A credible model shows three numbers: today's AWS cost, the target steady-state cost including the lines above, and the one-time migration cost. It then calculates payback in months. If payback runs past 18 months, optimize AWS first and revisit.
How to decide in 90 days without betting the company
This is a decision process, not a migration plan.
Days 1–20: Get the real baseline. Export 12 months of Cost and Usage Reports. Tag spend by workload, not by service. Identify the three biggest steady line items, as FluentU's RDS turned out to be.
Days 21–40: Score the matrix with the people who own each criterion: finance for commitments, security for compliance, engineering for portability. Disagreements are the useful output.
Days 41–70: Run a pilot on one non-critical, steady workload, such as a worker pool, a reporting database replica, or a blog. Measure actual cost, latency, and ops hours.
Days 71–90: Build the go/no-go model with current 2026 pricing, the hidden-cost lines, and payback. Decide between optimize, hybrid, and full exit. Only then plan the migration itself.
Repatriate with a team that has done it, including the aborted cutover
Gart Solutions plans and runs AWS exits for SaaS companies in the US and Europe, from the first cost audit to the final DNS switch and the on-call afterwards.
~78%
lower steady-state infrastructure cost for FluentU after moving from AWS to Hetzner
$87K/yr
projected savings on a $9.3K/month starting AWS bill
6 months
from first audit to production on Hetzner, with a schema-gated cutover and validated restores
We'll tell you if leaving AWS isn't worth it. Sometimes the right answer is a cleaner AWS bill.
Explore cloud migration services