Migrating Legacy PHP Applications to AWS Lambda: A Case Study

7 min read
PHP, AWS Lambda, Serverless
Share

When a client approached us with a ten-year-old PHP application running on a pair of EC2 instances, the brief was simple: reduce hosting costs and improve reliability without a full rewrite. The application handled around 50,000 requests per day with significant traffic spikes during business hours. After evaluating several options, we chose a phased migration to AWS Lambda using the Bref runtime.

Bref is a PHP runtime for AWS Lambda that provides a native execution environment for PHP applications. Unlike containerised approaches, Bref uses Lambda layers to provide the PHP binary, which keeps deployment packages small and cold start times reasonable. For a Laravel application, cold starts typically run between 300 and 800 milliseconds, which is acceptable for most web applications when combined with provisioned concurrency for critical endpoints.

The goal of migration is not to replicate your monolith in Lambda. It is to decompose it into services that benefit from serverless economics.

We did not attempt to migrate the entire application at once. Instead, we identified the components that would benefit most from serverless architecture: the API endpoints, background job processing, and scheduled tasks. The frontend rendering remained on a single small EC2 instance behind CloudFront, serving cached responses for the majority of page requests.

The Migration Strategy

The API layer was the first to migrate. We used Laravel Vapor as the deployment framework, which handles the API Gateway configuration, Lambda function packaging, and environment variable management. Each API route maps to a Lambda function that boots the Laravel framework, handles the request, and returns a response. Database connectivity uses RDS Proxy to manage connection pooling, which is essential because Lambda functions create new database connections on each cold start.

Background jobs moved to SQS-triggered Lambda functions. This was the area where we saw the most significant cost savings. The previous architecture ran a dedicated worker instance 24 hours a day processing an average of 2,000 jobs daily. With Lambda, each job runs in its own invocation, and we pay only for the compute time consumed. The worker instance cost approximately 45 pounds per month. The Lambda equivalent costs about 3 pounds per month.

  • Use Bref for PHP Lambda deployments rather than custom Docker runtimes
  • Implement RDS Proxy for database connection management
  • Migrate background jobs first for the quickest cost reduction
  • Use provisioned concurrency for latency-sensitive endpoints
  • Keep deployment packages under 50MB for faster cold starts
  • Monitor cold start frequency and optimise the most-invoked functions first

The total infrastructure cost dropped from approximately 280 pounds per month to 110 pounds per month, a reduction of 61%. More importantly, the system now scales automatically during traffic spikes that previously caused performance degradation. The migration took eight weeks of engineering time, and the client recovered the investment within four months.

Want to Chat?

Contact our friendly team for quick and helpful answers.

Contact us