Netlify Alternative for EU Developers 2026: CLOUD Act, GDPR, and EU-Native Deployment
Post #661 in the sota.io EU Compliance Series
Netlify built the modern web deployment experience. Git-push-to-deploy, preview deployments, serverless functions, edge middleware — it popularised the workflow that every developer now expects. It is also a Delaware corporation headquartered in San Francisco, California.
That second fact matters more in 2026 than it did in 2018. This post explains the specific CLOUD Act and GDPR exposure that comes with Netlify, analyses which parts of your stack are most at risk, and gives you a complete comparison of EU-native alternatives including a Python NetlifyComplianceChecker tool and a 15-item migration checklist.
Why "US Company" is a Legal Fact, Not a Marketing Angle
The CLOUD Act (Clarifying Lawful Overseas Use of Data Act, 18 U.S.C. § 2713) requires US persons and US entities to disclose stored communications and data to US law enforcement — regardless of where the data is physically stored. Netlify Inc. is unambiguously a US person under this statute.
What this means in practice:
- US authorities can compel Netlify to produce your data without going through EU mutual legal assistance treaties (MLAT) or informing you in advance.
- Netlify's EU datacenter location does not change this. The CLOUD Act applies to the company's obligations as a US entity, not to the physical location of its servers.
- Build logs, environment variables, serverless function invocation data, and form submissions processed by Netlify are subject to CLOUD Act disclosure obligations.
This creates a GDPR Article 44 cross-border transfer problem. When you use Netlify to process data from EU users — even if Netlify's edge node is in Frankfurt — the data controller relationship with a US entity triggers transfer obligations.
What Netlify Processes (and Why It Matters for GDPR)
Most compliance discussions focus on where user data is stored. Netlify's exposure is more nuanced because it touches multiple data types across different pipeline stages.
Build-Time Data
Every Netlify build processes:
- Source code — may contain personal data references, hardcoded test fixtures, migration files with real data
- Environment variables — API keys, database connection strings, often scoped to production endpoints
- Build logs — include dependency resolution, test output, sometimes stack traces with data samples
Under GDPR Article 4(1), personal data is "any information relating to an identified or identifiable natural person." A database migration file with real email addresses is personal data. A stack trace containing a user ID is personal data. Netlify's build infrastructure processes these on US-controlled systems.
Serverless Functions and Edge Middleware
Netlify Functions (AWS Lambda-backed) and Netlify Edge Functions (Deno-based) process HTTP requests from your users in real time. If those requests carry:
- Authentication tokens (JWTs with user sub claims)
- Session cookies (GDPR-protected personal data under ePrivacy)
- User-submitted form data (GDPR Article 6 lawful basis required)
- IP addresses (personal data under GDPR in the EU, confirmed by ECJ)
...then each function invocation is a data processing activity under GDPR Article 4(2). The processor is Netlify Inc. — a US entity.
Form Submissions (Netlify Forms)
Netlify Forms captures form submissions and stores them on Netlify's servers. If your EU users submit contact forms, waitlist signups, or support requests through Netlify Forms, this data is stored on US-controlled infrastructure. GDPR Article 28 requires a Data Processing Agreement (DPA). Netlify provides a DPA — but it is a US-entity DPA with Standard Contractual Clauses (SCCs) as the transfer mechanism.
Analytics and Logs
Netlify's analytics and access logs record:
- Visitor IP addresses
- Request paths (which may encode user IDs in URLs)
- User-Agent strings (fingerprinting data under GDPR recital 30)
These are retained by Netlify and subject to CLOUD Act disclosure.
The Article 44 Transfer Mechanism Problem
When EU personal data is transferred to a US entity, GDPR Article 44 requires a valid transfer mechanism:
| Mechanism | Netlify Status | Risk Level |
|---|---|---|
| Adequacy decision (UK/Swiss framework) | US has no full EU adequacy | N/A |
| Standard Contractual Clauses (SCCs) | Netlify DPA uses SCCs | Medium — SCC validity depends on TIA |
| Binding Corporate Rules (BCRs) | Not applicable for processors | N/A |
| Data Privacy Framework (DPF) | Netlify is DPF-certified | Lower — but DPF challenged in courts |
Netlify relies on the EU-US Data Privacy Framework (DPF) for transfers and falls back to SCCs. The DPF was challenged before the European Parliament and faces ongoing litigation. More importantly, even a valid DPF certification does not suspend CLOUD Act obligations — US authorities can still compel disclosure.
The Transfer Impact Assessment (TIA) Gap
Since Schrems II (C-311/18), EU data exporters must conduct a Transfer Impact Assessment (TIA) before relying on SCCs. A proper TIA for Netlify must address:
- US CLOUD Act: does it create obligations that undermine SCC guarantees? (Answer: yes, in theory)
- US FISA Section 702: are Netlify's services "electronic communication service providers" subject to mass surveillance? (Potentially yes)
- US Executive Order 14086: does it provide "essentially equivalent" protection? (Contested by EU DPAs)
DPAs in Germany (DSK), France (CNIL), and Austria (DSB) have taken hard positions on US surveillance law. A TIA that concludes Netlify transfers are fully SCC-compliant is a difficult legal position to defend if audited.
Article 28 DPA: What Netlify Provides
Netlify does provide a Data Processing Agreement. Key provisions to evaluate:
Sub-processors: Netlify's sub-processor list includes AWS (Lambda for Functions), Deno Deploy (Edge Functions), and several US analytics providers. Each sub-processor inherits the CLOUD Act exposure.
Audit rights: Netlify's DPA provides audit rights via third-party certifications (SOC 2 Type II) but limits direct customer audits. GDPR Article 28(3)(h) requires the processor to "make available to the controller all information necessary to demonstrate compliance" — certification summaries may not be sufficient for a German or French DPA audit.
Data deletion: Netlify commits to deleting data within 90 days of contract termination. Build logs and form submissions may persist in backup systems during this window.
Incident notification: 72-hour breach notification commitment — compliant with GDPR Article 33. But breaches of US law enforcement access are not disclosed (CLOUD Act gag orders are permitted).
Practical Risk Map: Netlify Use Cases
| Use Case | GDPR Risk | CLOUD Act Exposure |
|---|---|---|
| Static sites (no user data) | Low | Low |
| Static sites + EU user analytics | Medium | Medium (IP logs) |
| Next.js with SSR (user sessions) | High | High (JWT/session data) |
| Netlify Functions with user data | High | High (real-time processing) |
| Netlify Forms (EU user submissions) | High | High (stored personal data) |
| Edge Middleware (auth, personalization) | High | High (real-time PII) |
| CI/CD with production env vars | Medium | Medium (env var access) |
Python: NetlifyComplianceChecker
This tool analyses your Netlify setup for GDPR and CLOUD Act risk:
#!/usr/bin/env python3
"""
NetlifyComplianceChecker — Assess GDPR/CLOUD Act risk in your Netlify deployment.
Usage:
checker = NetlifyComplianceChecker("netlify.toml")
report = checker.analyse()
print(report.summary())
"""
from __future__ import annotations
import re
from dataclasses import dataclass, field
from pathlib import Path
from typing import Optional
@dataclass
class ComplianceFinding:
severity: str # "HIGH" | "MEDIUM" | "LOW" | "INFO"
category: str
finding: str
recommendation: str
@dataclass
class ComplianceReport:
findings: list[ComplianceFinding] = field(default_factory=list)
risk_score: int = 0 # 0-100
def summary(self) -> str:
high = sum(1 for f in self.findings if f.severity == "HIGH")
med = sum(1 for f in self.findings if f.severity == "MEDIUM")
low = sum(1 for f in self.findings if f.severity == "LOW")
lines = [
f"NetlifyComplianceChecker — Risk Score: {self.risk_score}/100",
f"Findings: {high} HIGH, {med} MEDIUM, {low} LOW",
"",
]
for f in sorted(self.findings, key=lambda x: ("HIGH", "MEDIUM", "LOW", "INFO").index(x.severity)):
lines.append(f"[{f.severity}] {f.category}: {f.finding}")
lines.append(f" → {f.recommendation}")
return "\n".join(lines)
class NetlifyComplianceChecker:
"""Analyse netlify.toml and project structure for EU compliance risk."""
PERSONAL_DATA_PATTERNS = [
r"email",
r"user_id",
r"ip_addr",
r"session",
r"auth_token",
r"jwt",
r"cookie",
r"name\s*=",
r"phone",
r"address",
]
def __init__(self, config_path: str = "netlify.toml") -> None:
self.config_path = Path(config_path)
self.project_root = self.config_path.parent
def analyse(self) -> ComplianceReport:
report = ComplianceReport()
# 1. Jurisdiction check (always applies)
report.findings.append(ComplianceFinding(
severity="HIGH",
category="Jurisdiction",
finding="Netlify Inc. is a US company subject to CLOUD Act (18 U.S.C. § 2713). "
"US authorities can compel data disclosure without MLAT.",
recommendation="For GDPR Art.44 compliance, conduct a Transfer Impact Assessment (TIA). "
"Consider EU-native alternatives (sota.io, Scalingo, Clever Cloud) for "
"workloads processing EU personal data.",
))
report.risk_score += 30
# 2. Check for Netlify Functions
functions_dir = self.project_root / "netlify" / "functions"
if functions_dir.exists() and any(functions_dir.glob("*.js")) or any(functions_dir.glob("*.ts")) if functions_dir.exists() else False:
report.findings.append(ComplianceFinding(
severity="HIGH",
category="Serverless Functions",
finding="Netlify Functions found. These run on AWS Lambda (US infrastructure). "
"Real-time user data processing under CLOUD Act jurisdiction.",
recommendation="Review function code for personal data handling. "
"Add GDPR Art.28 DPA review for AWS as Netlify sub-processor. "
"Consider migrating to EU-native serverless (e.g., sota.io workers).",
))
report.risk_score += 20
# 3. Check netlify.toml for edge functions
if self.config_path.exists():
config_text = self.config_path.read_text()
if "edge_functions" in config_text or "[[edge_functions]]" in config_text:
report.findings.append(ComplianceFinding(
severity="HIGH",
category="Edge Functions",
finding="Netlify Edge Functions configured. Runs on Deno Deploy (US-controlled). "
"Real-time request processing including auth tokens, session cookies.",
recommendation="Audit edge function code for PII access. "
"Document in your GDPR Art.30 RoPA as 'transfer to Netlify Inc. (US)'.",
))
report.risk_score += 20
# Check for form handling
if "[build]" in config_text and "forms" in config_text.lower():
report.findings.append(ComplianceFinding(
severity="HIGH",
category="Netlify Forms",
finding="Netlify Forms appears configured. EU user form submissions "
"stored on US-controlled infrastructure.",
recommendation="Replace with EU-hosted form backend or self-hosted solution. "
"If keeping Netlify Forms, ensure GDPR Art.13 privacy notice "
"discloses transfer to Netlify Inc. (US) with DPF basis.",
))
report.risk_score += 15
# 4. Scan for personal data patterns in function code
pii_found_in = []
for fn_file in self.project_root.rglob("*.ts"):
if "node_modules" in str(fn_file) or ".venv" in str(fn_file):
continue
try:
content = fn_file.read_text()
for pattern in self.PERSONAL_DATA_PATTERNS:
if re.search(pattern, content, re.IGNORECASE):
pii_found_in.append(fn_file.name)
break
except (OSError, UnicodeDecodeError):
continue
if pii_found_in:
report.findings.append(ComplianceFinding(
severity="MEDIUM",
category="PII in Source",
finding=f"Personal data patterns found in: {', '.join(set(pii_found_in[:5]))}. "
f"These files may process GDPR-protected data on Netlify infrastructure.",
recommendation="Confirm each pattern is covered in your GDPR Art.30 RoPA entry "
"for Netlify. Verify Art.28 DPA sub-processor list is current.",
))
report.risk_score = min(100, report.risk_score + 10)
# 5. Environment variable check
env_files = list(self.project_root.glob(".env*"))
if env_files:
report.findings.append(ComplianceFinding(
severity="MEDIUM",
category="Environment Variables",
finding=f"Found {len(env_files)} .env file(s). Production env vars synced to Netlify "
"are stored on US-controlled infrastructure and accessible to Netlify staff.",
recommendation="Audit which env vars contain credentials for EU data stores. "
"Rotate credentials if migrating away from Netlify. "
"Use Netlify's encrypted env vars — not plaintext .env in builds.",
))
report.risk_score = min(100, report.risk_score + 5)
# 6. DPF / SCC status
report.findings.append(ComplianceFinding(
severity="MEDIUM",
category="Transfer Mechanism",
finding="Netlify relies on EU-US Data Privacy Framework (DPF) and SCCs. "
"DPF faces ongoing legal challenges. SCCs require a TIA since Schrems II.",
recommendation="Document your TIA conclusion in writing. "
"Monitor CJEU/national DPA decisions on DPF validity. "
"Plan migration path if DPF is invalidated (as Safe Harbor was in 2015, "
"Privacy Shield in 2020).",
))
report.risk_score = min(100, report.risk_score + 5)
return report
if __name__ == "__main__":
import sys
config = sys.argv[1] if len(sys.argv) > 1 else "netlify.toml"
checker = NetlifyComplianceChecker(config)
report = checker.analyse()
print(report.summary())
sys.exit(0 if report.risk_score < 50 else 1)
Run it from your project root:
python3 netlify_compliance_checker.py netlify.toml
A score above 50 indicates material GDPR/CLOUD Act risk that should be addressed before your next DPA audit.
EU-Native Netlify Alternatives in 2026
sota.io — EU-Native PaaS (€9/mo)
Jurisdiction: German GmbH. No US parent, no US investment. CLOUD Act does not apply.
What it handles: Containerised web apps, Next.js/Remix/Astro, Node.js APIs, background workers, cron jobs. Git-push-to-deploy with GitHub/GitLab integration. Automatic HTTPS, custom domains.
GDPR status: German entity. DPA available. Data stays in EU. No SCCs required for EU customers.
Pricing: €9/mo flat for 2 vCPU + 2 GB RAM always-on. No per-request billing surprises.
Migration from Netlify: If your Netlify site is a Next.js app with API routes, sota.io runs it without changes. Static export sites deploy as Docker containers. Serverless functions migrate to Node.js HTTP handlers.
Scalingo — French PaaS
Jurisdiction: French SAS. EU-only infrastructure. ISO 27001, HDS (French healthcare data hosting).
What it handles: Node.js, Ruby, Python, PHP, Go. Git-deploy. Add-on marketplace (databases, Redis, etc.). No Edge Functions equivalent.
GDPR status: Strong. French company, French servers, French DPA jurisdiction.
Pricing: From €7.20/mo for 512 MB RAM containers. More expensive at scale than sota.io.
Trade-off: Less Next.js-native DX than Netlify or sota.io. Stronger regulatory posture for healthcare/finance.
Clever Cloud — French PaaS
Jurisdiction: French SAS. EU infrastructure (France, Paris). Strong compliance posture.
What it handles: Similar to Scalingo — traditional PaaS with language buildpacks. No Edge Functions. Git or CI/CD deploy.
Pricing: Pay-per-use. Can be cost-effective for low-traffic apps.
Trade-off: Older DX paradigm. No preview deployments out of the box.
Self-Hosted: Coolify on Hetzner
Jurisdiction: Your Hetzner VM (German GmbH server). You control everything.
What it handles: Docker-based deploys, static sites, databases. Netlify-like DX via the Coolify UI.
Pricing: €4.15/mo Hetzner VPS + Coolify (OSS). Total: ~€5-6/mo.
Trade-off: You manage ops, security, updates. No managed SLA.
Cloudflare Pages — US but CDN-focused
Jurisdiction: US company. CLOUD Act applies.
Note: Cloudflare is US-incorporated. If GDPR compliance is the driver, Cloudflare Pages has the same jurisdiction issue as Netlify. Better performance at the edge, but same legal exposure.
Comparison Table
| Feature | Netlify | sota.io | Scalingo | Clever Cloud |
|---|---|---|---|---|
| Jurisdiction | US (California) | Germany | France | France |
| CLOUD Act | YES | No | No | No |
| EU DPA available | Yes (SCCs) | Yes (no SCCs needed) | Yes | Yes |
| DPF required | Yes | No | No | No |
| Edge Functions | Yes (Deno, US) | No | No | No |
| Serverless Functions | Yes (AWS Lambda) | Via containers | Via add-ons | Via add-ons |
| Static Site Deploy | Yes | Yes | Yes | Yes |
| Next.js SSR support | Yes | Yes | Yes | Yes |
| Preview Deployments | Yes | Yes | Via CI/CD | Via CI/CD |
| Form Handling | Yes (US-stored) | Via your backend | Via your backend | Via your backend |
| Starting price | Free tier / $19/mo Pro | €9/mo | €7.20/mo | Pay-per-use |
| 2 vCPU + 2 GB RAM | ~$88/mo (Pro) | €9/mo | ~€28/mo | ~€25/mo |
15-Item Netlify EU Compliance Checklist
Use this before your next GDPR audit or before migrating:
Jurisdiction and Transfer Basis
- 1. Document Netlify as a US entity in your GDPR Art.30 RoPA (Records of Processing Activities)
- 2. Confirm Netlify's DPF certification is current at privacyshield.gov
- 3. Complete a Transfer Impact Assessment (TIA) documenting CLOUD Act risk
- 4. Execute Netlify's DPA — do not rely on click-through terms alone
Data Mapping
- 5. List every Netlify-processed data type: build logs, function invocations, form submissions, analytics
- 6. Verify Netlify's sub-processor list (AWS, Deno, analytics providers) is acceptable for your use case
- 7. Check if Netlify Forms stores EU user personal data — if yes, add to RoPA and notify users (Art.13)
Technical Measures (Art.25 Privacy by Design)
- 8. Disable Netlify Analytics if you have another EU-compliant solution (e.g., Plausible EU)
- 9. Review Edge Function code: does it read cookies, JWT claims, IP addresses?
- 10. Audit environment variables stored in Netlify: do any give access to EU personal data stores?
Incident Response
- 11. Document that CLOUD Act law enforcement access to Netlify data may not be disclosed to you
- 12. Verify your breach notification process accounts for Netlify as a data processor under Art.33
Migration Readiness
- 13. Map your Next.js SSR pages that set cookies or read user data — these are highest-risk for Netlify
- 14. Test your app on a EU-native alternative (sota.io 30-day trial) before committing to migration
- 15. Update your privacy policy to reflect any change in transfer mechanism if you migrate
Migration Guide: Netlify to sota.io
Step 1: Containerise your app
Netlify handles build + serve for you. sota.io needs a Dockerfile. For Next.js:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
Add output: "standalone" to next.config.js.
Step 2: Connect your repo
In sota.io, create a new project, connect your GitHub repo, and set your Dockerfile path. Automatic deploys on every push to main.
Step 3: Migrate environment variables
Copy your Netlify environment variables to sota.io's encrypted env var store. Rotate any credentials that were previously accessible to Netlify.
Step 4: Update DNS
sota.io provides a custom domain with automatic Let's Encrypt TLS. Update your DNS records. TTL should be set low (300s) before migration to minimise downtime.
Step 5: Migrate Netlify Functions
Netlify Functions become route handlers in Next.js (App Router) or standalone Express endpoints. No AWS Lambda-specific code is needed — plain HTTP handlers work.
Step 6: Replace Netlify Forms
Netlify Forms → your own API route + a database (Supabase EU, PlanetScale EU, or Postgres on sota.io). Example:
// app/api/contact/route.ts
import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db"; // your EU-hosted DB
export async function POST(req: NextRequest) {
const { name, email, message } = await req.json();
await db.insert({ name, email, message, created_at: new Date() });
return NextResponse.json({ ok: true });
}
This keeps form data in your EU-hosted database — no Netlify Forms US storage.
The Decision Framework
Ask yourself three questions:
-
Does your Netlify deployment process EU personal data? (User sessions, form submissions, auth tokens, IP-based personalization) → If yes, you have material GDPR Art.44 exposure.
-
Would a breach of your Netlify data cause regulatory or reputational harm? → If yes, the CLOUD Act gag-order risk (being unable to notify affected users of a law enforcement access event) is a specific liability.
-
What is the operational cost of migration vs. the cost of a DPA audit finding? → German DPA fines under GDPR can reach 4% of global annual turnover. For most startups, migrating to a €9/mo EU-native PaaS like sota.io costs less than one audit remediation cycle.
What sota.io Provides That Netlify Cannot
sota.io is a German company deploying to German infrastructure:
- No US parent. No investor with FISA Section 702 obligations.
- No CLOUD Act. German legal system only. US law enforcement requires formal MLAT process to access data.
- No SCCs needed. You are an EU controller using an EU processor. No cross-border transfer mechanism required.
- GDPR Art.28 DPA included in all plans. German-law governed.
- €9/mo flat pricing for 2 vCPU + 2 GB RAM. No per-function-invocation billing, no egress surprises.
For EU developers who need the Netlify developer experience without the US jurisdiction exposure, sota.io is the direct replacement.
See Also
- Why EU Region ≠ EU Jurisdiction: The CLOUD Act Explained for Developers
- Railway vs Render vs Fly.io: EU PaaS Pricing Comparison 2026
- GitHub Actions Self-Hosted vs Managed Runners: GDPR and CLOUD Act 2026
- Koyeb Is Joining Mistral AI: Best EU PaaS Alternatives 2026
- GDPR Article 44 Transfer Mechanisms: Complete Developer Guide 2026