What Is Serverless? Functions and Edge Computing Explained for AI Coders

When you deploy a Next.js app to Vercel, your API routes run as serverless functions. When AI generates backend logic for you, it may assume serverless. Here's what that means, the tradeoffs, and when to use it vs. a traditional server.

TL;DR

Serverless means your code runs as individual functions triggered by requests — no server you manage, no server running when idle. Vercel's API routes, AWS Lambda, and Netlify Functions are all serverless. You pay per-request, not per-hour. The tradeoffs: cold starts (first request can be slow), no persistent state between requests, and database connections need special handling. Best for: variable traffic, side projects, APIs that don't need persistent connections.

Why AI Coders Need to Understand Serverless

If you deploy a Next.js app to Vercel (the default recommendation for Next.js), your /app/api/ routes automatically become serverless functions — even if you never explicitly chose serverless. These are essentially API endpoints that run on demand. Understanding this explains:

  • Why storing data in a global variable between requests doesn't work (each invocation is fresh)
  • Why database connections behave differently vs. a traditional Express server
  • Why your first request to a cold endpoint is slower than subsequent ones
  • Why you occasionally see "function timeout" errors on long operations

Real Scenario: A Next.js API Route

Your AI Prompt

"Build a Next.js API route that accepts a POST request with a user's email and saves it to my PostgreSQL database."

// app/api/subscribe/route.js
// This file becomes a serverless function on Vercel automatically
// Each request runs this in an isolated environment

import { prisma } from '@/lib/prisma'

export async function POST(request) {
  const { email } = await request.json()

  if (!email || !email.includes('@')) {
    return Response.json({ error: 'Invalid email' }, { status: 400 })
  }

  try {
    await prisma.subscriber.create({ data: { email } })
    return Response.json({ success: true })
  } catch (error) {
    if (error.code === 'P2002') {  // Prisma unique constraint violation
      return Response.json({ error: 'Already subscribed' }, { status: 409 })
    }
    return Response.json({ error: 'Server error' }, { status: 500 })
  }
}

// When this runs on Vercel:
// - Vercel spins up a fresh Node.js environment
// - Runs the function
// - Returns the response
// - May shut down the environment (or keep it warm for more requests)
// Each invocation is potentially isolated from every other

How Serverless Works

Traditional Server vs. Serverless

Traditional Server (VPS)Serverless Functions
Running when idleYes — costs money 24/7No — shuts down between requests
ScalingManual (upgrade server)Automatic (0 to millions of requests)
State between requestsPersistent (variables survive)Ephemeral (fresh each time)
Cost modelPer hour (paying always)Per request (paying only when used)
Cold startsNone100ms–2000ms on first request
Max durationUnlimited10–900 seconds (varies by platform)
WebSocketsSupportedNot supported (request-response only)

Cold Starts: The Main Tradeoff

When a serverless function hasn't been called recently, the cloud provider has to boot up a fresh environment before it can run your code. This startup takes anywhere from 100ms to 2 seconds. After that first request, subsequent requests are fast because the environment stays "warm."

What this means for you: the first visitor to hit your API after a quiet period gets a slower response. Everyone after that is fine. Here's how to deal with it:

  • Keep functions small: Fewer dependencies = faster cold start. Don't import entire libraries when you need one function.
  • Edge functions: Vercel Edge Functions and Cloudflare Workers run in V8 isolates (not Node.js), with cold starts under 1ms. Tradeoff: limited runtime APIs.
  • Keep functions warm: Ping them periodically via a cron job to prevent cold starts on critical endpoints.

Database Connections in Serverless

Traditional servers open a database connection once on startup and reuse it. Serverless functions may spin up hundreds of instances simultaneously, each opening its own connection. A PostgreSQL server handles ~100 connections before degrading.

// The problem: each serverless instance opens its own connection
// 100 concurrent requests = 100 database connections = overloaded DB

// The solution: use a connection pooler (PgBouncer or Supabase Pooler)
// or Prisma Accelerate

// In your Prisma schema:
datasource db {
  provider = "postgresql"
  // For serverless: use pooled connection URL
  url      = env("DATABASE_URL")         // Pooled (port 6543 for Supabase)
  directUrl = env("DIRECT_URL")          // Direct (port 5432) for migrations only
}

// Or use a singleton Prisma client (reuses connection within a warm function):
// lib/prisma.js
import { PrismaClient } from '@prisma/client'

const globalForPrisma = globalThis
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma

What AI Gets Wrong About Serverless

1. Storing State in Global Variables

// BROKEN in serverless — in-memory state doesn't persist between requests
let requestCount = 0  // This resets every time a cold start happens

export async function GET() {
  requestCount++  // This counter is meaningless in serverless
  return Response.json({ count: requestCount })
}

// FIX: Store state in a database, Redis, or a KV store

2. Opening Database Connections Without a Singleton

// BAD: Creates a new Prisma client (new connection) on every request
export async function POST(request) {
  const prisma = new PrismaClient()  // New connection every time!
  // ...
}

// GOOD: Import singleton from a shared module
import { prisma } from '@/lib/prisma'  // Reused in warm function instances

3. Long-Running Operations That Exceed Timeouts

Vercel Hobby: 10-second max. Vercel Pro: 60-second max. Long AI inference calls, large file processing, or slow external APIs can exceed these limits. Move long operations to a queue-based background job system.

Serverless vs. Edge Functions

Vercel offers two serverless options:

  • Serverless Functions: Full Node.js runtime. Can use any npm package. Cold start: 100ms–1s. Run in one region.
  • Edge Functions: A lighter runtime that starts almost instantly and runs closer to your users worldwide. Tradeoff: you can't use all Node.js features or npm packages.

Default to Serverless Functions. Use Edge only for very latency-sensitive operations (authentication checks, personalization) where you can live within the constraints.

What to Learn Next

Frequently Asked Questions

What does serverless mean?

Serverless means your code runs as on-demand functions without you managing server infrastructure. The cloud provider handles scaling, uptime, and servers. You write functions, deploy them, and pay only for actual execution time — not for a server running 24/7. "Serverless" doesn't mean no servers; it means you don't manage them.

What is a cold start in serverless?

A cold start happens when your function hasn't run recently and the cloud provider must spin up a new instance: provisioning a container, loading your code and dependencies, initializing connections. This adds 100ms–2000ms of latency to the first request. Functions used frequently stay "warm." Critical user-facing endpoints may need warming strategies or edge functions.

When should I use serverless vs a traditional server?

Serverless: unpredictable or spiky traffic, zero infrastructure management desired, functions under 30 seconds, side projects that may get zero traffic most days. Traditional server (VPS): persistent connections (WebSockets, SSE), long-running processes, consistent high-volume traffic (where per-request costs exceed VPS costs), or operations that require Node.js APIs unavailable in serverless.

Are Vercel API routes serverless?

Yes. Every file in /app/api/ in a Next.js app deployed to Vercel becomes a serverless function automatically. Each route runs in isolation, scales to handle traffic spikes, and you pay per invocation. The free tier includes enough for most side projects. This happens transparently — no extra configuration required.

What does AI get wrong about serverless?

AI commonly generates code that stores state in global variables (which doesn't persist between invocations), creates new database connections per request (exhausting connection limits at scale), and doesn't account for execution time limits. Always check for global state and ensure you're using a Prisma singleton pattern or connection pooler when deploying to serverless platforms.