Radar 2.0's Stack
Cloudflare Radar 2.0, released during Birthday Week, is a full revamp of the original product. The goal was straightforward: make it easier to navigate our data and find insights, with a faster, cleaner user experience. From an engineering standpoint, the project also served as a proof point—demonstrating that a complex, multi-layered application can be built entirely on Cloudflare's developer platform.


The architecture breaks down into three distinct layers. The Core layer contains the data lake, exploration tools, and backend API. The Cloudflare network layer hosts the public-facing APIs and runs the application itself. The Client layer is the browser-based web app.

Running the App: Pages and Remix
Radar 2.0 is deployed on Cloudflare Pages, which now supports custom Workers scripts through its Functions feature. This enables server-side computing—like rendering the app and serving the frontend API—without needing a separate Worker deployment or a traditional Node.js server. Functions also grant access to Durable Objects, KV, R2, and D1, just like a standard Worker.
The frontend uses Remix, which is designed around a server/client model. Remix reduces the amount of JavaScript, CSS, and JSON sent over the wire by pre-rendering DOM components and pre-fetching API calls on the server. The browser receives fully-formed HTML with only the necessary assets attached. Remix runs on Cloudflare Workers and Pages, eliminating the need for a dedicated Node.js server.
Remix routes handle user interactions and data changes. Each route can export a loader for GET requests, an action for POST, PUT, PATCH, and DELETE submissions, and a default export for the React UI. Routes without a default export return only data, which is useful for API endpoints. A simplified Radar route for the Outage Center illustrates how these pieces fit together.
import { createPagesFunctionHandler } from "@remix-run/cloudflare-pages";
import * as build from "@remix-run/dev/server-build";
const handleRequest = createPagesFunctionHandler({
build: {
...build,
publicPath: "/build/",
assetsBuildDirectory: "public/build",
},
mode: process.env.NODE_ENV,
getLoadContext: (context) => ({
...context.env,
CF: (context.request as any).cf as IncomingRequestCfProperties | undefined,
}),
});
const handler: ExportedHandler<Env> = {
fetch: async (req, env, ctx) => {
const r = new Request(req);
return handleRequest({
env,
params: {},
request: r,
waitUntil: ctx.waitUntil,
next: () => {
throw new Error("next() called in Worker");
},
functionPath: "",
data: undefined,
});
},
};import type { MetaFunction } from "@remix-run/cloudflare";
import { useLoaderData } from "@remix-run/react";
import { type LoaderArgs } from "@remix-run/server-runtime";
export async function loader(args: LoaderArgs) {
const ssr = await initialFetch(SSR_CHARTS, args);
return { ssr, };
}
export default function Outages() {
const { ssr } = useLoaderData<typeof loader>();
return (
<Page
filters={["timerange"]}
title={
<>
<Svg use="icon-outages" />
{t("nav.main.outage-center")}
</>
}
>
<Grid columns={[1, 1, 1, 1]}>
<Card.Article colspan={[1, 1, 1, 1]} rowspan={[1, 1, 1, 1]}>
<Card.Section>
<Components.InternetOutagesChoropleth ssr={ssr} />
</Card.Section>
<Divider />
<Card.Section>
<Components.InternetOutagesTable ssr={ssr} />
</Card.Section>
</Card.Article>
</Grid>
</Page>
);
}
Server-side rendering (SSR) also brings measurable performance gains. Metrics like Cumulative Layout Shift (CLS), First Contentful Paint (FCP), and Largest Contentful Paint (LCP) improve when the number of network fetches is reduced and the DOM is pre-rendered. Cloudflare TV saw significant improvements after porting to Remix, and Radar's desktop Lighthouse scores now approach 100% across Performance, Accessibility, Best Practices, and SEO.


Cloudflare's Speed product, specifically Early Hints, contributes to the fast load times. Early Hints uses the HTTP 103 status code to tell the browser which assets will be needed before the main response is ready, cutting perceived latency dramatically.

