Software Engineering·July 21, 2026·8 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.

```javascript
// 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.

```javascript
// 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:

```javascript
// 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

Load Balancing
What a load balancer does, how traffic gets distributed, and what you need to know as a builder using managed platforms.
Message Queues and Async Processing
Message queues let your app offload slow work to the background so users get fast responses. This guide explains queues, pub/sub, workers, and key patterns like idempotency and dead letter queues.
Security Best Practices for Vibe Coders
The most common security mistakes when building with AI tools — and how to avoid them. Covers API keys, environment variables, database security, authentication, and frontend vs. backend.

Turn shipping into understanding

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

Join the waitlist