Serverless computing promised backend engineers a simpler way to build scalable applications without managing servers. Instead of provisioning virtual machines, maintaining application runtimes, or managing capacity manually, developers could deploy functions that execute on demand and scale automatically.
For many workloads, that model works extremely well. AWS Lambda can process API requests, respond to events, execute scheduled jobs, and connect services without requiring teams to maintain dedicated application servers.
But as backend systems become more latency-sensitive, some engineering teams are discovering the limitations of function-based execution. Cold starts, runtime initialization, network overhead, database connection management, and execution limits can make Lambda less suitable for applications that require consistently low response times.
The problem is not that AWS Lambda is inherently slow. Its performance depends on the runtime, memory allocation, deployment package, initialization logic, workload pattern, and surrounding architecture. A well-designed Lambda function can respond quickly, while a poorly designed one can introduce significant latency.
In 2026, backend engineers have more options than simply choosing between Lambda and traditional servers. Cloudflare Workers, edge runtimes, container-based serverless platforms, and long-running application services provide different approaches to execution, scaling, and latency.
The real architectural question is not whether Lambda should be replaced everywhere. It is which execution model best fits the latency, workload, and operational requirements of each backend service.
Why AWS Lambda Can Feel Slow
AWS Lambda runs application code in managed execution environments. When an invocation arrives, AWS can reuse an existing environment or create a new one when additional capacity is needed.
When an environment is already initialized, a function can often begin processing quickly. When a new environment must be created, additional initialization work can increase latency.
This is commonly known as a cold start.
The delay can include runtime initialization, loading application code, initializing frameworks, importing dependencies, establishing connections, and running custom initialization logic. The amount of time varies significantly between workloads.
Several factors can contribute to higher Lambda latency:
- Large deployment packages and dependency trees.
- Heavy application frameworks and initialization routines.
- Runtime startup overhead.
- Database connections established during invocation.
- Network calls to external services.
- VPC networking and other environment-specific configuration.
- Bursty traffic that requires additional execution environments.
- Insufficient memory or CPU resources for the workload.
These factors do not affect every function equally. A small function that performs a simple transformation may execute efficiently, while a function that initializes a large application framework and connects to several services may take considerably longer.
The distinction matters because the solution should target the actual source of latency rather than assume that changing platforms will automatically improve performance.
Cold Starts: The First Source of Latency
A cold start occurs when Lambda needs to prepare a new execution environment before processing an invocation. This is different from a warm invocation, where an existing environment can be reused.
For a simple function, initialization may be relatively lightweight. For a complex backend handler, initialization can involve loading many modules, constructing dependency containers, creating SDK clients, and preparing database access.
Consider an API endpoint that initializes a large framework, loads configuration, connects to a database, and then performs a small query. The business logic might take only a few milliseconds, while setup and network operations account for much of the total response time.
This can make performance inconsistent, particularly when traffic is intermittent or suddenly increases.
There are several ways to reduce the impact:
Keep initialization lightweight. Import only the modules the function needs and avoid unnecessary work during startup.
Reuse clients and connections where appropriate. Initialize reusable SDK clients outside the handler so warm execution environments can reuse them.
Reduce package complexity. Remove unnecessary dependencies and avoid loading large libraries for simple operations.
Measure cold and warm behavior separately. Average latency alone can hide occasional slow invocations that affect the user experience.
AWS also offers features such as Provisioned Concurrency for workloads that need initialized execution environments ready in advance. This can reduce cold-start latency for supported configurations, but it introduces additional cost and capacity-planning considerations.
Provisioned Concurrency is therefore a useful option when predictable latency is worth paying for, rather than a universal solution for every function.
Why P95 and P99 Latency Matter More Than Averages
Backend engineers often evaluate performance using average response time. That metric is useful, but it can conceal problems that affect a smaller percentage of requests.
For a production API, p95 latency indicates the response time at or below which 95% of measured requests complete. P99 provides a similar view for 99% of requests.
A function might have a low average latency while a subset of invocations takes significantly longer because of initialization, connection setup, downstream services, or resource contention.
These slower requests can affect checkout flows, authentication, payment processing, and other latency-sensitive operations.
A useful performance investigation should examine:
- Average and median latency.
- P95 and p99 latency.
- Cold-start frequency and duration.
- Function duration and timeout rates.
- Database connection and query latency.
- External API latency.
- Throttling and concurrency behavior.
- Cost per successful request.
The objective is to understand the full request path. Replacing Lambda without measuring its contribution to end-to-end latency can simply move the bottleneck somewhere else.
Database Connections Can Become the Real Bottleneck
A common serverless architecture sends each API invocation to a database. This works well when the application manages connections efficiently, but it can become problematic as concurrency grows.
If many execution environments establish database connections independently, the database may receive a sudden increase in concurrent connections. Connection establishment also adds latency to requests that need to initialize a new connection.
This is particularly important for relational databases with finite connection capacity.
For workloads using Amazon RDS or Aurora, teams can evaluate Amazon RDS Proxy to manage and reuse database connections. Other options include carefully reusing connections within execution environments, reducing unnecessary database round trips, and selecting a database access pattern appropriate for the workload.
However, connection pooling is not a substitute for application-level capacity planning. Teams still need to understand transaction behavior, connection limits, query performance, and the effects of concurrent requests.
In many applications, database access contributes more to total latency than the function runtime itself. That is why profiling the entire request path should come before migrating platforms.
The First Alternative: Cloudflare Workers
Cloudflare Workers provides an execution model designed for running code across Cloudflare’s distributed network. It is particularly relevant for APIs, lightweight request processing, authentication checks, content transformation, and other workloads that benefit from executing closer to users.
<AsyncImage query=”Cloudflare Workers edge computing architecture global network diagram” aspectRatio=”16:9″ width=”100%” />
Unlike a conventional Lambda deployment centered on AWS regional infrastructure, Workers can execute code at Cloudflare’s edge locations. For suitable workloads, this can reduce network round-trip time between users and application logic.
Workers also supports JavaScript and TypeScript using a web-standard-oriented runtime model, which can make it attractive for developers building lightweight backend services.
Potential advantages include:
- Execution close to users across a distributed network.
- A programming model suited to request-driven APIs.
- Useful integration with Cloudflare’s networking and security services.
- Support for lightweight request handling and edge logic.
But Workers is not a universal replacement for Lambda. Runtime compatibility differs, and some Node.js APIs, native dependencies, or application libraries may require adaptation. Data access patterns also matter: an edge function can still be slow if it must call a database or service located far away.
Workers is worth evaluating when network proximity is a significant part of the latency budget and the workload fits the runtime’s capabilities.
The Second Alternative: Bun and Long-Running Application Servers
Not every backend needs a function-per-request execution model.
For applications with sustained traffic, frequent requests, or substantial initialization work, a long-running service may provide a more predictable execution environment. The application can initialize once, reuse clients and connections, and process multiple requests without repeatedly entering a function-oriented lifecycle.
Bun is a JavaScript runtime that supports server-side application development and provides an integrated toolchain. Teams can use it to run backend services, HTTP servers, scripts, and other JavaScript workloads.
However, Bun is not itself a serverless hosting platform. It is a runtime that needs to be deployed somewhere, such as a container platform, virtual machine, or compatible managed hosting environment.
A long-running Bun service can be attractive when a team wants to reduce runtime overhead or simplify JavaScript tooling, but performance and compatibility should be benchmarked against the existing Node.js application. The result depends on the code, libraries, workload, and hosting environment.
The broader architectural alternative is a continuously running service, not simply a different runtime.
This model can be a good fit when the application benefits from persistent connections, substantial in-memory state, background processing, or predictable resource allocation. It also brings operational responsibilities around scaling, deployment, health checks, and capacity management.
The Third Alternative: Container-Based Serverless
Sometimes the best answer is not moving away from serverless but changing how the application is packaged and executed.
Container-based platforms can run application processes in managed environments while reducing the need to manage individual virtual machines. Depending on the platform, applications can scale based on traffic, queue depth, or configured resource requirements.
Options worth evaluating include AWS Fargate, Google Cloud Run, and Azure Container Apps.
These platforms differ in scaling behavior, startup characteristics, networking, pricing, and runtime constraints. They should not be treated as interchangeable.
For example, AWS Fargate runs containers without requiring teams to manage the underlying server fleet directly, but the application still needs a scheduler or service architecture such as Amazon ECS or Amazon EKS. Google Cloud Run provides a managed container execution model with request-based and other scaling options, depending on the configuration. Azure Container Apps supports managed container workloads and event-driven scaling.
Container-based execution can be a strong fit when the application needs a conventional server process, larger dependencies, or greater control over runtime configuration.
The trade-off is that teams must still consider startup time, scaling-to-zero behavior, container image size, minimum instance settings, and the operational cost of maintaining the service.
Lambda vs. Workers vs. Containers
The right platform depends on the workload rather than a single benchmark.
| Consideration | AWS Lambda | Cloudflare Workers | Container-based services |
|---|---|---|---|
| Execution model | Managed function invocations | Distributed edge execution | Long-running or managed container processes |
| Best fit | Event-driven functions and AWS-integrated workloads | Lightweight APIs and edge request processing | Stateful services, APIs, and workloads needing runtime control |
| Startup behavior | Cold starts can affect some invocations | Designed for lightweight distributed execution, with runtime-specific constraints | Depends on image size, platform, and scaling configuration |
| Ecosystem | Deep AWS service integration | Cloudflare networking and edge ecosystem | Broad language and framework compatibility |
| Connection handling | Requires attention to environment reuse and concurrency | Depends on the data-access model and platform integrations | Can support persistent application connections |
| Operational model | Managed function infrastructure | Managed edge runtime | Managed containers or container orchestration |
| Main trade-off | Invocation model and latency variability | Runtime and data-location constraints | More responsibility for application lifecycle and capacity |
This comparison is a starting point, not a universal performance ranking. The same application can perform differently across platforms depending on where its data lives, how it initializes, and how much work it performs per request.
Optimize Lambda Before Replacing It
Migration can be expensive and introduce new failure modes. Before moving away from Lambda, teams should establish a baseline and test targeted improvements.
1. Reduce initialization work. Move reusable client initialization outside the handler, avoid unnecessary imports, and remove expensive setup that does not need to run for every execution environment.
2. Tune memory and CPU. Lambda allocates CPU in relation to configured memory. Increasing memory can reduce execution time for compute-intensive workloads, although it also changes cost. Benchmark several configurations rather than assuming that the lowest memory setting is cheapest overall.
3. Reuse database connections carefully. Avoid creating unnecessary connections during every invocation. Evaluate connection pooling and managed database proxies where appropriate.
4. Review package size. Reduce dependencies, optimize bundling, and avoid shipping development-only libraries with production functions.
5. Use Provisioned Concurrency when justified. For workloads with strict latency requirements, keeping execution environments initialized can reduce cold-start impact. Compare the cost with the business value of lower latency.
6. Check downstream services. Profile database queries, network calls, and external APIs. If most of the response time is spent waiting on another service, changing the compute platform may not help.
7. Measure the result. Compare p50, p95, and p99 latency, error rates, cold-start behavior, and total cost under representative traffic.
If these changes bring performance within the required service-level objectives, Lambda may remain the most economical and operationally convenient choice.
Choosing the Right Architecture for Different Workloads
A common mistake is forcing every endpoint into the same execution model.
A lightweight webhook may work well on Lambda. An edge authentication check may benefit from Cloudflare Workers. A long-running API with frequent database access may fit a containerized service. A background worker processing large jobs may need queue-based scaling and controlled concurrency.
A hybrid architecture can assign each workload to the environment that suits it best.
For example, a customer-facing application might use an edge runtime for request routing and lightweight validation, a regional backend service for business logic, and asynchronous functions for event processing. The architecture should still account for security, data residency, consistency, observability, and operational complexity.
More platforms do not automatically mean a better system. Every additional runtime introduces deployment workflows, monitoring requirements, security policies, and expertise that the team must maintain.
The right architecture minimizes unnecessary complexity while meeting the application’s performance and reliability requirements.
Cost Is More Than the Price of an Invocation
Lambda pricing can be attractive because teams pay for execution rather than maintaining continuously running compute for every function. But the total cost depends on request volume, execution duration, memory allocation, concurrency, networking, logging, and downstream services.
A function that runs frequently and performs expensive initialization may be less economical than expected. Conversely, a workload with irregular traffic may be cheaper on Lambda than on a service that reserves capacity continuously.
Container-based services can reduce some overhead for sustained workloads, but they may incur charges for minimum instances or continuously allocated resources. Edge platforms have their own pricing models and limits.
A useful comparison should include:
- Compute cost per successful request.
- Execution duration and resource allocation.
- Minimum capacity and idle-resource costs.
- Database and network charges.
- Observability and logging expenses.
- Engineering time required to operate the platform.
- Cost of meeting latency and availability objectives.
The lowest compute bill is not necessarily the lowest total cost. A slightly more expensive execution model may be justified if it improves customer experience or reduces operational effort.
Observability Must Follow the Entire Request
Changing runtimes will not improve performance if the engineering team cannot identify where time is spent.
Distributed tracing can reveal whether latency originates in function initialization, application logic, database access, DNS resolution, network calls, or downstream processing. Metrics should distinguish invocation duration from end-to-end request latency, while logs should provide enough context to investigate failures without unnecessarily exposing sensitive data.
Teams should track latency percentiles, error rates, timeouts, concurrency, throttling, resource utilization, and dependency performance.
For a hybrid architecture, traces should correlate work across edge functions, regional services, queues, databases, and external APIs. Otherwise, a request that crosses multiple platforms can become harder to debug than the original Lambda deployment.
Observability should also support controlled performance experiments. Before and after a migration, teams need comparable traffic patterns, workload characteristics, and success criteria.
Security and Reliability Still Matter
Performance improvements should not come at the expense of security.
Teams moving from Lambda to edge runtimes or containers need to review authentication, authorization, secret storage, network access, dependency management, and deployment permissions. A new platform may change how credentials are delivered, how traffic reaches services, and where data is processed.
The architecture should enforce access controls independently of the execution platform. Sensitive operations should remain authorized by trusted backend services, and services should receive only the permissions they need.
Migration plans should also include staged rollout, load testing, rollback procedures, and compatibility checks. A faster endpoint that fails under peak traffic or exposes sensitive data is not an improvement.
Where Engineering Teams Fit
Selecting a backend execution model requires a balance between performance, infrastructure cost, application architecture, and operational complexity. Team like GeekyAnts, Thoughtworks work across backend engineering, cloud infrastructure, and application development, making this broader engineering perspective relevant for teams evaluating serverless optimization or migration strategies. The objective is to identify where the current architecture creates measurable constraints and choose an execution model that meets production requirements without introducing unnecessary complexity.
The Future of Serverless Backend Development
Serverless computing is not disappearing. AWS Lambda remains a strong option for event-driven processing, asynchronous workflows, and workloads that benefit from managed scaling and AWS service integration.
But serverless architecture is no longer limited to one execution model. Edge runtimes, managed containers, long-running application services, and conventional serverless functions can coexist within the same backend system.
For backend engineers, the important skill is understanding the trade-offs between them. Cold starts are one potential source of latency, but they are not the only one. Database access, dependency initialization, network distance, runtime compatibility, and resource configuration can have an equal or greater impact.
Before replacing Lambda, measure the complete request path and optimize the parts responsible for the delay. If the workload still cannot meet its latency objectives, evaluate alternatives against realistic traffic, data-access patterns, operational needs, and total cost.
The goal is not to abandon serverless. It is to stop treating one execution model as the answer to every backend problem.
For more, visit our homepage!
















Add Comment