Skip to content
Achieving Sub-100ms APIs: Edge Functions & Serverless Postgres for Global Apps
Modern Tech & Innovations

Achieving Sub-100ms APIs: Edge Functions & Serverless Postgres for Global Apps

12 min read
Edge FunctionsServerlessPostgresNeonAPI Performance

Global user expectations demand instant application responses, but traditional architectures often struggle with latency. This article explores how Vercel Edge Functions combined with serverless Postgres (Neon) deliver sub-100ms API performance, revolutionizing user experience and operational efficiency.

1. Introduction & The Global Latency Problem

In today's interconnected world, users expect instantaneous interactions with web applications. Whether it's a real-time dashboard, an e-commerce checkout, or a collaborative editing tool, any noticeable delay degrades user experience, leads to higher bounce rates, and ultimately impacts business metrics. Traditional application architectures, often deployed in a single or a few regional data centers, face an inherent challenge: network latency. Data must travel physically across vast distances between the user's browser, the server, and the database, adding hundreds of milliseconds to every request.

This problem is compounded for global applications. A user in Sydney interacting with an application hosted in Virginia will experience significant round-trip times (RTTs). While Content Delivery Networks (CDNs) effectively cache static assets, they do little for dynamic API calls that require computation and database access. Building truly global applications that feel local to every user demands a fundamental shift in architecture.

2. The Solution Concept: Edge Functions & Serverless Postgres

The solution lies in bringing computation and data closer to the user. This is where Edge Functions and Serverless Databases become indispensable. Let's break down this powerful combination:

Edge Functions (e.g., Vercel Edge Functions, Cloudflare Workers)

Edge Functions are stateless compute environments that run code at the edge of the network, geographically closest to the user. When a request comes in, it's routed to the nearest available edge location, minimizing network latency. This dramatically reduces the time taken for the initial API response. They are ideal for lightweight, highly concurrent, and globally distributed tasks like API routing, authentication, and data fetching.

Serverless Postgres (e.g., Neon)

Traditional relational databases are often deployed in fixed regions and can be a bottleneck for global applications. Connecting an Edge Function to a distant database still introduces latency. Serverless Postgres solutions like Neon address this by providing a highly scalable, pay-as-you-go PostgreSQL service with features optimized for modern serverless architectures. Neon, for instance, offers instant branching, a sophisticated connection pooler designed for short-lived serverless connections, and the ability to provision read replicas close to your edge functions, ensuring low-latency data access.

The Synergistic Architecture

By combining Edge Functions and Serverless Postgres, we create an architecture where:

  • User requests hit the nearest Edge Function.
  • The Edge Function, with minimal latency, connects to a regionally optimized, serverless Postgres instance (or a read replica).
  • The database queries and business logic execute quickly, and the response travels back to the user with minimal network hops.

This setup significantly reduces the total round-trip time, making APIs feel lightning-fast regardless of the user's location.

3. Step-by-Step Implementation: Building a Low-Latency API

Let's build a simple API with Vercel Edge Functions and Neon. We'll create an endpoint to fetch and create items, demonstrating the core principles.

Prerequisites:

  • Node.js (v18+)
  • Vercel CLI installed (npm i -g vercel)
  • A Neon account (free tier available)
  • A Vercel project

Step 1: Set Up Your Neon Database

  1. Go to Neon.tech and create a new project.
  2. Once your project is created, navigate to the 'Connection Details' and copy your connection string. It will look something like: postgres://user:password@ep-random-name-12345.us-east-2.aws.neon.tech/dbname?sslmode=require.
  3. Create a simple table, e.g., items:
    CREATE TABLE items (
      id SERIAL PRIMARY KEY,
      name VARCHAR(255) NOT NULL,
      created_at TIMESTAMPTZ DEFAULT NOW()
    );

Step 2: Initialize Your Vercel Project

If you don't have one, create a new Next.js project (or any Vercel-compatible framework).

npx create-next-app@latest my-edge-app --ts
cd my-edge-app
pnpm install

Step 3: Install Dependencies

We'll use the pg client for PostgreSQL interactions and dotenv for local environment variables.

pnpm add pg dotenv

Step 4: Configure Environment Variables

