Serverless Architecture

Serverless architecture runs application logic in stateless, short-lived functions managed entirely by a cloud provider. You write the function; the provider handles provisioning, scaling, patching, and billing. You pay per invocation and execution time, not for idle capacity. “Serverless” is a misnomer — servers exist, but you don’t manage them.

The canonical example is Azure Functions / AWS Lambda: a function triggered by an HTTP request, a queue message, a timer, or a blob upload. The function runs, completes, and the infrastructure scales to zero when idle.

How It Works

// Azure Function: HTTP trigger
public static class OrderProcessor
{
    [Function("ProcessOrder")]
    public static async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req,
        FunctionContext ctx)
    {
        var order = await req.ReadFromJsonAsync<OrderRequest>();
        // Process order...
        var response = req.CreateResponse(HttpStatusCode.OK);
        await response.WriteAsJsonAsync(new { OrderId = Guid.NewGuid() });
        return response;
    }
}

The function is stateless: no in-memory state survives between invocations. State must be externalized to a database, cache, or storage service.

Triggers and Bindings

Azure Functions and AWS Lambda support multiple trigger types:

TriggerUse case
HTTPREST APIs, webhooks
TimerScheduled jobs (cron)
Queue (Service Bus, SQS)Async message processing
Blob/S3File processing on upload
Event Grid/EventBridgeEvent-driven workflows

Pitfalls

Cold Start Latency

What goes wrong: the first invocation after a period of inactivity takes 500ms–3s while the runtime initializes. For latency-sensitive APIs, this is unacceptable.

Why it happens: the provider scales to zero when idle. The first request must boot the runtime, load the function, and initialize dependencies.

Mitigation: use Premium Plan (Azure) or Provisioned Concurrency (AWS) to keep instances warm. For .NET, use Native AOT compilation to reduce startup time. Accept cold starts for background jobs where latency doesn’t matter.

Vendor Lock-In

What goes wrong: the function uses provider-specific trigger bindings, SDKs, and configuration. Migrating to another provider requires rewriting the function host.

Why it happens: provider-specific bindings are convenient and reduce boilerplate.

Mitigation: isolate business logic from the function host. The function handler should be a thin adapter that calls a provider-agnostic service. This makes the core logic portable even if the host is not.

Database Connection Exhaustion

What goes wrong: under load the platform spins up hundreds of concurrent function instances, each opening its own database connections, and the database hits max_connections and rejects everyone — a self-inflicted outage exactly when traffic is highest.

Why it happens: serverless instances are isolated and short-lived, so they can’t share an in-process connection pool the way a long-running server does. Massive horizontal fan-out multiplies the connection count.

Mitigation: front the database with a server-side pooler that all instances share (RDS Proxy, Azure SQL, PgBouncer) and cap per-instance pool size. See Connection Pooling — this is the canonical serverless data gotcha.

NOTE

“Serverless” now includes containers. Beyond FaaS (Functions/Lambda), serverless container platforms — Azure Container Apps, AWS Fargate, Google Cloud Run — give scale-to-zero and pay-per-use for a normal containerized app, sidestepping the function programming model and much of the cold-start/portability friction. Often the better fit when you want serverless economics without rewriting to a function host.

Tradeoffs

ApproachStrengthsWeaknessesWhen to use
Serverless (Functions)Zero infrastructure management, scales to zero, pay-per-useCold starts, stateless constraint, vendor lock-in, hard to debug locallyEvent-driven workloads, variable traffic, background jobs
Containers (AKS, ECS)Full control, no cold starts, portableInfrastructure management overhead, minimum cost even at idleSteady traffic, stateful workloads, complex services
PaaS (App Service, Elastic Beanstalk)Managed runtime, no cold startsAlways-on cost, less granular scalingLong-running services, traditional web apps

Decision rule: use serverless for event-driven, bursty, or infrequent workloads where idle cost matters. Use containers or PaaS for services with steady traffic, strict latency requirements, or complex state management. Serverless and containers are often combined: serverless for async processing, containers for the synchronous API layer.

Questions

References