loke.dev
Cover image for Is the Edge Really Faster If Your Database is Still in Virginia?

Is the Edge Really Faster If Your Database is Still in Virginia?

Stop chasing millisecond execution times at the edge until you solve the 'regional gravity' problem that's throttling your data-heavy requests.

· 3 min read

Why does your "globally distributed" application feel like it’s running on a 56k modem the moment a user from London tries to log in, even though your code is executing mere miles from their house?

You jumped on the Edge computing bandwagon because the marketing promised sub-10ms response times. You moved your Next.js API routes to Cloudflare Workers or Vercel Edge Functions. You optimized your bundles until they were microscopic. But the second your code hits await db.select().from(users)..., all those gains evaporate.

The culprit is "Regional Gravity."

The Speed of Light is a Harsh Mistress

If your serverless function executes in a London data center but your Postgres instance is sitting in us-east-1 (Northern Virginia), every single database query has to travel across the Atlantic Ocean.

The round-trip time (RTT) from London to Virginia is roughly 70ms to 90ms under ideal conditions. That doesn't sound like much until you realize most modern ORMs and application patterns are chatty.

Look at this common (and slightly inefficient) pattern:

// Running on the Edge in London
export async function GET(request: Request) {
  // 1. Auth check (Request to DB in Virginia: +85ms)
  const session = await db.query.sessions.findFirst({ ... });

  if (!session) return new Response("Unauthorized", { status: 401 });

  // 2. Fetch user profile (Request to DB in Virginia: +85ms)
  const user = await db.query.users.findFirst({ ... });

  // 3. Fetch user preferences (Request to DB in Virginia: +85ms)
  const prefs = await db.query.preferences.findFirst({ ... });

  return Response.json({ user,沟通 prefs });
}

By the time your "lightning-fast" edge function finishes, you’ve spent over 250ms just waiting for photons to travel through undersea cables. Your execution time was 5ms, but your latency was 255ms. You would have been significantly faster if you had just hosted the code in Virginia right next to the database.

The Connection Pool Trap

It’s not just the distance; it’s the handshake.

Standard Postgres and MySQL use TCP connections. If your edge function is truly "serverless," it’s likely spinning up, opening a connection, doing the work, and dying. Setting up a TLS/TCP connection can take three round trips.

If you aren't using an HTTP-based connection pooler (like Prisma Accelerate, Upstash, or Neon’s serverless driver), your "Edge" function might spend 300ms just shaking hands with a database on the other side of the world before it even sends the first SELECT statement.

How to Actually Use the Edge

If you actually need the Edge for data-heavy apps, you have three real choices.

1. Distributed Data (The Turso/Fly.io Model)

You move the data to the Edge too. Technologies like Turso (built on libSQL) allow you to have read replicas in multiple regions. When your London function runs, it queries a London-based replica.

// Using a distributed DB client
const client = createClient({
  url: process.env.LIBSQL_URL, // This points to the local replica automatically
  authToken: process.env.LIBSQL_AUTH_TOKEN,
})

This reduces that 85ms RTT to {"<"}5ms. But beware: write consistency becomes the new headache. Writes still have to travel back to the "Primary" region.

2. Regional Compute (The "Heresy" Model)

Stop using the Edge for everything. If your database is in Virginia, run your API in Virginia. Use the Edge for what it’s actually good at:

  • Geolocation redirects.
  • Personalizing static HTML (A/B testing).
  • Input validation and edge-side caching (Stale-While-Revalidate).
  • Image optimization.

3. The "Mega-Query"

If you insist on the Edge but keep a central DB, you must minimize round trips. This means no N+1 queries. No sequential awaits. You fetch everything in one go, even if the SQL gets ugly.

// Instead of three awaits, use a single join or a complex json_build_object
const result = await db.execute(sql`
  SELECT json_build_object(
    'user', u.*,
    'prefs', p.*
  ) 
  FROM users u 
  LEFT JOIN preferences p ON u.id = p.user_id 
  WHERE u.id = ${userId}
`)

The Verdict

Edge computing is often sold as a performance silver bullet, but for 90% of CRUD applications, it's actually a performance regression. Unless you are willing to invest in a distributed database architecture or a heavy caching layer (like Redis at the edge via Upstash), you are likely paying a "latency tax" for the privilege of saying your app is distributed.

Before you switch that deployment toggle to "Global," ping your database from your local machine. If the number is higher than 20ms, the Edge is going to make your app feel slower, not faster.