Create a .env.local file in your project root and add your Neon connection string.

DATABASE_URL="postgres://user:password@ep-random-name-12345.us-east-2.aws.neon.tech/dbname?sslmode=require"

For deployment on Vercel, you'll add this DATABASE_URL as a secret environment variable through the Vercel dashboard or CLI (vercel env add DATABASE_URL).

Step 5: Create the Edge API Route

Create a file at pages/api/items.ts (for Pages Router) or app/api/items/route.ts (for App Router) and add the following code. For simplicity, we'll use the Pages Router structure here, but the core logic for the Edge Runtime is similar for App Router.

// pages/api/items.ts

import { NextRequest, NextResponse } from 'next/server';
import { Client } from 'pg';

// IMPORTANT: Configure the Edge Runtime
export const config = {
  runtime: 'edge',
};

let client: Client | null = null;

async function getPgClient() {
  if (!client) {
    client = new Client({
      connectionString: process.env.DATABASE_URL,
      ssl: {
        rejectUnauthorized: false, // Required for Neon's SSL
      },
    });
    await client.connect();
  }
  return client;
}

export default async function handler(req: NextRequest) {
  const pgClient = await getPgClient();

  if (req.method === 'GET') {
    try {
      const result = await pgClient.query('SELECT id, name, created_at FROM items ORDER BY created_at DESC');
      return NextResponse.json(result.rows, { status: 200 });
    } catch (error: any) {
      console.error('Error fetching items:', error);
      return NextResponse.json({ error: 'Failed to fetch items', details: error.message }, { status: 500 });
    }
  } else if (req.method === 'POST') {
    try {
      const { name } = await req.json();
      if (!name) {
        return NextResponse.json({ error: 'Name is required' }, { status: 400 });
      }
      const result = await pgClient.query('INSERT INTO items (name) VALUES ($1) RETURNING id, name, created_at', [name]);
      return NextResponse.json(result.rows[0], { status: 201 });
    } catch (error: any) {
      console.error('Error creating item:', error);
      return NextResponse.json({ error: 'Failed to create item', details: error.message }, { status: 500 });
    }
  } else {
    return NextResponse.json({ error: 'Method not allowed' }, { status: 405 });
  }
}

Code Explanation:

  • export const config = { runtime: 'edge' };: This crucial line tells Vercel to deploy this API route as an Edge Function.
  • getPgClient(): This function ensures a single PostgreSQL client instance is reused across invocations within the same Edge Function execution context. While Edge Functions are stateless and cold starts are possible, Vercel's platform often keeps instances warm for a period, allowing for connection reuse. Neon's connection pooler handles multiple concurrent connections efficiently.
  • req: NextRequest, NextResponse: These types from next/server are designed for the Edge Runtime, providing a Web standard Request/Response API.
  • ssl: { rejectUnauthorized: false }: This is necessary when connecting to Neon from a Vercel Edge Function, as the default Node.js root CAs might not include Neon's certificate authority, and Vercel's environment might be slightly different. In production, you might explore more robust SSL handling if strict CA validation is paramount for your specific security model (e.g., providing a custom CA).

Step 6: Test Locally

pnpm dev

Then, use curl or Postman:

  • GET: http://localhost:3000/api/items
  • POST: http://localhost:3000/api/items with a JSON body like { "name": "My New Edge Item" }

Step 7: Deploy to Vercel

vercel

Follow the prompts. Vercel will automatically detect the Edge Runtime configuration and deploy your API globally.

4. Optimization & Best Practices

  • Connection Pooling (Neon's Advantage)

    While we initialized a single pg client in our Edge Function for simplicity, Edge Functions are short-lived. Neon has a built-in intelligent connection pooler that effectively manages connections from ephemeral serverless functions, ensuring your database isn't overwhelmed. This is a significant advantage over traditional databases.

  • Cold Starts Mitigation

    Edge Functions can experience 'cold starts' (initialization latency). For critical paths, you can:

    • Keep it Lean: Minimize bundle size. Only import necessary libraries.
    • Warming: Some platforms offer
Muhammad Tahir logo

Muhammad Tahir

Building web & mobile apps since 2021. Passionate about clean code and real-world impact.