Two APIs, One Front Door
Radar relies on two separate APIs. The backend API has direct access to our internal data sources, while the frontend API is public and powers both the Radar website and third-party consumers.
Backend API
The backend API is written in Python, using Pandas and FastAPI. This choice lets data scientists and engineers collaborate easily, since the same tools (JupyterHub and Jupyter Notebooks) are used for data exploration and prototyping. The API is shielded by Cloudflare Access, JWT token validation, and authenticated origin pulls (AOP). It communicates with the frontend API through a GraphQL server built with Strawberry. GraphQL's query flexibility is valuable for internal analysts building reports from our data lake.
Frontend API on Workers
The frontend API runs as a Cloudflare Worker. Its primary jobs are to fetch and transform data from the backend via GraphQL, and to expose a public REST API. Operating as a Worker adds several practical features:
- Fine-grained control over caching with the Cache API, including support for POST requests and custom cache-control headers.
- Stale response serving from R2. If the backend API fails but a stale response is cached, that response is served from R2 to keep end users going.
- Both CSV and JSON output formats. CSV makes the data directly consumable in analysis tools and spreadsheets.
The frontend API also supports OpenAPI 3. We built a custom library on top of itty-router that automatically generates an OpenAPI schema and validates incoming requests against it. That work is now open source as itty-router-openapi, available on GitHub for anyone building Workers with similar requirements.
In addition, we published developer documentation for the Radar API. The API itself is free, which we hope encourages academics and data enthusiasts to explore global Internet trends. A Colab Notebook template is also available to simplify initial experimentation.

Inside the Radar 2.0 front end
The Radar App is built with Remix and leans heavily on data visualization. For that, Cloudflare assembled a component library from two open-source foundations: visx, which provides low-level React visualization primitives, and D3 for data-driven DOM manipulation. MapLibre handles the map rendering. The result is a set of reusable widgets, including the animated attack map the team calls “PewPew.”

Using the component in a page is a matter of dropping in the Remix React component:
<Card.Section
title={t("card.attacks.title")}
description={t("card.attacks.description")}
>
<Flex gap={spacing.medium} align="center" justify="flex-end">
<SegmentedControl
label="Sort order:"
name="attacksDirection"
value={attacksDirection}
options={[
{ label: t("common.source"), value: "ORIGIN" },
{ label: t("common.target"), value: "TARGET" },
]}
onChange={({ target }: any) => setAttacksDirection(target.value)}
/>
</Flex>
<Components.AttacksCombinedChart
ssr={ssr}
height={400}
direction={attacksDirection}
/>
</Card.Section>
Radar 2.0 also switched its graphical assets to SVG. The format has several advantages over bitmaps: it is vector-based, so it renders crisply at any resolution; it is small and efficient to transmit; and because SVG files are XML text, they can be indexed, manipulated, and localized. That last point matters for accessibility—screen readers and translation tools can handle SVG content more naturally than raster images.

The team uses React Cosmos as a sandbox for building and testing UI components in isolation. It fits Radar’s needs well because the front end is highly visual, the components are reused across many pages, and the team is multidisciplinary—engineers, designers, and other stakeholders can all open the component library, tweak options in real time, and see the result. That shortens iteration and improves communication across roles.

A faster pipeline
Continuous integration was a pain point for Radar 1.0. A simple fix could take 30 minutes from commit to deployment. For Radar 2.0, the team rebuilt the pipeline around Cloudflare Pages and Workers, using Bitbucket and TeamCity internally. The workflow builds, tests, and deploys within minutes of an approved pull request and merge.
Unit tests run with Vitest; end-to-end tests use Playwright. Visual regression testing is on the roadmap, and Playwright’s snapshot support will cover it. Multiple staging environments sit between the test suite and production, and the CI/CD setup makes environment switching and rollbacks straightforward via Pages preview deployments, aliases, and branch build controls.
The biggest win was speed. By caching intelligently during builds and running tests asynchronously for commits outside release branches, Cloudflare shrank deployment time to seconds. Now every push to any branch generates a preview link, and notifications go straight to the team’s chat.

