Software Engineering·July 21, 2026·3 min read

Serverless Compute

What serverless means, when to use it, and the trade-offs that trip up builders — cold starts, statelessness, costs at scale.

serverlesscloudinfrastructurecomputing

Serverless is a cloud model where you run code without managing servers. Despite the name, servers still exist — you just don't provision, scale, or maintain them. You write a function, deploy it, and pay only for the time it actually runs. If Cartara flagged this in your diff, you likely added a serverless function, changed how one handles state, or hit a pattern that breaks in a serverless environment (like holding a database connection open).

How it works

When a request comes in, the cloud provider spins up a container to run your code, executes the function, and tears the container down (or keeps it warm briefly for future calls). You don't decide how many copies run — the platform handles that automatically.

Cold start vs warm start is the key trade-off:

  • Cold start: A fresh container has to spin up. This adds latency — typically 100ms to 2 seconds depending on the runtime and provider
  • Warm start: A recently-used container is reused. Near-instant execution

Cold starts matter most for latency-sensitive user-facing code. They matter less for background tasks.

What triggers a serverless function

Functions don't run on their own. They respond to events:

TriggerExample
HTTP requestAPI call via API Gateway
ScheduleCron job (every morning at 6am)
Queue messageNew item in a queue
File uploadImage uploaded to S3
Database changeNew row inserted
Auth eventUser signs up

The statelessness constraint

Serverless functions are stateless by design. Each invocation is independent — you can't rely on in-memory data persisting between calls. One run might happen on a completely different container than the last one.

This means any state that needs to persist across requests must live outside the function: in a database, object storage, or a cache. This is the most common thing builders get wrong.

// Broken: assumes data persists in memory between calls
let callCount = 0  // this resets on every cold start

export async function handler(event) {
  callCount++  // unreliable across instances
  return { count: callCount }
}

// Correct: state stored in a database
export async function handler(event) {
  const result = await db.counters.upsert({
    where: { id: 'global' },
    update: { count: { increment: 1 } },
    create: { id: 'global', count: 1 }
  })
  return { count: result.count }
}

When serverless is a good fit

  • Unpredictable or spiky traffic — scales to zero and to thousands instantly
  • Event-driven workloads — responding to uploads, messages, webhooks
  • Background tasks — image processing, email sending, data transformation
  • APIs with variable load — you pay only for actual usage
  • Side projects — generous free tiers make it nearly free at low volume

When serverless is a poor fit

  • Long-running processes — most providers cap execution time (AWS Lambda: 15 minutes max)
  • Latency-critical paths where cold starts are unacceptable
  • Stateful workloads that need persistent in-memory state
  • High sustained throughput — at scale, always-on containers often cost less
  • ML model serving with large models that take too long to load

The database connection problem

This trips up many serverless builders. A traditional server opens a database connection once and reuses it. A serverless function might spin up 1,000 instances simultaneously — each wanting its own connection. Most databases have a connection limit, and you'll exhaust it.

The fix is a connection pooler (PgBouncer, or the built-in pooler on Supabase/Neon). It maintains a shared pool of connections that functions borrow and return. Enable this before deploying serverless functions that touch a database.

// Use the pooled connection string, not the direct one
// Supabase example:
const db = new PrismaClient({
  datasources: {
    db: {
      url: process.env.DATABASE_URL  // should point to PgBouncer/pooler, not direct DB
    }
  }
})

What You'll See in Your Code

Cartara commonly flags synchronous fan-out patterns that create cascading latency in serverless:

// Slow: calling multiple lambdas synchronously
export async function processOrder(event) {
  await sendConfirmationEmail(event.orderId)    // wait 300ms
  await updateInventory(event.orderId)           // wait 200ms
  await notifyWarehouse(event.orderId)           // wait 400ms
  // Total: ~900ms, and each failure blocks the others
}

// Better: trigger async jobs via a queue
export async function processOrder(event) {
  await queue.sendBatch([
    { type: 'send_confirmation', orderId: event.orderId },
    { type: 'update_inventory', orderId: event.orderId },
    { type: 'notify_warehouse', orderId: event.orderId },
  ])
  return { status: 'queued' }  // returns fast, work happens in background
}

Providers at a glance

ProviderServiceMax TimeoutNotes
AWSLambda15 minutesMost mature, largest ecosystem
Google CloudCloud Run60 minutesContainer-based, very flexible
CloudflareWorkers30s CPU timeEdge-native, very fast globally
VercelFunctions60 secondsBest DX for Next.js apps

Serverless vs containers

Serverless wins at low traffic, simplicity, and zero idle cost. Containers win at sustained high throughput, long-running processes, and predictable cost. The line is blurring — services like Cloud Run and AWS Fargate are "serverless containers" where you define a container but the platform manages scaling.

Related concepts

Tech Stack Landscape
A map of cloud services across AWS, Azure, and GCP — compute, storage, databases, AI, DevOps, and messaging compared side by side.
Google Cloud Services
A practical reference to Google Cloud Platform's key services — with particular focus on BigQuery, Kubernetes, Cloud Run, Firebase, and Vertex AI where GCP genuinely leads.
Managed Platforms
The platforms that abstract away cloud complexity — hosting, databases, auth, and AI infrastructure — and how to choose between them for your stage and stack.

Turn shipping into understanding

Cartara measures what your team actually learns from every AI coding session.

Join the waitlist