We released a new feature few years back that was supposed to make our customers happy, but it’s causing nothing but pain. Our monolithic, server-based architecture doesn’t scale well, so we spend half of our time over-provisioning for down-times and the other half under-provisioning for when we hit the front page of Reddit.
This is the story of how I turned a large web app to AWS Lambda, going serverless to solve scaling problems, cut operation cost and ship features faster than ever. If you're tired of having too many servers or just want future proof apps — come with me into the world of serverless computing.
What is Serverless Architecture? A Game Changer
But let me show you what serverless architecture really means.
In traditional setups, we maintain and manage servers. We constantly worry about scaling, provisioning resources and ensuring that the server is functioning as expected. With serverless architecture, all of this is abstracted away. It’s the cloud provider (in our case AWS Lambda) who takes care of scaling, management and resource allocation. You write your code, you deploy it and let AWS do the rest. When a request comes in, AWS spins up everything needed for execution including necessary resources as per load. It’s like you have a cluster of magical servers which only appear when you invoke them! Too good to be true? Here is how it went in my real world scenario.
The Challenge: Unpredictable Traffic and Costly Over-Provisioning
Serverless was sort of an alien concept or a term coined when AWS launched Lambda way back in 2014, but now all major public / private cloud vendors offer their versions of Serverless Stack. So what is Serverless? Does it really mean there are no servers (wes/servers are like cockroaches that cannot be gotten rid of or served -to pasify we Dev folks!). Then why do we need to worry about? For us business App/ System developers low-level plumbing/machinery details aren’t our concern.
A while back, my team at my company had a problem that I’m sure many of you have experienced – our server-based APIs were unable to handle the load of large, unpredictable traffic spikes. When we received a surge in traffic our EC2 instances couldn’t scale quickly enough and requests would be either denied or queued resulting in very slow response times, degradation of service and sometime even downtime. To prevent this we would have to over-provision servers and hence costs during normal or under-utilised off-peak hours. This was not only inefficient but also costly.
We need to find a better solution where we can both scale on demand as well as save on cost during quiet periods. AWS Lambda fit the use case perfectly.
The Turning Point: Going Serverless with AWS Lambda
We decided to take a plunge into serverless computing. Instead of adding more EC2 instances, we decomposed our application into individual Lambda functions. Every API endpoint became a Lambda function and API Gateway was used for routing.
Here’s what we did:
- We created a dedicated Lambda function for each of the core API calls. This allows you to scale each function independently of others.
- We had used API Gateway in order to direct any incoming HTTP requests towards the appropriate Lambda function.
- Moreover, DynamoDB was integrated with our database as it happened to be a good fit for the kind of serverless architecture that we were running.
Almost instantly, we began to see the rewards. Traffic surges? Don't worry—AWS Lambda scaled automatically with traffic. Idle servers? Not anymore —Lambda only billed us for the requests it processed. After our first month, we had reduced our operational costs by 40%.
Why Serverless? Here Are the Benefits We Reaped
- Cost-Efficiency: You Pay for What You Use
In our traditional model we paid for servers to be running irrespective of whether anything was being executed on the server or not. Lambda being an event-driven model, we pay only for the compute time consumed. It is like paying only for the milliseconds EC2 instance is used by Lambda during each request.
- Secondly, No need to configure auto-scaling thresholds and policies, decide when a new instance should be launched, etc. Let AWS handle all of that.
One of the most stressful parts of running web applications is figuring out how to handle sudden spikes in traffic. Lambda took that burden off our shoulders. It scaled automatically—whether we had one request per minute or 1,000 requests per second. I remember a particularly busy day when traffic spiked during a product launch, and Lambda effortlessly handled it all without us lifting a finger.
- Faster Deployments: Iterate and Release with Confidence
Serverless made deployment a breeze. We didn’t need to provision servers, we just wrote code and pushed it into production. It took our time to deployment from days to hours. Our team could iterate quickly on features, test things in isolation and also update things without any concern about server management.
Challenges We Faced (and How We Solved Them)
Serverless sounds like a dream, but it wasn’t without some challenges. Here are two we faced and how we conquered them.
- Cold Starts: The Speed Bump
At first, we had cold starts where the very first request to a Lambda function would take longer to process because AWS needed to “spin up” the resources. It wasn’t bad, but it would add some extra unnecessary latency on a few API calls we made.
The Solution: We used Provisioned Concurrency which kept a specific number of Lambda instances warm and ready to handle requests at all times. And for other less critical functions, we improved our initialization process so that cold starts weren’t as noticeable. This made cold starts a non-issue 99% of the time for us when it came it performance.
- Monitoring and Debugging: Where’s My Server?
When we first moved to Lambda, we were used to having direct access to server logs. In a serverless world, this was no longer existent. We needed a way to monitor, log, and debug our lambda functions.
The Solution: In order to achieve this we used AWS CloudWatch & AWS X-Ray for monitoring and logging in real-time at scale. CloudWatch gave us performance metrics and logs per function invocation, X-Ray gave us insights about how our Lambda functions were interacting with each other and external services. Both these tools together helped us keep eyes on our entire system health without missing anything.
How to Build a Simple Serverless App with AWS Lambda
Let me walk you through the process of setting up a basic serverless web application using Node.js, AWS Lambda, and API Gateway.
Step 1: Create the Lambda Function
Start by creating a simple Lambda function in Node.js that responds to HTTP requests. Here's a simple example:
Step 2: Set Up API Gateway
Next, create an API Gateway and configure it to trigger your Lambda function when an HTTP request is received. API Gateway allows you to expose the Lambda function to the web as a REST API.
Step 3: Add DynamoDB for Persistence
If your app needs to store or retrieve data, use DynamoDB as your database. Here’s how you can modify your Lambda function to read from a DynamoDB table:
Step 4: Deploy the Application
Deploy your Lambda function and API Gateway configuration. Now, you have a fully serverless web application that scales automatically and integrates seamlessly with DynamoDB.
The Future of Serverless: What’s Next?
As I look back, one thing is certain – Serverless architecture is the future. It’s a perfect fit to cater the increasing demand of IoT, mobile backs and real time data processing.
Going serverless not only made us highly scalable and operation costs cheaper, but it let us focus on what actually mattered in building great features.
No matter if you are running a small application or global platform, the flexibility, efficiency and the ability to scale automatically is unmatched using serverless architecture. The infrastructure concern is left behind. This is so exciting to see how this technology will improve going forward and continue changing web development landscape.
Conclusion: Ready to Go Serverless?
Our journey toward using AWS Lambda was well worth it. We reduced costs, simplified architecture, and removed unnecessary undifferentiated heavy lifting. We provided more efficient and reliable services. Yet we had to confront some limitations with cold starts and monitoring.
If you’ve been thinking about going serverless, I can tell you it’s pretty awesome. Web development just got a whole lot cooler with serverless!
Have you fought the same battles or are considering going serverless? Let’s talk about it, I’d love to hear your experience!
Top comments (2)
Thanks for sharing your experience! I recently deployed an AI app to AWS Lambda. The main challenge was to handle heavy dependencies. I had to package everything into a .zip file and upload it to S3 first (package size larger than 50MB), and I also hit the 250MB code size limit. I'm curious if you've seen something similar when you deploy a more complex app to Lambda?
@qianl15 Yes, I’ve encountered a similar situation when working on a complex application with a large set of dependencies. It's a tough issue but there is some hope if you can split your application into logical sub-functions. When I tried to deploy the app it hit the limit as well but I managed to create a "core" lambda that had two sub-lambdas and split dependencies between them.
However, this option might not be suitable especially when the logic is tightly coupled. In this case, I believe the feature you are looking for is Lambda Layers which does just what it says - share dependencies between Lambda functions thus reducing bundle size and making life easier when maintaining and deploying them.
In your case, you could package the larger dependencies such as AI libraries or frameworks into a Layer and reference it in your Lambda function. That way, you won't hit the 250MB limit and can also manage dependencies more efficiently.
If this does not work for you due to heavy dependencies, one easy way is to push some of the heavy-duty works into Amazon S3 itself! Using EFS for Lambda is another option if your application needs access to larger datasets or libraries.
Hope this helps!