Lessons learned migrating to Laravel Vapor

Jun 4, 2021

Recently, I was involved in a move from Linode to AWS Lambda. We chose to use Laravel Vapor considering it was a Laravel project and going serverless would satisfy our main reason for moving - scalability and concurrency.

The move went ok for the most part, but there were some real obstacles that were not entirely visible from the start.

Benefits

There are clear, theoretical benefits from moving to a serverless infrastructure. No more server setup. No more updating and patching of servers. You only have to scale and size the related services - redis, database and the like.

Laravel Vapor makes it very easy to get things up and running.

Service management and environments

Create a project in Laravel Vapor, add database, DNS records, redis cache and environments for production, staging, test, development - it's all very easy to set up in the Laravel Vapor interface. Adding RDS Proxy or load balancers is easy.

Deployment

Deploying to AWS Lambda through Laravel Vapor is also quite easy. A yml file to describe the environments, services to use, actions to perform during build or deploy and off you go. It works very well from both development machines and continuous delivery systems.

Queue processing

My favourite part of Vapor's use of AWS Lambda is how the queues are processed. By default, Vapor sets up SQS for the queues so that an incoming job is automatically sent to a Lambda function executing your Laravel project for that particular queue job. No long running process that continuously checks the queue for new jobs, it is all handled by SQS and Lambda on-demand.

Cron job processing

Cron jobs are similarly executing a Lambda function triggered by a timer in CloudWatch. Pure genius.

Limitations

Although the benefits are clear and the execution in Vapor is easy to use, there are some limitations to be aware of.

Service settings

Vapor is basically a re-implementation of certain parts of the AWS console. Vapor makes it easier to set up, but the result is configuration of AWS resources that is possible to do directly in the AWS console.

However, this also means that not all options are available through Vapor. When it comes to which RDS engines to use for the database or encryption settings for the ElastiCache clusters, Vapor limits the options.

Lambda response size limits

The Vapor documentation correctly lists that there is a limit on response sizes from Lambda of 6 MB that should be considered. In most cases, this will only be a problem when the response is a file to download, in which case Vapor docs suggest to place the file on S3 and generate a temporary URL. A very good solution to that particular problem.

The 6 MB limit is only when accessing Lambda through the default API Gateway, though. Should you be in need of a load balancer - for example if your project runs on wildcard subdomains - the limit is 1 MB. This is very well hidden in AWS documentation, but it means that you are much more likely to hit the response size limit when using a load balancer, and will need to make changes to the application in order to fit this limit.

Lambda timeouts

There is a hard limit of 15 minutes execution time on a Lambda function. This means that a cron or queue job that does a lot of processing, runs the risk of timing out. Applications may need to split up processing into smaller jobs that can be queued and processed asynchronously in order to fit this limit.

Scalability and consequences

Serverless infrastructure promises endless scalability, but the devil is in the details here. While the Lambda infrastructure can scale easily to 1000 concurrent processes - and this limit can be increased by AWS engineers - the related services may become bottlenecks.

Concurrency

When moving from a standard infrastructure with a given number of webserver processes and queue workers, you can experience sudden spikes if you do not limit the concurrency of Lambda functions. Processing a thousand queue jobs in 20 concurrent processes may not stress the database, but if you are suddenly processing all thousand jobs simultanously, database locking, deadlocks and waits may become more apparent. Not to mention the increased load on the database servers' CPU and RAM - or external services that your application may communicate with. Laravel Vapor does give options to restrict the number of concurrent queue processes, but it is an important area to consider and tweak in order not to overload other services.

Spin-up latency

With AWS Lambda, you no longer have a webserver ready to receive incoming requests. Instead, the request is routed through a load balancer or API Gateway to a Lambda function. Usually this means, initialising a new Lambda function and processing the request. AWS Lambda is extremely fast in initiating a new function, but it can be with a noticeable delay.

Vapor makes it easy to warm up Lambda functions or keep a number of idle functions at the ready, but you should keep in mind that it is not free - if the number of functions at-the-ready is higher than needed, you are paying for processing, you do not use. It can very quickly become quite expensive.

Other considerations

With all the niceness and buzzwordy feel-good feelings surrounding serverless infrastructure and Laravel Vapor, there are also other considerations to take before jumping into the frenzy.

Access permissions

Securing an AWS account can be taken to the extremes, but it can also be too loose. Laravel Vapor suggests giving them administrator access so they can set up everything in AWS from Vapor and while it is possible through personal contact with the Vapor team to get a specified list of needed permissions, it is not readily available. This may be a concern for some, but you could argue that if they have that kind of lowest privilege policy, they most likely will also have the knowledge to set up and maintain the right permissions.

Conclusion

Laravel Vapor is an excellent product that can take a lot of the hassle out of managing your Laravel project on AWS Lambda. It has some genius and some shortcomings so my verdict is that it is not for everyone.

Personally, I am not convinced that AWS Lambda is a great solution for replacing a web server, but it is absolutely magnificient for queue and cron processing.

Now, if only they would extend Vapor to be able to deploy the web responding part on AWS Elastic Container Service (ECS) while keeping the queue and cron on Lambda, I would absolutely love it - even if my needs for service configuration exceeds what Vapor provides. Just being able to package and deploy the project on Lambda AND ECS in one go, would be worth the monthly $40 for me.

by Jan Keller

Long time developer, architect and CTO with a real love for the backend. On this blog, I give out insight gathered through working with Vue, Nuxt, Laravel and more, when building and maintaining our SaaS.

Catch me on Twitter and Github

Restructuring a Laravel application using Domains, Actions and more

In coding tutorials, much is often left out in order not to be too verbose, to keep the complexity down or because it feels over engineering to follow through with the examples. I will give a full structural suggestion based on my experience that can be applied directly, regardless of the project size.

Jan Keller Jun 8, 2022

Mutation Testing - the missing link

Mutation testing can give your tests that extra confidence level not achieved simply by measuring code test coverage.

Jan Keller Dec 15, 2021

TDD without tests first approach

TDD is synonymous with writing tests first and implementations later. I want to challenge that approach as a catch-all do-all approach.

Jan Keller Dec 15, 2021

SurveyUno User Survey

The results of the first SurveyUno user survey are in - and while there is room for improvements, they are overwhelmingly positive

Jan Keller Aug 13, 2021