DEV Community

seller-mind
seller-mind

Posted on

Why I Chose Edge Computing Over Serverless for SaaS Tooling

When I first started building micro-SaaS tools, I kept running into the same frustrating bottleneck. I was building SEO and analytics utilities that needed to fetch and parse external web pages. Initially, I deployed these tools using standard serverless functions. It worked fine locally, but in production, I was plagued by latency issues and unpredictable cold starts. Every time a user ran a check, they were waiting for a function to spin up in a region hundreds of miles away from the target server. I spent weeks debating whether to refactor my entire stack to a pure serverless architecture with provisioned concurrency, or if I should push the compute entirely to the edge. The trade-offs were confusing, and the documentation for hybrid approaches was scattered. So I decided to build something that solved this for me, and eventually for others.

The core problem with building data-fetching SaaS tools on traditional serverless infrastructure is the network topology. When your function and your target data are in different geographic regions, network hops add up. For an SEO checker or a link analyzer, you are making outbound HTTP requests to arbitrary URLs across the globe.

If you ignore this architectural mismatch, the cost is high. Slow response times lead to a degraded user experience, and users will quickly abandon a tool that takes five seconds to return a simple metadata check. Furthermore, managing state and handling timeouts across distributed serverless regions can become a nightmare.

On the flip side, building a custom edge network from scratch is incredibly complex. You have to manage global routing, handle edge caching manually, and deal with the strict runtime limitations of edge environments. Developers need a practical middle ground that offers global, low-latency compute for I/O bound tasks without the overhead of managing custom infrastructure or paying for provisioned serverless concurrency.

To solve this, I had to objectively compare the two main approaches: pure serverless functions versus dedicated edge workers.

Approach A: Pure Serverless (e.g., standard Vercel or AWS Lambda functions)
Pros: Extremely easy to write, seamless integration with managed databases, and access to the full Node.js ecosystem.
Cons: Cold starts can still occur depending on the provider, and regional latency is inherent when making cross-globe HTTP requests.

Approach B: Dedicated Edge Workers (e.g., Cloudflare Workers)
Pros: Zero cold starts, runs globally in data centers close to the user, and incredibly cost-effective for I/O bound tasks.
Cons: Smaller runtime limits, strict CPU time constraints, and historically lacking native Node.js APIs (though this is rapidly improving).

I chose a hybrid architecture. I used Next.js 14 with the App Router for the core UI, authentication via NextAuth.js, and Stripe for subscription billing. But for the heavy lifting—specifically fetching and analyzing external URLs—I pushed the logic to Cloudflare Workers.

Here is how the edge worker handles the SEO analysis. Instead of using a heavy DOM parser, which would bloat the bundle and exceed edge CPU limits, I used lightweight regex matching.

// 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' },
    });
  },
};
Enter fullscreen mode Exit fullscreen mode

By using the cf object in the fetch request, I can instruct the edge network to cache the target page for 300 seconds. This means if multiple users check the same URL, the worker serves the cached HTML instantly without making a new outbound request. The regex approach keeps the execution time well under the strict edge CPU limits, ensuring the tool remains responsive even under heavy load.

This hybrid approach worked exceptionally well. Next.js handles the complex state, routing, and OAuth flows beautifully, while the Cloudflare Workers handle the I/O heavy SEO fetching with zero noticeable latency.

What surprised me the most was how little code it actually took to write the edge worker. Because I stripped away the heavy DOM parsing in favor of regex, the bundle size was tiny. The lack of cold starts meant the tool felt instant, which drastically improved the perceived performance.

If I were to change one thing, I would have started with the regex approach from day one. I initially wasted a few days trying to get a full HTML parser working within the edge worker's constraints before realizing it was overkill for basic metadata extraction. Sometimes the simplest, most constrained approach is the right one for edge computing.

If you are building similar tools and want to test your own site's baseline metadata before writing your own parser, I extracted the core logic into a free SEO checker. You can try it out and see how fast edge analysis can be at https://saaslaunch.dev/free-tools/seo-checker.


Full disclosure: I'm the developer of SaaSLaunch. I built this because I needed it myself.

Top comments (0)