Skip to main content
Runa
Back to Articles

The Pains of the Cloud: Deprecated Services and Why Lambdas Are King

Engineering
9 min read
by Monika BronskaFeb 2, 2026
Illustration of a computer exchanging data with a cloud and a stack of servers

Just like for a lot of software businesses out there, most of Runa’s services are based on a Cloud-based microservices design with AWS being our exclusive cloud provider. To build systems capable of processing hundreds of thousands of events in seconds in a reliable manner, we have additionally adopted the approach to favour serverless AWS services in our architecture.

In a serverless model, developers can build and deploy applications without having to manage the underlying infrastructure. The cloud provider will dynamically allocate resources based on usage, allowing our teams to develop and deploy faster while focusing on business logic.

AWS offers various serverless services across different domains, including API management (API Gateway), compute (Lambda, App Runner), event-driven integration (EventBridge, Step Functions, SQS, and SNS), and data storage (S3, DynamoDB, and Aurora Serverless).

As part of the Billing team, a sub-team of engineering, responsible for all things related to financial reconciliation and invoicing of customers and brands we work with, I have worked extensively with most of these over the past months at Runa.

Although on paper, these services might seem like a perfect solution to most problems, and they generally do provide a great developer experience, it’s worth noting that it hasn’t always been smooth sailing. There are trade-offs and pitfalls to navigate along the way.

The Common Challenges With Being Distributed Over Many Cloud Services

It is well-known that microservices increase the operational overhead and complexity of the system, making it more challenging for developers to follow and work with. This is no different in the Cloud, although AWS's offering of supporting tools, combined with our preference for serverless, makes it significantly easier.

One of the main challenges with having the system components broken down into various Cloud services is ensuring adequate observability and monitoring - tracing a request end-to-end across a Step Function, which might invoke a Lambda, which in turn interacts with other services… although some supporting AWS services such as X-Ray and CloudWatch assist with logging and tracing these also have to be integrated with our internal observability framework and third-party tools like Datadog (and how we go about it deserves its own article 🙂) to achieve a reliable and comprehensive alerting and monitoring system as well as more manageable debugging of issues.

Some Stumbling Blocks Associated With Specific Services

Over the years, we have also encountered some limitations and complications linked to specific AWS services. For example, some commonly occurring issues with “phantom” requests in API Gateway and how we addressed them were described by my colleague in this article.

Last year, we were forced to migrate our Quantum Ledger Database (QLDB) to another service, as AWS announced its deprecation, with the shutdown scheduled for July 31, 2025. As a managed ledger database service, it offered a cryptographically verifiable transaction log, making it a perfect choice where the immutability of records and audit functionality were necessary. Apart from serverless support, QLDB offered integration with our current infrastructure (Step Functions, API Gateway) and fit our data model for the payouts system, in which a record is stored in a document format with support for nested objects and document history out of the box. To obtain a permanent, immutable history of all record changes for audit purposes, which QLDB offered with a different database service, those transaction logs can still be tracked and permanently stored, but only with the support of other services, for example, CloudTrail or S3.

Serverless Favorites

At Runa, one of the main domains in our infrastructure where the serverless services’ dominance is particularly visible is computing and workflow orchestration. Lambdas and Step Functions form the backbone of our infrastructure and underpin many of our services. They are used to power everything from real-time API calls to scheduled background processes and are widely adopted by all our teams. Lambdas let us run lightweight, event-driven workloads on demand, while Step Functions orchestrate more complex workflows across multiple services. Since each service deserves a closer look, this article will focus solely on AWS Lambda.

Lambdas are a popular choice when you want to run code without having to worry about how it will be run - AWS will provision and manage servers for you, and even automatically scale based on traffic demand. Additionally, you only pay for the amount of time the code is running (the charges are based on the number of requests and the time it takes to run them).

Lambda natively connects to AWS event sources (SNS, SQS, API Gateway, EventBridge, etc.), making it an ideal component for irregular or bursty workloads. These services act as managed ingress points that absorb traffic spikes, buffer events, and invoke Lambda functions only when work is available. As a result, there is no need to provision or scale compute capacity in advance: Lambda is invoked reactively in response to events, and automatically scales concurrency to match the incoming workload. Some of our workloads run on an infrequent schedule and may consume fluctuating amounts of resources - for example, our invoicing cycle runs only once a month on the first day. During the billing cycle, a large amount of resources will be consumed due to a high volume of data to be processed, but Lambda functions will scale automatically to the workload, which makes it a perfect choice since we can run these processes without having idle infrastructure outside of that time.