Those fast previews changed the workflow. An engineer can move from idea to a fully working, end-to-end Radar instance on a link that a product manager or teammate can click immediately.
Accessibility and localization from the start
Cloudflare has publicly committed to accessibility standards across its properties, and Radar 2.0 treats it as a design constraint rather than an afterthought. The design system follows Cloudflare’s brand guidelines and incorporates WCAG best practices around color contrast, tags, and SVG usage.
Localization is a separate engineering requirement. Choosing libraries and frameworks that make translation manageable from the beginning avoids rewrites later. Radar’s approach is straightforward: all UI strings live in locale JSON files, so adding a language means translating one file, not touching code.
{
"abbr.asn": "Autonomous System Number",
"actions.chart.download.csv": "Download chart data in CSV",
"actions.chart.download.png": "Download chart in PNG Format",
"actions.chart.download.svg": "Download chart in SVG Format",
"actions.chart.download": "Download chart",
"actions.chart.maximize": "Maximize chart",
"actions.chart.minimize": "Minimize chart",
"actions.chart.share": "Share chart",
"actions.download.csv": "Download CSV",
"actions.download.png": "Download PNG",
"actions.download.svg": "Download SVG",
"actions.share": "Share",
"alert.beta.link": "Radar Classic",
"alert.beta.message": "Radar 2.0 is currently in Beta. You can still use {link} during the transition period.",
"card.about.cloudflare.p1": "Cloudflare, Inc. ({website} / {twitter}) is on a mission to help build a better Internet. Cloudflare's suite of products protects and accelerates any Internet application online without adding hardware, installing software, or changing a line of code. Internet properties powered by Cloudflare have all web traffic routed through its intelligent global network, which gets smarter with every request. As a result, they see significant improvement in performance and a decrease in spam and other attacks. Cloudflare was named to Entrepreneur Magazine's Top Company Cultures 2018 list and ranked among the World's Most Innovative Companies by Fast Company in 2019.",
"card.about.cloudflare.p2": "Headquartered in San Francisco, CA, Cloudflare has offices in Austin, TX, Champaign, IL, New York, NY, San Jose, CA, Seattle, WA, Washington, D.C., Toronto, Dubai, Lisbon, London, Munich, Paris, Beijing, Singapore, Sydney, and Tokyo.",
"card.about.cloudflare.title": "About Cloudflare",
...
More languages are planned for release.
Reports without the manual grind
Radar Reports—long-form analyses of topics like quarterly DDoS trends or IPv6 adoption—start as Jupyter Notebooks. Data scientists iterate on a theme inside an internal Jupyter Hub, then produce a notebook for publication.
Under Radar 1.0, converting that notebook into a polished Radar page was a slow, manual process involving engineering and design resources. Updating a published report was equally painful. Radar 2.0 automates the entire workflow. A notebook that follows a set of internal rules is converted to HTML automatically, with the output and assets hosted in R2, and pushed to the Reports page. The generated pages follow the Radar design system, so they look like native parts of the app rather than embedded documents.

The conversion tool is eventually slated to be open sourced.
The Cloudflare layer
Many of the features that keep Radar running are Cloudflare products configured through the dashboard or API. DDoS protection, WAF, and Bot Management filter malicious traffic before it reaches the application, governed by rules like these:

Bulk Redirects handle traffic from the old Radar site to the new one; redirect lists are managed directly in the dashboard. Anything available in the dashboard is also accessible via Cloudflare’s APIs, and the Terraform provider covers infrastructure-as-code workflows. Wrangler, the command-line tool for Workers and Pages, supports local emulation of the full stack before deploying.
Radar 2.0 is an example of building an application on top of Cloudflare’s platform rather than managing infrastructure directly. The team plans to keep iterating, share what it learns, and open-source more of its tooling. Feedback and questions are welcome in the Radar room on the Cloudflare Developers Discord server, and updates are posted on Twitter at @cloudflareradar.



