Heroku Alternative for EU Developers 2026: GDPR, CLOUD Act, and Salesforce Jurisdiction
Post #662 in the sota.io EU Compliance Series
Heroku invented the modern Platform-as-a-Service. Git push, it runs. No servers to manage, no Dockerfiles to write, no infrastructure ops. For a decade it was the default answer to "where should I deploy my app?" Many production EU applications still run on Heroku today.
Heroku is also owned by Salesforce, a Delaware corporation headquartered in San Francisco, California. That legal fact — not the datacenter region you pick — is the thing your DPO cares about in 2026.
This post explains exactly what the Heroku-Salesforce-CLOUD Act chain means for GDPR compliance, which data flows are most exposed, and gives you a complete comparison of EU-native alternatives with a Python HerokuMigrationComplianceChecker tool and a 15-item compliance migration checklist.
The Salesforce Chain: Why Heroku Is a US Entity
Salesforce acquired Heroku in January 2011 for $212 million. Heroku, Inc. became a wholly owned subsidiary of Salesforce.com, Inc. (now Salesforce, Inc.). Both entities are incorporated in Delaware and headquartered in California.
This matters because of the CLOUD Act.
The CLOUD Act (Clarifying Lawful Overseas Use of Data Act, 18 U.S.C. § 2713) requires US persons and US entities — including subsidiaries of US corporations — to disclose stored communications and customer data to US law enforcement authorities upon lawful request. The obligation follows the entity, not the server location.
What this means for Heroku customers:
- US authorities can compel Salesforce/Heroku to produce your data without EU mutual legal assistance treaties (MLAT). They can also issue gag orders preventing Salesforce from notifying you that a request was made.
- Heroku's EU region ("heroku-eu", hosted on AWS eu-west-1 in Ireland) does not change this. CLOUD Act obligations are entity-level, not datacenter-level.
- Your Heroku config vars, dyno logs, Heroku Postgres data, and Heroku Redis data are all managed by a US entity with CLOUD Act disclosure obligations.
- The AWS infrastructure underneath adds a second layer. Heroku runs on AWS. AWS is also a US entity subject to the CLOUD Act independently.
You have two US CLOUD Act-exposed entities in your stack simultaneously: Salesforce/Heroku as the PaaS layer, and AWS as the infrastructure layer beneath it.
The GDPR Exposure Map
Article 44: Third-Country Transfers
GDPR Article 44 prohibits transfers of personal data to third countries (non-EEA) unless one of the lawful transfer mechanisms in Articles 45–49 applies. Using Heroku to process EU user data creates this transfer because your data controller has a contract with a US entity (Heroku/Salesforce).
Salesforce offers Standard Contractual Clauses (SCCs) and a Data Processing Addendum (DPA) as the transfer mechanism. The problem: SCCs alone are not sufficient under the Schrems II ruling (C-311/18) when the recipient country has laws incompatible with the EU Charter of Fundamental Rights. The CLOUD Act is exactly such a law.
Your DPO needs to conduct a Transfer Impact Assessment (TIA) before relying on SCCs with Heroku. The TIA must evaluate CLOUD Act risk. Many DPOs conclude that CLOUD Act exposure is not adequately addressed by SCCs alone.
Article 28: Data Processor Requirements
GDPR Article 28 requires that data processors provide "sufficient guarantees" of technical and organisational measures. Heroku's DPA is the Salesforce master DPA, which covers all Salesforce products. It is not Heroku-specific.
Key issues with the Salesforce/Heroku DPA:
- Sub-processor list includes AWS, Salesforce internal services, and third-party tooling — all US entities
- No specific EU-only processing commitment beyond "data residency add-on" (which is a paid feature and does not remove CLOUD Act exposure)
- Support access: Salesforce global support staff can access dyno logs and config vars for troubleshooting — these are potential CLOUD Act disclosure points
Article 25: Data Protection by Design
GDPR Article 25 requires data protection by design and by default. Choosing infrastructure with structural CLOUD Act exposure is an architecture decision that works against Art.25 compliance. EU supervisory authorities increasingly expect controllers to demonstrate that infrastructure selection itself reflects data minimisation and purpose limitation.
BayLDA (Bavaria's data protection authority) issued guidance in 2023 stating that controllers should document why US infrastructure is necessary when EU alternatives exist. "We always used Heroku" is not a documented necessity.
Article 32: Security of Processing
Heroku's free tier (which was sunset in November 2022) processed significant EU user data for years without enterprise security commitments. Remaining paid tiers include security features, but the underlying CLOUD Act exposure is not a security measure — it is a legal structure.
What Heroku Processes (and When It Is a Problem)
Not all Heroku usage creates equal GDPR risk. This breakdown helps you assess your specific exposure:
High Risk: Heroku Postgres
Heroku Postgres is a managed PostgreSQL service operated by Heroku (Salesforce). If this database stores:
- User account data (names, emails, account identifiers)
- Transaction records
- Health or financial data
...then you have a US entity (subject to CLOUD Act) holding your most sensitive EU user data. This is the highest-risk component.
Heroku Postgres is not just "Postgres on AWS" — it is a managed service with Salesforce support access, backup management, and operational visibility into your data.
High Risk: Heroku Redis
Same analysis as Postgres. Session tokens, cache data, and queue messages processed through Heroku Redis are managed by a Salesforce entity.
Medium Risk: Config Vars
Environment variables (API keys, secrets, database URLs) stored in Heroku config vars are stored in Heroku's platform and visible to Heroku support. A CLOUD Act request could compel disclosure of these credentials.
Medium Risk: Build Logs and Dyno Logs
Every application log written to stdout in a Heroku dyno is processed by Heroku's log aggregation infrastructure. If your application logs include user identifiers, IP addresses, or request content — this log data is processed by a US entity.
Lower Risk: Static Assets
If you only use Heroku to serve static assets with no user data logging, GDPR exposure is lower. Still present due to IP address processing, but lower relative risk.
The Free Tier Sunset and Why Migration Is Still Ongoing
In August 2022, Salesforce announced the sunset of Heroku's free tier, effective November 28, 2022. Hundreds of thousands of applications — student projects, indie applications, small production services — were affected.
The migration wave that followed was massive but is still incomplete. Many teams:
- Migrated the main app but left Heroku Postgres in place (it had no equivalent free replacement)
- Moved to other US-based PaaS providers (Railway, Render) without addressing the GDPR issue
- Are still on paid Heroku tiers because migration is low priority
For EU teams, the free-tier sunset created an opportunity to do migration correctly: move to EU-native infrastructure at the same time. Many did not, because the focus was operational continuity rather than legal compliance.
In 2026, the DPA risk is catching up. EU supervisory authorities are actively auditing infrastructure choices.
EU-Native Heroku Alternatives Comparison
| Platform | Jurisdiction | CLOUD Act | Managed Postgres | Git Deploy | Price Start |
|---|---|---|---|---|---|
| sota.io | Germany (EU) | None | Yes (EU) | Yes | €9/mo |
| Clever Cloud | France (EU) | None | Yes (EU) | Yes | ~€15/mo |
| Scalingo | France (EU) | None | Yes (EU) | Yes | ~€10/mo |
| Fly.io | USA | YES | Via extensions | Yes | ~$5/mo |
| Render | USA | YES | Yes | Yes | $7/mo |
| Railway | USA | YES | Yes | Yes | ~$5/mo |
Critical note on Fly.io, Render, and Railway: All three are US-incorporated entities subject to the CLOUD Act, regardless of which datacenter region they operate in. Choosing "EU region" on these platforms does not remove CLOUD Act exposure — it only affects physical data location. The legal entity relationship with a US company remains.
sota.io: EU-Native Heroku Replacement
sota.io is incorporated and operated in Germany (EU). No US parent, no US subsidiary, no CLOUD Act exposure. The deployment model maps directly onto Heroku's mental model:
- Git-push deployment — push to deploy, same workflow as Heroku
- Managed Postgres — EU-hosted PostgreSQL with EU-only operations
- Managed Redis — EU-hosted Redis for sessions and caching
- Environment variables — stored in EU infrastructure with German data residency
- GDPR-compliant DPA — German law DPA, not a Salesforce master agreement
Pricing: from €9/month for a managed application with 2 dedicated vCPU, compared to Heroku's Eco dyno at $5/mo for shared infrastructure or Basic dyno at $7/mo.
Clever Cloud: French EU PaaS
Clever Cloud is a French company (SAS) founded in 2010. It predates Heroku's free tier sunset and has been the go-to EU Heroku alternative for French developers. Strong EU compliance posture, ISO 27001 certified, HDS (French Health Data Host) certified. Slightly more complex UI than Heroku but mature ecosystem.
Scalingo: French EU PaaS (Closest Heroku Feel)
Scalingo is explicitly designed as a Heroku-compatible PaaS. Buildpacks, Procfile, environment variables — the migration path is intentionally compatible. French company, EU data residency, SecNumCloud (French national security certification) in progress.
Migration Checklist: Heroku → EU-Native PaaS
Before migrating, run through this 15-item compliance checklist:
☐ 1. Identify all Heroku apps storing EU personal data (user records, logs, analytics)
☐ 2. Check Heroku Postgres — is it storing EU user data? (highest risk component)
☐ 3. Check Heroku Redis — session tokens or user-identifiable cache keys?
☐ 4. Review config vars — do any contain EU user PII or credentials to EU systems?
☐ 5. Audit Heroku log drains — are you sending logs to another US service (Papertrail, LogDNA)?
☐ 6. Check Heroku Add-ons — each add-on is a separate sub-processor (often US entities)
☐ 7. Review your current Heroku DPA — is it a Salesforce master DPA? (flag for DPO)
☐ 8. Run Transfer Impact Assessment for CLOUD Act exposure before SCCs reliance
☐ 9. Identify target EU-native platform (sota.io / Clever Cloud / Scalingo)
☐ 10. Test buildpack compatibility — Heroku buildpacks work on sota.io / Scalingo / Clever Cloud
☐ 11. Migrate Heroku Postgres → EU-native managed Postgres (pg_dump / pg_restore)
☐ 12. Migrate Heroku Redis → EU-native managed Redis (BGSAVE / restore)
☐ 13. Update DNS and SSL certificates on new platform
☐ 14. Update Article 30 Records of Processing Activities (RoPA) with new processor details
☐ 15. Document migration decision for Art.25 (privacy by design) compliance record
Python: HerokuMigrationComplianceChecker
#!/usr/bin/env python3
"""
HerokuMigrationComplianceChecker
Analyses your Heroku stack for GDPR/CLOUD Act exposure
and generates a migration priority report.
Usage: python heroku_compliance_checker.py --heroku-api-key YOUR_KEY
"""
import os
import json
import argparse
from dataclasses import dataclass, field
from typing import List, Optional
# Known US-entity add-ons (not exhaustive)
US_ENTITY_ADDONS = {
"heroku-postgresql": "Salesforce/Heroku — CLOUD Act exposed",
"heroku-redis": "Salesforce/Heroku — CLOUD Act exposed",
"papertrail": "SolarWinds (US) — log data CLOUD Act exposed",
"logdna": "Mezmo (US) — log data CLOUD Act exposed",
"rollbar": "Rollbar Inc (US) — error data CLOUD Act exposed",
"sendgrid": "Twilio (US) — email CLOUD Act exposed",
"mailgun": "Pathwire/Sinch (US) — email CLOUD Act exposed",
"cloudamqp": "84codes (SE) — EU entity, lower risk",
"redis-cloud": "Redis Ltd (US) — CLOUD Act exposed",
"mongolab": "MongoDB Inc (US) — CLOUD Act exposed",
"jawsdb": "JAWS DB (US) — CLOUD Act exposed",
"cleardb": "ClearDB (US) — CLOUD Act exposed",
}
EU_NATIVE_ADDONS = {
"heroku-postgresql": "sota.io Managed Postgres (DE), Clever Cloud PostgreSQL (FR), Scalingo PostgreSQL (FR)",
"heroku-redis": "sota.io Managed Redis (DE), Clever Cloud Redis (FR), Scalingo Redis (FR)",
"sendgrid": "Brevo (FR), Postmark EU region, Mailjet (FR)",
"mailgun": "Brevo (FR), Mailjet (FR — Mailjet is EU-native)",
}
@dataclass
class HerokuApp:
name: str
region: str
addons: List[str] = field(default_factory=list)
config_var_count: int = 0
has_eu_user_data: bool = False
@dataclass
class ComplianceRisk:
component: str
risk_level: str # HIGH / MEDIUM / LOW
issue: str
gdpr_article: str
cloud_act_exposed: bool
eu_alternative: Optional[str] = None
def analyse_app(app: HerokuApp) -> List[ComplianceRisk]:
risks = []
# Base Heroku platform risk (always present)
risks.append(ComplianceRisk(
component=f"Heroku Platform ({app.name})",
risk_level="MEDIUM",
issue="Heroku is a Salesforce subsidiary (US entity). CLOUD Act applies to all dyno data, "
"config vars, and log output regardless of region selection.",
gdpr_article="Art.44 (transfer), Art.28 (processor)",
cloud_act_exposed=True,
eu_alternative="sota.io (DE), Clever Cloud (FR), Scalingo (FR)"
))
# Region check
if "eu" in app.region.lower():
risks.append(ComplianceRisk(
component=f"Region: {app.region}",
risk_level="LOW",
issue="EU region reduces data latency but does NOT remove CLOUD Act exposure. "
"The legal entity (Salesforce/Heroku) is still a US person under 18 U.S.C. § 2713.",
gdpr_article="Art.44 (transfer risk persists)",
cloud_act_exposed=True,
eu_alternative=None
))
# Add-on analysis
for addon in app.addons:
addon_key = addon.lower().split(":")[0] # strip plan suffix
if addon_key in US_ENTITY_ADDONS:
is_high = "postgresql" in addon_key or "redis" in addon_key
risks.append(ComplianceRisk(
component=f"Add-on: {addon}",
risk_level="HIGH" if is_high else "MEDIUM",
issue=US_ENTITY_ADDONS[addon_key],
gdpr_article="Art.44 (transfer), Art.28 (sub-processor)",
cloud_act_exposed=True,
eu_alternative=EU_NATIVE_ADDONS.get(addon_key, "Check eu-alternatives.org")
))
# Config var risk
if app.config_var_count > 5:
risks.append(ComplianceRisk(
component="Config Vars",
risk_level="MEDIUM",
issue=f"{app.config_var_count} config vars stored in Heroku platform. "
"Accessible to Heroku/Salesforce support. CLOUD Act compellable.",
gdpr_article="Art.32 (security)",
cloud_act_exposed=True,
eu_alternative="Vault (HashiCorp) on EU infra or target platform secret management"
))
return risks
def generate_report(apps: List[HerokuApp]) -> None:
print("=" * 60)
print("HEROKU EU COMPLIANCE REPORT — GDPR / CLOUD ACT ANALYSIS")
print("=" * 60)
all_risks = []
for app in apps:
print(f"\n[APP] {app.name} | Region: {app.region}")
risks = analyse_app(app)
all_risks.extend(risks)
for risk in risks:
icon = "🔴" if risk.risk_level == "HIGH" else "🟡" if risk.risk_level == "MEDIUM" else "🟢"
print(f" {icon} [{risk.risk_level}] {risk.component}")
print(f" Issue: {risk.issue}")
print(f" GDPR: {risk.gdpr_article}")
if risk.eu_alternative:
print(f" EU Alt: {risk.eu_alternative}")
high_count = sum(1 for r in all_risks if r.risk_level == "HIGH")
medium_count = sum(1 for r in all_risks if r.risk_level == "MEDIUM")
print("\n" + "=" * 60)
print(f"SUMMARY: {high_count} HIGH risks, {medium_count} MEDIUM risks")
print(f"CLOUD Act exposed components: {sum(1 for r in all_risks if r.cloud_act_exposed)}")
print("\nPRIORITY MIGRATION ORDER:")
print(" 1. Heroku Postgres → sota.io / Clever Cloud / Scalingo Postgres (EU)")
print(" 2. Heroku Redis → sota.io / Clever Cloud / Scalingo Redis (EU)")
print(" 3. Log drains → EU-native log aggregation")
print(" 4. Email add-ons → Brevo / Mailjet (EU)")
print(" 5. App dynos → sota.io / Clever Cloud / Scalingo (EU PaaS)")
print("=" * 60)
def main():
parser = argparse.ArgumentParser(description="Heroku EU Compliance Checker")
parser.add_argument("--heroku-api-key", help="Heroku API key (or set HEROKU_API_KEY env var)")
parser.add_argument("--demo", action="store_true", help="Run with demo data")
args = parser.parse_args()
if args.demo:
# Demo mode with sample apps
demo_apps = [
HerokuApp(
name="my-saas-app",
region="us",
addons=["heroku-postgresql:standard-0", "heroku-redis:premium-0", "sendgrid:starter"],
config_var_count=12,
has_eu_user_data=True
),
HerokuApp(
name="my-api-eu",
region="eu",
addons=["heroku-postgresql:essential-0", "papertrail:choklad"],
config_var_count=8,
has_eu_user_data=True
),
]
generate_report(demo_apps)
return
# Real mode: fetch from Heroku API
api_key = args.heroku_api_key or os.environ.get("HEROKU_API_KEY")
if not api_key:
print("Error: Provide --heroku-api-key or set HEROKU_API_KEY environment variable")
print("Tip: Run with --demo to see sample output")
return
try:
import urllib.request
headers = {
"Accept": "application/vnd.heroku+json; version=3",
"Authorization": f"Bearer {api_key}",
}
req = urllib.request.Request("https://api.heroku.com/apps", headers=headers)
with urllib.request.urlopen(req) as resp:
apps_data = json.loads(resp.read())
apps = []
for app_data in apps_data:
# Fetch add-ons for this app
addon_req = urllib.request.Request(
f"https://api.heroku.com/apps/{app_data['name']}/addons",
headers=headers
)
with urllib.request.urlopen(addon_req) as addon_resp:
addons_data = json.loads(addon_resp.read())
addon_names = [a["addon_service"]["name"] for a in addons_data]
apps.append(HerokuApp(
name=app_data["name"],
region=app_data.get("region", {}).get("name", "unknown"),
addons=addon_names,
config_var_count=0, # would need separate API call
))
generate_report(apps)
except Exception as e:
print(f"Error fetching Heroku data: {e}")
print("Run with --demo to see sample output")
if __name__ == "__main__":
main()
Run in demo mode:
python heroku_compliance_checker.py --demo
Or against your real Heroku account:
export HEROKU_API_KEY=$(heroku auth:token)
python heroku_compliance_checker.py
The Salesforce DPA: What It Actually Covers
When you sign up for Heroku, your data processing agreement is with Salesforce. The Salesforce Data Processing Addendum applies to all Salesforce services including Heroku. Key clauses to understand:
Sub-processor List: Salesforce maintains a list of sub-processors at salesforce.com/content/dam/web/en_us/www/documents/legal/Privacy/salesforce-sub-processors.pdf. For Heroku specifically, the key sub-processor is Amazon Web Services (AWS) — also a US entity subject to the CLOUD Act independently.
Support Access: Section 4 of the Salesforce DPA covers access controls for support purposes. Heroku support staff can access dyno metadata, log output, and platform configuration to diagnose issues. These access events are CLOUD Act compellable.
Data Residency: Salesforce sells a "Hyperforce Data Residency" add-on for some products. Heroku does not have an equivalent offering that would isolate data processing within EU jurisdiction and remove CLOUD Act exposure. EU region on Heroku is a performance/latency feature, not a legal jurisdiction feature.
What EU Supervisory Authorities Are Looking At
The EDPB (European Data Protection Board) and national DPAs have been increasingly focused on infrastructure jurisdiction since the Schrems II decision in 2020. Key enforcement actions relevant to Heroku-style situations:
- Meta (Facebook) Ireland: €265M fine in 2022, partially related to data transfer mechanisms — establishing that SCCs + CLOUD Act exposure requires additional safeguards
- BayLDA guidance (2023): Controllers must document why US infrastructure is necessary when EU alternatives exist. Generic "market-standard tooling" justification is insufficient
- Austrian DSB ruling (2022): Google Analytics EU data flows violated Art.44 because Google (US entity) is subject to FISA 702 and CLOUD Act. Same analysis applies to Heroku/Salesforce
The enforcement trajectory is clear: using US-entity infrastructure for EU personal data processing is an increasing compliance risk, and the "everyone uses it" argument is not a defence.
Migration Time Estimates
| Component | Migration Complexity | Estimated Time |
|---|---|---|
| App dyno → EU PaaS (sota.io/Scalingo) | Low (buildpack compatible) | 2–4 hours |
| Heroku Postgres → EU Postgres | Medium (pg_dump + pg_restore) | 4–8 hours |
| Heroku Redis → EU Redis | Low (BGSAVE + restore) | 1–2 hours |
| Config vars → new platform | Trivial | 30 minutes |
| DNS update + SSL cert | Low | 1–2 hours |
| Log drain update | Low | 30 minutes |
| DPA + RoPA update | Administrative | 1–2 hours |
| Total | Low–Medium | ~1–2 days |
Most EU teams migrating from Heroku report the hardest part is Postgres migration for large databases — not the application code or platform configuration.
Conclusion: Heroku in 2026 for EU Developers
Heroku remains a technically capable PaaS. For EU companies handling personal data, it has a fundamental legal structure problem that no datacenter region selection can fix: it is a Salesforce subsidiary, subject to the CLOUD Act, with AWS (also CLOUD Act-exposed) as its underlying infrastructure.
If your Heroku apps process EU personal data — user accounts, transaction records, application logs with IP addresses — you have ongoing GDPR Art.44 transfer exposure and a Data Processing Agreement that your DPO likely cannot approve without a documented Transfer Impact Assessment.
The migration path to EU-native alternatives is well-established. sota.io, Clever Cloud, and Scalingo all support Heroku buildpacks, have managed database offerings, and operate as EU legal entities with no CLOUD Act exposure. The technical migration work is measured in days, not weeks.
The compliance risk of staying on Heroku for EU personal data is harder to quantify — but EU DPA enforcement actions are increasing, fines are reaching seven and eight figures, and "we always used Heroku" is not a documented legal justification under Art.25.