Lambda’s features help us to create a system that is not only more maintainable but also resilient - the function automatically retries failed asynchronous invocations and provides high availability out of the box. When integrated with durable event buses such as SNS and SQS, Lambdas can offer a decoupled and fault-tolerant workflow - for example, our invoicing system contains several Lambdas which consume and produce events that get processed along the pipeline with queues and topics keeping the services decoupled. Each Lambda is responsible for its own logic, as AWS best practices recommend writing single-purpose functions. This separation offers additional resilience under unpredictable loads; for example, a queue can act as a buffer if the downstream Lambda is experiencing a temporary slowness in processing the events.

Things to Consider When Working With Lambdas

It is worth mentioning that there are also some well-known drawbacks to using Lambdas. These include vendor lock-in with heavy reliance on AWS-managed services (something which is a lesser concern for us, but can be tackled with hexagonal architectures and standard runtimes) or execution and resource limits of the Lambdas, which need to be considered when developing a service. AWS limits the executions to 15 minutes per invocation, which makes it unsuitable for long-running jobs unless they are broken down into subtasks and split between multiple Lambdas or a Step Function coordinating each task separately. Additionally, as there are resource caps on Lambda memory and ephemeral disk storage, they might not be a suitable option for resource-intensive tasks.

Another well-known problem with Lambdas is what’s known as a cold start, which occurs when a function hasn’t been used recently and the first invocation requires AWS to spin up a new execution environment. This adds additional latency to the first request and can be particularly noticeable for infrequently used, latency-sensitive paths. In practice, however, this impact can be reduced significantly. For critical APIs, provisioned concurrency allows us to keep execution environments warm and predictable.  Provisioned concurrency means that (if provisioned to the right scale) we always have a lambda that is warm and ready to compute. It is great for:

  • When we have a critical but low traffic endpoint that requires high performance
  • When we have a lambda that’s package size results in significant startup time

We can also mitigate cold starts by keeping deployment packages small, avoiding unnecessary dependencies, choosing lightweight runtimes for hot paths, and deferring expensive initialisation logic until it is actually needed. For workloads where some startup latency is acceptable, like in our invoicing lambdas, cold starts become largely irrelevant, allowing us to benefit from Lambda’s scaling and cost model without compromising user experience.

Our biggest concern in the example of the invoicing workflow was implementing an acceptable and reliable observability of that system. Having multiple distributed Lambdas, which additionally interact with other services, adds to the complexity and makes it harder to monitor and debug. We were able to overcome these challenges using centralised monitoring, which integrates AWS services such as X-ray, third-party tools (Datadog) and in-house solutions.

Final Thoughts

While AWS services have enabled us to develop and scale quickly, our journey has also revealed the challenges that come with depending on a constantly evolving cloud ecosystem. From troubleshooting service-specific issues to navigating the forced deprecation of QLDB, we’ve repeatedly had to adapt our systems and revisit design choices. Operating across many cloud services amplifies this complexity, making flexibility and resilience in system design essential to absorb change without disrupting the platform.

Despite these challenges, this approach has been the right one for us: managed services have allowed our teams to focus on product and business logic rather than infrastructure concerns, while still supporting rapid growth and highly variable workloads. By deliberately designing for loose coupling and clear boundaries between services, we’ve been able to evolve or replace underlying components when necessary without slowing down delivery.

These experiences highlight an important reality of building serverless platforms at scale: the advantages of managed services come with trade-offs, including limited control and potential service discontinuity. For us, the key lesson has been to build with flexibility in mind — designing integrations and data flows in a way that allows us to pivot when services change, without disrupting product delivery.

Within that context, AWS Lambda remains the engineering team’s compute favourite. It enables us to move faster while absorbing a significant amount of operational burden through automatic scaling, per-invocation billing, native retries for asynchronous invocations, and easy integration with AWS event sources. This makes it particularly well-suited for event-driven pipelines that must handle large, unpredictable bursts — such as month-end invoice processing — without provisioning or maintaining idle infrastructure. Lambdas are not a silver bullet, but for us, their limitations are well understood and manageable when paired with deliberate architectural and operational practices.