{"id":98098,"date":"2026-10-13T17:26:00","date_gmt":"2026-10-13T21:26:00","guid":{"rendered":"https:\/\/overcentral.com\/en\/?p=98098"},"modified":"2026-09-29T08:06:59","modified_gmt":"2026-09-29T12:06:59","slug":"emdash-vendor-lock-in-cloudflare-98098","status":"publish","type":"post","link":"https:\/\/overcentral.com\/en\/emdash-vendor-lock-in-cloudflare-98098\/","title":{"rendered":"EmDash Vendor Lock-In: The Real Cost of Leaving Cloudflare"},"content":{"rendered":"<p>Cloudflare wants you to believe EmDash is free, open source, and portable. The code is MIT licensed. You can fork it, run it locally, even deploy it to a bare Node.js server. But the headline feature \u2014 sandboxed plugins \u2014 requires Cloudflare&#8217;s paid infrastructure to function. That&#8217;s not an accident. That&#8217;s architectural lock-in dressed in open-source clothing.<\/p>\n<p>The question isn&#8217;t whether EmDash <em>can<\/em> be ported. It&#8217;s whether the thing that makes it worth using survives the move.<\/p>\n<h2>What Actually Locks You In<\/h2>\n<p>EmDash ties you to Cloudflare across three distinct layers: compute, database, and storage. Each layer has a portability story. None of them are equally portable.<\/p>\n<h3>Compute: The Plugin Sandbox Dies Outside Cloudflare<\/h3>\n<p>This is the painful one. EmDash&#8217;s entire security pitch rests on dynamic workers \u2014 Cloudflare&#8217;s proprietary V8 isolate runtime that spins up in milliseconds, executes plugin code, and vanishes. Every plugin declares its capabilities in a manifest. The runtime enforces those boundaries at the hardware level using Linux namespaces, seccomp filters, and memory protection keys.<\/p>\n<p>Run EmDash on a standard Node.js server. Plugins execute in-process. No sandbox. No isolation. A compromised plugin can read your entire database, modify files, exfiltrate data. The feature that justifies EmDash&#8217;s existence simply <a href=\"https:\/\/overcentral.com\/en\/rascal-does-not-dream-trailer-release-80139\/\" title=\"Rascal Does Not Dream Drops Trailer for Final Film\" data-iacss-internal=\"1\">does not<\/a> exist on self-hosted infrastructure.<\/p>\n<p>The <a href=\"https:\/\/www.cloudflare.com\/plans\/developer-platform\/\" target=\"_blank\" rel=\"sponsored noopener noreferrer\" data-iacss-external=\"1\">Cloudflare Workers Paid Plan<\/a> costs $5\/month. That&#8217;s cheap. But the dependency is structural. You cannot replicate the V8 isolate sandbox on any other cloud provider. AWS Lambda, Google Cloud Functions, Azure Functions \u2014 none of them offer a runtime that can dynamically create and destroy sandboxed execution environments with sub-millisecond cold starts. EmDash&#8217;s plugin architecture is a Cloudflare-specific capability.<\/p>\n<h3>Database: D1 Is SQLite, But It&#8217;s Cloudflare&#8217;s SQLite<\/h3>\n<p>EmDash uses D1 by default, Cloudflare&#8217;s serverless SQLite database. D1 is built on top of SQLite, which is portable in theory. You can export your data. But D1 has features that standard SQLite doesn&#8217;t \u2014 global replication, HTTP-based query API, integration with Workers. Migrate away from Cloudflare, and you&#8217;re running raw SQLite on your own server. No replication. No global read distribution. Your site&#8217;s performance profile changes completely.<\/p>\n<p>The migration path exists. D1 exports to standard SQLite format. But the operational model you designed around \u2014 zero-effort global reads \u2014 disappears.<\/p>\n<h3>Storage: R2 Is S3-Compatible, but the Integration Isn&#8217;t<\/h3>\n<p>R2 is Cloudflare&#8217;s object storage. It uses the S3 API. AWS S3, Backblaze B2, and MinIO all speak S3. In theory, you can point EmDash at any S3-compatible provider.<\/p>\n<p>In practice, EmDash&#8217;s media handling assumes R2&#8217;s specific behavior \u2014 zero egress fees, integration with Cloudflare&#8217;s image optimization pipeline, Workers-based access patterns. Switch to AWS S3, and you&#8217;re paying egress. Switch to Backblaze, and you lose the tight Workers integration. The code still works. The economics and performance change.<\/p>\n<h2>The Strongest Counterargument \u2014 and Why It Falls Apart<\/h2>\n<p>The most common defense of EmDash&#8217;s portability goes like this: &#8220;The data is portable. D1 is SQLite. R2 is S3. You can move your content anywhere. The code is MIT licensed. You&#8217;re not locked into anything except your own preferences.&#8221;<\/p>\n<p>This sounds reasonable. It&#8217;s also incomplete.<\/p>\n<p>Data portability and operational portability are different things. Yes, you can export your SQLite database and dump your R2 bucket into AWS S3. But EmDash&#8217;s value proposition isn&#8217;t just &#8220;store content.&#8221; It&#8217;s &#8220;store content securely, run plugins in isolation, and serve pages at the edge with zero cold starts.&#8221; Move off Cloudflare, and two of those three features disappear. You&#8217;re left with a basic Node.js CMS that has fewer plugins, less community support, and no security advantage over WordPress.<\/p>\n<p>The lock-in isn&#8217;t about data. It&#8217;s about the runtime. Cloudflare owns the runtime that makes EmDash worth using. That&#8217;s not a bug \u2014 it&#8217;s the product.<\/p>\n<h2>The Billing Risk Nobody Is Talking About<\/h2>\n<p>Serverless billing is unpredictable. EmDash on Cloudflare uses Workers (per-request billing), D1 (per-row billing), R2 (per-operation billing), and KV (per-read\/write billing). A single page view can hit four different billing meters simultaneously.<\/p>\n<p>Traditional WordPress hosting: $20\/month, flat rate, no surprises. EmDash on Cloudflare: $5\/month base, but a traffic spike or bot attack can drive costs into the hundreds or thousands. Cloudflare does not offer a global spending cap. You can set CPU time limits per request. You can configure WAF rate limiting per IP. But a distributed attack from thousands of unique IPs bypasses per-IP limits. Your bill climbs. You have no kill switch.<\/p>\n<p>WordPress hosts throttle or crash under load. Your bill stays the same. EmDash keeps running and charging.<\/p>\n<h2>What Leaving Actually Costs<\/h2>\n<p>Let&#8217;s be specific about the migration effort. You have:<\/p>\n<ul>\n<li>A D1 database with your content, user data, and plugin state<\/li>\n<li>R2 buckets with your media library<\/li>\n<li>Workers running your site&#8217;s frontend and plugin execution<\/li>\n<li>KV stores for sessions and plugin metadata<\/li>\n<li>Zero egress fees on R2 (you lose this immediately)<\/li>\n<\/ul>\n<p>Moving to a standard Node.js server means:<\/p>\n<ul>\n<li>Export D1 to SQLite, configure a new database connection<\/li>\n<li>Migrate R2 files to S3-compatible storage (pay egress)<\/li>\n<li>Rewrite any plugin that depends on Workers-specific APIs<\/li>\n<li>Accept that plugins now run without sandbox isolation<\/li>\n<li>Set up your own caching and CDN (losing Cloudflare&#8217;s edge network)<\/li>\n<\/ul>\n<p>This is a days-to-weeks engineering project for a small site. For a site with custom plugins, WooCommerce-like functionality, or complex content structures, it&#8217;s a rewrite.<\/p>\n<h2>The Real Comparison<\/h2>\n<p>WordPress runs on any server with PHP and MySQL. You can switch hosts in an afternoon. Your plugins, themes, and content move with you. The code is GPL, which has its own licensing friction, but the <em>infrastructure<\/em> is free.<\/p>\n<p>EmDash&#8217;s code is MIT. The infrastructure is Cloudflare. The code is portable. The features are not.<\/p>\n<p>That&#8217;s not necessarily a dealbreaker. Cloudflare is a reliable, well-funded company. Their infrastructure is excellent. But &#8220;open source&#8221; implies a certain kind of freedom. EmDash offers freedom from licensing restrictions \u2014 not freedom from vendor dependency.<\/p>\n<h2>What Would Real Portability Look Like?<\/h2>\n<p>A genuinely portable EmDash would need a standardized plugin sandbox runtime that works on any cloud provider or bare metal. That doesn&#8217;t exist today. Cloudflare&#8217;s dynamic workers are proprietary. No other provider offers an equivalent.<\/p>\n<p>The MIT license means you could build an alternative runtime. But that&#8217;s a massive engineering effort \u2014 likely larger than building EmDash itself. And it would defeat the purpose: Cloudflare built EmDash to drive adoption of Cloudflare infrastructure.<\/p>\n<h2>The Honest Bottom Line<\/h2>\n<p>EmDash is a smart product with a real security advantage over WordPress. But the advantage is tied to Cloudflare&#8217;s platform. If you adopt EmDash, you are choosing Cloudflare as your infrastructure partner. Not just for hosting, but for the runtime that powers your CMS&#8217;s core differentiator.<\/p>\n<p>That&#8217;s fine if you trust Cloudflare and accept the dependency. It&#8217;s not fine if you want the portability that &#8220;open source&#8221; traditionally promises.<\/p>\n<p>The strongest argument for EmDash is its architecture. The strongest argument against it is that the architecture locks you in. Both are true.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cloudflare wants you to believe EmDash is free, open source, and portable. The code is MIT licensed. You can fork it, run it locally, even deploy it to a bare Node.js server. But the headline feature \u2014 sandboxed plugins \u2014 requires Cloudflare&#8217;s paid infrastructure to function. That&#8217;s not an accident. That&#8217;s architectural lock-in dressed in [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":100454,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98098.png","fifu_image_alt":"EmDash Vendor Lock-In: The Real Cost of Leaving Cloudflare","footnotes":""},"categories":[31],"tags":[],"class_list":["post-98098","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology"],"fifu_image_url":"https:\/\/cards.overcentral.com\/cards\/en\/98098.png","fifu_image_alt":"EmDash Vendor Lock-In: The Real Cost of Leaving Cloudflare","_links":{"self":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98098","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/comments?post=98098"}],"version-history":[{"count":1,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98098\/revisions"}],"predecessor-version":[{"id":100455,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/posts\/98098\/revisions\/100455"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media\/100454"}],"wp:attachment":[{"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/media?parent=98098"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/categories?post=98098"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/overcentral.com\/en\/wp-json\/wp\/v2\/tags?post=98098"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}