How I Built a Global Edge API for SEO Analysis Using Cloudflare Workers
When I first started building my SaaS, I thought the hardest part would be the core product logic. I was wrong. The real nightmare was the infrastructure. I wanted to build an SEO analysis tool that could fetch and parse
When I first started building my SaaS, I thought the hardest part would be the core product logic. I was wrong. The real nightmare was the infrastructure. I wanted to build an SEO analysis tool that could fetch and parse web pages quickly, no matter where the user was located. I initially set up standard serverless API routes in a single region. It worked fine for me in North America, but when I tested it from Europe and Asia, the latency was brutal. Fetching a remote webpage and parsing its HTML took forever. I was spending more time tweaking regional deployments than actually building features. So I decided to build something.
The Problem with Centralized APIs
The problem with centralized serverless functions for web scraping or SEO analysis is simple: physics. If your API is hosted in a single US data center, a user in Tokyo is waiting for the request to travel across the Pacific, the server to fetch the target URL, parse the HTML, and send the response back. For an SEO checker, this means analyzing a single page could take several seconds.
Why does this matter? Because in developer tools, perceived performance is everything. If a tool feels sluggish, developers assume the underlying data is stale or the architecture is flawed. The cost of ignoring edge computing isn't just a few extra milliseconds; it's user frustration and abandonment. But building a custom edge network from scratch is a massive time sink. I needed a way to run my API logic as close to the user as possible without managing a fleet of global servers.
Moving to the Edge
The solution was to move the heavy lifting to the edge using Cloudflare Workers, while keeping the main application logic in Next.js.
In my stack, Next.js 14 handles the frontend, authentication via NextAuth.js, and the Stripe billing integration. But for the actual SEO analysisβfetching the target URL and extracting the metadataβI offloaded that to a Cloudflare Worker.
Here is a simplified version of the edge worker I use to analyze pages:
// Cloudflare Worker for edge SEO analysis
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname !== '/api/analyze') {
return new Response('Not found', { status: 404 });
}
const targetUrl = url.searchParams.get('url');
if (!targetUrl) {
return new Response(JSON.stringify({ error: 'Missing url' }), {
status: 400,
headers: { 'Content-Type': 'application/json' },
});
}
// Fetch target page at the edge (low latency worldwide)
const response = await fetch(targetUrl, {
cf: { cacheTtl: 300, cacheEverything: true },
});
const html = await response.text();
// Run SEO checks (regex-based, no DOM needed)
const title = html.match(/<title[^>]*>([^<]*)<\/title>/i)?.[1] || '';
const desc = html.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']*)["']/i)?.[1] || '';
const h1Count = (html.match(/<h1[ >]/gi) || []).length;
return new Response(JSON.stringify({ title, desc, h1Count }), {
headers: { 'Content-Type': 'application/json' },
});
},
};
Let's break down the key decisions here.
First, the fetch call includes a Cloudflare-specific cf object. By setting cacheTtl: 300 and cacheEverything: true, I'm telling the edge network to cache the raw HTML response for 5 minutes. If another user asks to analyze the same URL shortly after, the worker doesn't even need to fetch it again; it just serves the cached HTML instantly.
Second, I kept the parsing extremely lightweight. Running a full headless browser or a heavy DOM parser at the edge is resource-intensive and can hit CPU limits. Since we only need basic SEO metrics (title, meta description, H1 count), a few simple regular expressions are more than enough. This keeps the worker execution time in the single-digit milliseconds.
While the edge worker handles the heavy analysis, the Next.js App Router handles the user dashboard and billing. Integrating Stripe subscriptions is often a pain point for indie devs, so having a production-ready setup is crucial. Here is how the checkout session is handled in the App Router:
// Next.js API route for Stripe checkout (App Router)
import { NextResponse } from 'next/server';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
export async function POST(req: Request) {
const { priceId, userId } = await req.json();
const session = await stripe.checkout.sessions.create({
mode: 'subscription',
payment_method_types: ['card'],
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${process.env.APP_URL}/dashboard?success=true`,
cancel_url: `${process.env.APP_URL}/pricing?cancelled=true`,
client_reference_id: userId,
});
return NextResponse.json({ url: session.url });
}
This keeps the billing logic cleanly separated in the main application, while the edge worker remains purely focused on the high-latency task of fetching and parsing external web pages.
Practical Results
Moving the analysis logic to the edge changed the feel of the tool completely. For example, a user in Tokyo might see response times drop from 800ms to under 150ms because the worker runs in a data center just miles away from them.
What surprised me the most was how much simpler the regex approach was compared to my initial attempts at using DOM parsers. It forced me to focus on the actual data I needed rather than over-engineering the parser.
If I were to change anything, I'd probably add a fallback mechanism. Regex works great for standard server-rendered HTML, but if a target site relies heavily on client-side rendering, the raw HTML won't contain the meta tags. In the future, I might integrate a lightweight rendering service for those specific edge cases, but for the vast majority of standard SEO checks, this edge approach is highly effective.
Try It Yourself
If you want to see this edge architecture in action, or if you just need to quickly check the SEO fundamentals of a landing page, I've packaged this exact worker logic into a free tool. You can try the SEO Checker here: https://saaslaunch.dev/free-tools/seo-checker
If you're building your own SaaS and want to skip the infrastructure setup, the whole stack (Next.js, Stripe, NextAuth, and these Cloudflare Workers) is available in the SaaSLaunch boilerplate.
Full disclosure: I'm the developer of SaaSLaunch. I built this because I needed it myself.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.