In-app reader
Blog Cloudflare WorkersDeveloper PlatformDevelopers** +2 Show 2 more tags
** 5 Tags Show 5 tags
_**
Selected Tags
Cloudflare WorkersDeveloper PlatformDevelopersEmDashPerformance
All tags
Matching tags
No tags found
1.1.1.1
2FA
Abuse
Access
Access Control Lists (ACLs)
Accessibility
Account Takeover
Acquisitions
Addressing
Advanced Certificate Manager
Advanced DDoS
Advertising
Aegis
AEO
Africa
Afroflare
Agent Cloud
Agent Development Lifecycle
Agent Readiness
Agents
Agents Week
Agents Week 2026
AI
AI Bots
AI Gateway
AI Search
AI-SPM
AI WAF
AI Week
Alertmanager
Always Online
AMD
AMP
Analytics
Anonymous
Anti Malware
Anycast
API
API Gateway
API Security
API Shield
APJC
Apple
Application Security
Application Services
Area 1 Security
Argo Smart Routing
ASCII
Asia
Athenian Project
Atlassian
Attacks
Audit Logs
Austin
Australia
Authentication
Authy
Automatic HTTPS
Automatic Platform Optimization
Automation
AutoMinify
Auto Rag
Awards
AWS
Baidu
Bandwidth Alliance
Bandwidth Costs
Best Practices
Beta
Better Internet
BGP
Billing
Birthday Week
Blackbird
Black Friday
Bot Fight Mode
Bot Management
Botnet
Bots
BPF
Brand
Brand Protection
Brazil
Browser Insights
Browser Rendering
Browser Run
Bug Bounty
Bugs
BYOIP
Cache
Cache Purge
Cache Reserve
Cache Rules
California
Canada
Cap'n Proto
CAPTCHA
Careers
CASB
Categories
CDN
CDNJS
Certificate Authority
Certificate Pinning
Certificate Transparency
Certification
CFSSL
Challenge Page
ChatGPT
China
China Network
Christmas
Chrome
CIO Week
CISA
Claire
CLI
ClickHouse
Clientless
Clientless Web Isolation
Cloud Connector
Cloud Email Security
Cloudflare Access
Cloudflare Apps
Cloudflare Area 1
Cloudflare Calls
Cloudflare Email Service
Cloudflare for Campaigns
Cloudflare for SaaS
Cloudflare for Startups
Cloudflare Gateway
Cloudflare History
Cloudflare Images
Cloudflare Media Platform
Cloudflare Meetups
Cloudflare Network
Cloudflare One
Cloudflare One Client
Cloudflare One User Risk Score
Cloudflare One Week
Cloudflare OS
Cloudflare Pages
Cloudflare Polish
Cloudflare Queues
Cloudflare Realtime
Cloudflare Stream
Cloudflare Tunnel
Cloudflare TV
Cloudflare Workers
Cloudflare Workers KV
Cloudflare Workers KV (ES)
Cloudflare Workers (PT)
Cloudflare Zero Trust
Cloudforce One
Cloudy
Code Orange
Coinbase
Colombia
Community
Compliance
Compression
Config Rules
Configuration Management
Congestion Control
Connectivity
Connectivity Cloud
Consumer Services
Containers
Content Independence Day
Content Scanning
Context
Core
COVID-19
Crawler Hints
CrowdStrike
Cryptography
Crypto Week
CSAM Reporting
Customers
Customer Success
Customer Zero
CVE
CVE-2023-50387
Cyber Readiness
Cybersecurity
D1
Dashboard
Data
Database
Data Catalog
Data Center
Data Localization
Data Localization Suite
Data Loss
Data Loss Prevention
Data Platform
Data Privacy Day
Data Protection
Data Sovereignty
Data Transfer Bucket
DDoS
DDoS Alerts
DDoS Reports
Debugging
Deep Dive
Descaler
Design
Deskope
Developer Documentation
Developer Platform
Developers
Developer Spotlight
Developers Storage
Developer Week
Device Security
DevOps
DEX
Digital Experience Monitoring
Digital Forensics
Disrupt
Distributed
Distributed Systems
Distributed Web
Diversity
DLP
DMARC
DNS
DNS Filtering
DNS Flood
DNSSEC
DNS Security
Dogfooding
DoH
Domain Rankings
Domain Scoped Roles
dosd
Drupal
Due Process
Durable Execution
Durable Objects
Early Hints
Earth Day
eBPF
EC2
eCommerce
Edge
Edge Computing
Edge Database
Edge Rules
Education
Egress
Elastic
Elections
Election Security
Elliptic Curves
Email Routing
Email Security
Email Workers
EmDash
Emissions
Employee Resource Groups
Encrypted SNI
Encryption
Engineering
Enterprise
Entropy
EPYC
Ethereum
Europe
European Union
Events
Exploit
Fancy Bear
Fast Fonts
FCC
Feature Flags
FedRAMP
FedRAMP High
FedRAMP Moderate
Firefox
Firewall
Firmware
Florida
Football
Formal Methods
Forrester
Fortran
Foundation DNS
Founders' Letter
France
Fraud
Free
Freedom of Speech
Front End
Full Stack
Full Stack Week
Fun
Gartner
Gatebot
GA Week
GDPR
General Availability
Generative AI
Gen X
Geo Key Manager
Germany
GitHub
Go
Google Analytics
Google Cloud
Google Workspace
Government Innovation
Grace Hopper
Grafana
GraphQL
Green
Grinch
Growth
gRPC
Guest Post
Hackathon
Halloween
Hardware
HashiCorp
Hertzbleed
Heuristics
History
Holidays
Holocaust
Hong Kong
Hosting Con
Hostnames
HTTP2
HTTP3
HTTPS
Human Rights
Hurricane
Hybrid Cloud
Hyperdrive
IBM
ICANN
iCloud Private Relay
Identity
IETF
IETF Standards
IL4
Image Optimization
Image Recognition
Image Resizing
Image Storage
Impact
Impact Week
I'm Under Attack Mode
Incident Report
Incident Response
India
Indicators of Compromise
Indonesian
Inference
Infrastructure
Infrastructure as Code
Insights
Intel
Interconnection
Internal DNS
Internet Performance
Internet Quality
Internet Regulation
Internet Shutdown
Internet Summit
Internet Traffic
Internet Trends
Internship Experience
Intrusion Detection
Investors
IoCs
iOS
IoT
IPFS
IPsec
IPv4
IPv6
IRAP
Israel
Italy
IWD
JAMstack
Japan
JavaScript
Jengo
Jengo Policy
Joomla
Judeoflare
Kafka
Kernel
Keyless SSL
KeyTrap
Key Value
Killnet
Korea
Kubernetes
LangChain
Latency
Latin America
Latinflare
LavaRand
Lazarus group
Leaked Credential Checks
Legal
Legal Patents Sable
LGBTQIA+
Life at Cloudflare
Linux
Lisbon
Live Streaming
Llama
LLM
Load Balancing
Localization
Log4J
Log4Shell
Logging
Log Push
Logs
LUA
Machine Learning
Magecart
Magic Firewall
Magic Network Monitoring
Magic Transit
Magic WAN
Magic WAN Connector
Malicious JavaScript
Malware
Managed Components
Managed Rules
March of Cloudflare
MASQUE
MCP
Meerkat
MeetUp
Meris
Message Protocol
Mexico
Micro-frontends
Microsoft
Microsoft 365
Microsoft Azure
Middle East
Migration Hub
Milestones
Miniflare
Mirage
Mirai
Mitel
Mitigation
Mixed Content Errors
MLops
Mobile
Mobile SDK
Model Context Protocol
Moldova
Monitoring
Multi-Cloud
Multi-User
MySQL
NaaS
Net Neutrality
Network
Networking
Network Interconnect
Network Performance Update
Network Protection
Network Services
New Year
NGINX
Ninjas
NIST
Node.js
North America
Notebooks
Notifications
NSEC3
OAuth
Observability
Oceania
OCSP
Offices
Okta
Olympics
Onboarding
OpenAI
Open API
OpenBMC
OpenDNS
Open Source
OpenSSL
OpenTelemetry
Optimization
Origin Rules
Outage
Oxy
Pacific Northwest
Page Rules
Page Shield
Parallels
Partners
Partnership
Password-reuse
Passwords
Passwords (PT)
Patents
PAYGO
Payments
Pay Per Crawl
PCI Certified
Peering
Performance
Phishing
php
Phython
Pingora
Pipelines
PlanetScale
Plans
Platform Engineering
Platform Week
Plesk
Policy & Legal
Politics
Portugal
Postgres
Post Mortem
Post-Quantum
Precursor
Prepared Statements
Prisma
Privacy
Privacy Pass
Privacy Week
Private IP
Private Network
Product Design
Product News
Programming
Programming (PT)
Project Fair Shot
Project Galileo
Project Honey Pot
Project Pangea
Project Safekeeping
Project Turpentine
Prometheus
Protocols
Proudflare
Proxying
Public Sector
Python
Python Workers
Quantization
Queues
QUIC
QUICHE
Quicksilver
R2
R2 Super Slurper
Radar
Radar Alerts
Radar API
Radar Maps
Railgun
Randomness
Ransom Attacks
Rapid Reset
Raspberry Pi
Rate Limiting
RC4
RDDoS
React
Reading List
Real-time
Recruiting
Regional Services
Registrar
Reliability
Remote Browser Isolation
Remote Desktop Protocol
Remote Work
Replication
Research
Resolver
Restreaming
Retreat
Reverse Engineering
REvil
Risk Management
Road to Zero Trust
Rocket Loader
RocksDB
Routing
Routing Security
RPC
RPKI
RRDNS
RSA
Russia
Rust
Rust Workers
SaaS
SAAS Security
Sable
Salt
Sampling
Sandbox
SASE
Save The Web
SDK
Search Engine
Secrets Store
Secure Web Gateway
Security
Security Analytics
Security Center
Security Posture
Security Posture Management
Security Service Edge
security.txt
Security Week
SEO
Serverless
Serverless AI
Serverless (PT)
Serverless Week
Server Push
Servers
SIEM
Signed Exchanges (SXG)
SIM
Singapore
Single Sign On (SSO)
Smart Placement
Smart Shield
Snippets
SOC as a Service
South Africa
South America
Spain
spdy
Spectrum
Speed
Speed Brain
Speed & Reliability
Speed Week
Spoofing
Sports
SQL
SRE
SSE
SSH
SSL
Standards
Startup Enterprise Plan
Statistics
StopTheHacker
Storage
Sumo Logic
Super Bowl
Supercloud
Supply Chain Attacks
Support
Sustainability
SWAG
SWG
Swift
Switzerland
SXSW
SYN
SYN Flood
Syria
TCP
Team
Teams Dashboard
TechCrunch
Technical Writing
Tech Talks
Terraform
Testimonials
Testing
Texas
Thanksgiving
The Serverlist Newsletter
Threat Data
Threat Feeds
Threat Intelligence
Threat Operations
Threat Report
Threats
Tiered Cache
TikTok
TLS
TLS 1.3
Tools
Tor
Tracing
Traffic
Transform Rules
Transparency
Trends
Trust & Safety
TTFB
TTL
TURN
TURN Server
Turnstile
TypeScript
UDP
Ukraine
United Kingdom
Universal SSL
URL Scanner
USA
User Research
VDI
Vectorize
Vetflare
Video
Visibility
Vite
VoIP
VPC
VPN
Vulnerabilities
WAF
WAF Attack Score
WAF Rules
Waiting Room
WARP
WARP Connector
WASM
Web3
Web Application Firewall
WebAssembly
Web Asset Discovery
Webinars
WebMCP
WebP
WebRTC
WebSockets
Wildebeest
Womenflare
WordPress
Workers AI
Workers Launchpad
Workers Logs
Workers Observability
Workers Sites
Workers Unbound
Workers VPC
Workflows
World IPv6 Day
Wrangler
x402
Year in Review
Z3
Zaraz
Zero Day Threats
Zero Trust
Zero Trust Week
Zone Versioning
EmDashPerformance
Cloudflare WorkersDeveloper PlatformDevelopersEmDashPerformance
August 24, 2026
**Kody Jackson , **Diogo Carneiro , and **Amy Dutton
11 minute read
** COPY URL
You likely noticed the recent redesign of the Cloudflare Blog. We added dark mode, modernized the look and feel, and made a lot of other small improvements along the way.
What you might not have noticed – well, except for those who are more terminally online – is that the redesign was part of a much bigger migration project. On Wednesday, August 12, we moved the blog to EmDash, a content management system (CMS) built especially to work on Astro and with Cloudflare.
We’ll take you into the migration story – what we learned and how EmDash got better – as well as into the benefits we’re already seeing from a new platform.
At Cloudflare, Cloudflare itself is Customer Zero. This means that we use our products. And – in use – we make them better for ourselves and our customers.
This is a very real cultural value at Cloudflare. The burden of proof is on you if you want to use an external vendor. Why can’t that team support you, what gaps are there, why can’t those gaps be filled, and are those “gaps” true requirements?
This preference is even enshrined in our internal engineering standards, known as our Codex.
** We don’t just build products for others; we build them to run Cloudflare itself. We are our own first, most demanding customer.
We validate scale, security, and usability on our own massive infrastructure before a paying customer ever touches the product. If a product breaks, it breaks us first. This forces us to fix issues immediately, ensuring that by the time a feature reaches the enterprise, it has already survived the harshest production environment on earth.
With the launch of EmDash and some limitations with our current CMS vendor, we knew that we’d likely be the Customer Zero for EmDash internally at Cloudflare.
When we began our initial migration conversations, we started with two main questions:
Does EmDash work for us?
Can EmDash scale?
Our first question was the most broad, does EmDash work for us? This is something you’d want to know broadly about any new platform, but especially one that’s pre-1.0.
To answer this question, we ran through a bunch of common user flows, such as:
Publishing and unpublishing a post
Authoring a new post
Scheduling a post
Adding media items
By and large, EmDash held up pretty well to these usability tests. The gaps we found were generally related to:
The sheer scale of the Cloudflare Blog (media, content entity search, and bylines)
Nuances around localization, SEO, and Content Security Policies (CSPs)
Usability features for the admin editor – especially ones that might delay the publishing of a post – such as easier findability for custom HTML blocks, bugs in the in-entity content editor, and keeping the formatting toolbar in view for longer posts.
The biggest oversight we found was around scheduled posts, which didn’t work until EmDash version 0.19.0. This gap was understandable given the early version of EmDash, but it was also definitely something we didn’t want to be finding out after the scheduled time for a post.
Our biggest concerns were whether our proposed EmDash setup could handle the traffic we saw on the Cloudflare Blog.
The traffic pattern to our blog is incredibly varied. Normal load sits in the neighborhood of 75 requests per second (RPS), but also spikes up to over 5,000 RPS. Some of these spikes line up with the publishing times of new posts, meaning those posts went viral and attracted a lot of attention. Others happen during all points of the day and night, which likely means folks are sending some extra traffic our way, just to see what happens.
Performance also matters for our systems (and our readers). Cloudflare is a web performance company, after all, so the speed at which a page loads becomes incredibly important.
With those two concerns in mind, we built out some scenarios using k6, an open-source performance testing tool:
Ramp: Where we gradually increase requests up to triple the prod baseline and then cool down.
Breakpoint: Where we ramp from 0 to 100 RPS over 10 minutes, stopping when something breaks.
Burst: Where we throw an immediate traffic load of 7,000 RPS and see what happens.
import { randomPageVisit } from "../random-page-visit.ts";
/**
* Sudden burst to 7,000 RPS.
*/
export const options = {
scenarios: {
burst: {
executor: "constant-arrival-rate",
rate: 7000,
timeUnit: "1s",
duration: "1m",
preAllocatedVUs: 4000,
maxVUs: 10000,
},
},
summaryTrendStats: [
"avg",
"min",
"med",
"max",
"p(90)",
"p(95)",
"p(99)",
"count",
],
thresholds: {
http_req_failed: ["rate],
"http_req_duration{status:200}": ["p(95), "p(99)],
checks: ["rate>0.99"],
},
};
export default randomPageVisit;
**
For each of those scenarios, we evaluated:
**Availability: **Failure when more than 0.01% of HTTP requests lead to 5xx errors, meaning the application couldn’t handle the traffic.
Latency:
P95 latency: Failure when more than 5% of responses exceed 500ms.
P99 latency: Failure when more than 1% of responses exceed 1000ms.
Armed with these tests – and a lot of internal discussion and data points – we came to our production architecture:
EmDash, running on a Cloudflare Worker
Running behind the new Workers Cache (we believe as the first major site to do so)
Using the new EmDash object cache built on Workers KV, which the EmDash team built specifically for our use case.
Using Cloudflare’s new, first-party Hyperdrive integration with PlanetScale.
The multiple layers of caching we put in place play a key role in making the blog both fast and resilient. In the diagram below, they are ordered from top to bottom by proximity to the user:
With this setup, we’re typically serving 99.5% of static files from a cache and 70% of requests from a cache, improving frontend performance and decreasing load on the database.
Once we had that architecture in place, we could start thinking about the frontend redesign as well.
Beyond updating the backend architecture, the migration offered us the perfect opportunity to bring the blog's interface into alignment with Cloudflare’s updated visual language. We rebuilt the frontend experience using patterns established by the Kumo design system, creating visual and structural consistency between the Cloudflare homepage, dashboard, and marketing sites. The result is a cohesive reading experience that feels like a natural extension of the broader Cloudflare ecosystem.
A major priority for this redesign, and a long-overdue request from our readers, was native support for light and dark modes. We implemented theme switching tied directly to system preferences, alongside an explicit toggle, and ensured that accessibility guidelines were strictly met across both themes. Regardless of preference, the updated palette and code syntax highlighting adapt seamlessly without sacrificing legibility.
We also took the opportunity to solve a few long-standing user experience quirks, starting with our email subscription form. Previously, the subscription box lived in the top right corner of the page. Because of its placement, readers frequently mistook it for a search bar and typed their search queries directly into the input field.
To fix this, we moved the email sign-up into a dedicated call-to-action block at the bottom of posts.
Now, once a reader finishes an article and wants to stay updated, the prompt to subscribe appears naturally at the end of a post.
Finally, we introduced two dedicated sidebar features on interior post pages to improve navigation and community engagement. On the right, an "On this page" table of contents tracks your progress and lets you jump directly to specific sections of longer technical posts. On the left, a new "Discuss Online" section makes it effortless to share articles and engage in conversations across social platforms and developer communities.
As we got nearer to our migration, we started focusing on the broader question of “how do we make this change safely?” Ensuring zero downtime for our readers was a non-negotiable requirement, alongside guaranteeing a seamless fallback mechanism if something went wrong at the last minute.
To achieve this, we deployed a proxy Worker to intelligently route traffic between the legacy blog and the new EmDash-powered site. This Worker set a version cookie on requests, which then let us route incoming traffic to the new or legacy experience accordingly. Additionally, this strategy allowed us to fall back to the legacy blog if the new site experienced any 500 errors. Thanks to the flexibility of Cloudflare Workers, this proxy was relatively simple to create and scaled without any issues. The ability to configure a direct worker-to-worker connection through the NEW_BLOG service binding was particularly useful here, as it reduced latency for any end user going through the proxy. This service binding let the proxy Worker dispatch incoming requests directly to the new blog Worker instead of sending them through a public hostname, DNS, TLS, and an outbound HTTP connection.
On launch day, we initiated a gradual rollout, starting at just 1% of total traffic, then incrementally stepping up to 5%, 15%, and beyond as we validated system health. This phased approach allowed us to observe how the platform handled real-world production load while catching a few last-minute edge cases without impacting the vast majority of our audience. By the end of the day, we had comfortably shifted 100% of traffic over to the new platform.
One of our primary objectives for this migration was to deliver a faster, more reliable site to our readers, and the early data shows we accomplished exactly that.
Comparing p95 response latencies between the old architecture (green line) and the new EmDash setup (yellow line) revealed a stark difference. Where the previous platform experienced periodic latency spikes under load, the new system maintains a remarkably flat, consistent response profile. By running EmDash on Cloudflare Workers alongside our new caching layers, we’ve delivered a significantly faster and more performant reading experience across the board.
We’ve seen all these performance gains – and minimal errors – while serving up to 850 RPS.
With this change, the blog also got more accessible for agents, in two distinct ways.
The first is that we released a new Model Context Protocol (MCP) server for the Cloudflare Blog.
An MCP server bundles up a bunch of specific tools that your agent can then use to interact with an external resource, almost like an API for agents.
Using that MCP, you can now use the following tools with your agents:
search_posts
list_posts
get_post
list_tags
With the new, intuitive EmDash APIs and AI search endpoints exposed by our Worker, creating this new MCP took just a few hours o
…(truncated for reading performance)
Discussion
Sign in to join the discussion.
Keep reading
Optional: create a free account to save items, track programs, and sync across web + app. Reading stays free.