Deploying Laravel on AWS Lambda with Vapor

Khimananda Oli 8 min read Cloud
Deploying Laravel on AWS Lambda with Vapor

By Khimananda Oli | Last reviewed: August 2026

Deploying Laravel on AWS Lambda with Vapor transforms a traditional monolithic PHP application into a scalable, serverless workload without rewriting your codebase. While standard EC2 or VPS deployments require manual provisioning and maintenance, Vapor abstracts the underlying AWS infrastructure while retaining full control over the deployment pipeline. This approach is ideal for teams needing auto-scaling and reduced operational overhead, provided you understand the constraints of ephemeral storage and execution time limits.

CloudFrontStatic AssetsAPI GatewayHTTP RoutingAWS LambdaLaravel RuntimeRDS / AuroraManaged DBS3 BucketUser UploadsSQS QueueAsync Jobs
Serverless architecture for deploying Laravel on AWS Lambda with Vapor: requests flow through CloudFront and API Gateway to Lambda, which connects to managed databases and S3 storage.

How do you configure an existing project for deploying Laravel on AWS Lambda with Vapor?

Before you can deploy, your application must be adapted for a read-only filesystem and stateless execution. If you are evaluating whether this architecture suits your workload compared to traditional hosting, review our comparison of serverless with AWS Lambda when it actually makes sense. Vapor handles most adaptation automatically, but specific configuration ensures reliability.

Install the Vapor CLI and Core Package

The Vapor CLI orchestrates infrastructure provisioning via CloudFormation, while the core package adapts Laravel’s bootstrap process for the Lambda runtime. Install both globally and locally:

composer global require laravel/vapor-cli
composer require laravel/vapor-core

After installation, authenticate with your AWS account. Vapor uses your local AWS credentials to provision resources, so ensure your IAM user has sufficient permissions (AdministratorAccess is recommended for initial setup, then scoped down for production):

vapor login
vapor link my-laravel-project

Adapt File Storage and Sessions

Lambda functions have an ephemeral /tmp directory limited to 512 MB by default (expandable to 10 GB). You cannot store sessions, logs, or uploads locally. Update your .env.vapor.production file to use AWS-native drivers:

SESSION_DRIVER=dynamodb
CACHE_STORE=dynamodb
LOG_CHANNEL=stderr
FILESYSTEM_DISK=s3

Using DynamoDB for sessions and cache provides millisecond latency and automatic scaling. The stderr log channel streams logs directly to CloudWatch Logs, which is essential for debugging since you cannot SSH into a Lambda function. For teams managing multiple environments, understanding how to manage multiple environments in IaC helps keep staging and production configurations cleanly separated.

What infrastructure does Vapor provision during deployment?

When you run vapor deploy production, Vapor generates and executes a CloudFormation template that creates over 20 AWS resources. Understanding this stack is critical for troubleshooting and cost estimation.

  • API Gateway (HTTP API): Routes HTTP requests to your Lambda function. Vapor uses HTTP APIs (v2) rather than REST APIs for lower latency and reduced cost.
  • Lambda Function: Executes your Laravel application. Vapor configures a custom runtime using Bref or its proprietary runtime layer to support PHP 8.3+.
  • S3 Asset Bucket: Stores compiled frontend assets (CSS, JS, images). Vapor automatically versioned these during deployment.
  • CloudFront Distribution: Serves static assets from edge locations globally, bypassing Lambda entirely for cached content.
  • DynamoDB Tables: Created automatically if you use dynamodb for cache or sessions.
  • SQS Queues: Provisioned for each queue connection defined in vapor.yml.
  • CloudWatch Alarms & Log Groups: Basic error rate monitoring and centralized logging.
Local Machinevapor deployBuild ContainerComposer + NPMS3 ArtifactZipped BundleCloudFormationStack UpdateLambda LayerPHP Runtime
Vapor deployment pipeline: local CLI triggers a containerized build, uploads artifacts to S3, and updates the CloudFormation stack to deploy new Lambda versions.

The Role of vapor.yml

This configuration file defines environment-specific settings. A common mistake is leaving development defaults in production. Always explicitly set memory, timeout, and concurrency limits:

id: 12345
name: my-laravel-app
environments:
    production:
        memory: 1024
        timeout: 30
        concurrency: 250
        database: my-production-db
        cache: dynamodb-cache
        queues:
            - default
            - emails
        deploy:
            - 'php artisan migrate --force'

The deploy array runs commands after infrastructure updates but before traffic shifts. This is where you execute migrations. Note that migrations run inside a Lambda invocation, so they must complete within your configured timeout. For large schemas, consider running migrations separately via vapor tinker or a dedicated CI step.

How do you handle databases and secrets when deploying Laravel on AWS Lambda with Vapor?

Database connectivity is the most frequent failure point in serverless Laravel deployments. Lambda functions scale independently of your database, which can exhaust connection pools instantly during traffic spikes.

Use RDS Proxy for Connection Pooling

Never connect Lambda directly to an RDS instance in production. Each concurrent Lambda invocation opens a new database connection. With 250 concurrent Lambdas, you will hit MySQL/PostgreSQL max_connections limits rapidly. Enable RDS Proxy in your vapor.yml:

environments:
    production:
        database:
            name: my-production-db
            proxy: true

RDS Proxy maintains a pool of persistent connections and multiplexes Lambda requests across them. It also handles failover transparently. If you are choosing between database engines, our guide on MariaDB vs MySQL covers compatibility nuances relevant to Aurora Serverless.

Secrets Management Best Practices

Never commit database passwords or API keys to your repository. Vapor integrates with AWS Secrets Manager natively. Store secrets in Secrets Manager and reference them in vapor.yml:

environments:
    production:
        secrets:
            - arn:aws:secretsmanager:us-east-1:123456789:secret:laravel-prod-db-credentials
            - arn:aws:secretsmanager:us-east-1:123456789:secret:stripe-api-key

Vapor injects these as environment variables at runtime. Rotate secrets in Secrets Manager without redeploying — Lambda fetches fresh values on next invocation. For compliance-focused teams (SOC 2, ISO 27001), this audit trail is non-negotiable.

How does deploying Laravel on AWS Lambda with Vapor compare to traditional hosting?

Choosing between Vapor and traditional EC2/VPS hosting depends on traffic patterns, team expertise, and budget. The table below reflects real-world trade-offs observed across dozens of production deployments in 2026.

CriteriaVapor (Lambda)EC2 / VPS (Forge/LightSail)
ScalingAutomatic, instant to thousands of concurrent invocationsManual or ASG-based; minutes to scale up
Cold Start Latency200–800ms (mitigated with Provisioned Concurrency)None (always warm)
Cost at Low TrafficNear-zero (pay per request)Fixed monthly ($10–$50 minimum)
Cost at High TrafficCan exceed EC2 if unoptimized; watch API Gateway costsPredictable; cheaper above ~50M requests/month
FilesystemEphemeral; must use S3/DynamoDBPersistent EBS volumes
Long-running TasksMax 15 minutes; offload to SQS/Step FunctionsNo practical limit
DebuggingCloudWatch Logs only; no SSHFull SSH access; familiar tooling
Compliance Audit TrailNative CloudTrail + Config integrationRequires additional agent/tooling

Vapor excels for variable workloads, startups validating products, and applications requiring global edge caching. Traditional hosting remains superior for steady-state high traffic, legacy apps dependent on local filesystem writes, or teams lacking AWS expertise. For Nepali businesses serving primarily local users, note that AWS has no region in Nepal; latency to Mumbai (ap-south-1) averages 80–120ms. Pair Vapor with CloudFront to cache aggressively and reduce perceived latency for Kathmandu-based users.

Monthly Requests (Millions)Cost (USD)Vapor (Lambda)EC2 (t3.medium)1M10M50M100M200MCrossover Point~50M requests/month
Cost comparison for deploying Laravel on AWS Lambda with Vapor versus EC2: Vapor is cheaper below ~50 million requests per month; EC2 becomes more economical at sustained high volume.

How do you optimize performance and reduce costs after deploying Laravel on AWS Lambda with Vapor?

Post-deployment optimization separates viable production systems from expensive experiments. Focus on three areas: cold starts, payload size, and observability.

Mitigate Cold Starts Strategically

Cold starts occur when Lambda initializes a new execution environment. For Laravel, this includes bootstrapping the framework, loading service providers, and establishing database connections. Three tactics reduce impact:

  1. Provisioned Concurrency: Pre-warm a fixed number of instances. Use sparingly — it incurs hourly charges regardless of usage. Reserve for critical user-facing endpoints.
  2. Reduce Package Footprint: Remove unused Composer dependencies. Every megabyte added to the deployment bundle increases initialization time. Run composer install --no-dev --optimize-autoloader in your build step.
  3. Lazy Load Services: Defer heavy service provider registration until actually needed. Use Laravel’s deferred providers or conditional loading based on route patterns.

Optimize Asset Delivery

Vapor automatically pushes compiled assets to S3 and serves them via CloudFront. Ensure your build process generates hashed filenames for cache busting. In vite.config.js, verify build.rollupOptions.output.entryFileNames includes [hash]. Set long TTL headers in CloudFront behaviors for /assets/* paths. This prevents Lambda invocations for static content entirely.

Implement Structured Observability

CloudWatch Logs alone are insufficient for debugging distributed failures. Integrate OpenTelemetry early. Our guide on instrumenting an app with OpenTelemetry covers adding traces to Laravel applications. Export traces to AWS X-Ray or Grafana Tempo to visualize request flows across API Gateway, Lambda, RDS Proxy, and external APIs. Set alarms on P99 latency and error rates, not just invocation counts. A 500ms P99 may be acceptable; a 5-second tail latency indicates cold start or database contention issues requiring immediate attention.

Next Steps for Your Serverless Laravel Deployment

Deploying Laravel on AWS Lambda with Vapor offers genuine operational leverage when applied to suitable workloads. Start with a non-critical internal tool or staging environment to validate your team’s comfort with the debugging model and deployment cadence. Measure actual costs against projections for two billing cycles before migrating customer-facing traffic. If your application relies heavily on long-running processes, local file manipulation, or persistent WebSocket connections, reconsider — traditional hosting or container orchestration may serve you better. When you are ready to architect a production-grade serverless deployment or need an audit of your existing Vapor setup, reach out to discuss your infrastructure requirements.

Frequently Asked Questions

Vapor is a serverless deployment platform that automates provisioning and deploying Laravel applications to AWS Lambda, removing infrastructure management overhead.

Costs depend on AWS usage plus a $39 monthly Vapor subscription. Typical low-traffic apps run under twenty dollars monthly including compute, storage, and database expenses.

No. You must have an active AWS account with programmatic access credentials configured before installing or deploying any project through the Vapor CLI.

Yes. Vapor automatically provisions and renews Amazon Certificate Manager SSL certificates and configures CloudFront distributions for custom domains during deployment.

Run php artisan vapor:migrate after deployment. This executes migrations via a temporary Lambda function using your production environment variables and VPC configuration.

Vapor supports PHP 8.3 and 8.4 as stable runtimes. Always check the official Vapor documentation for the latest supported versions before upgrading production environments.

Vapor redirects file uploads directly to S3 using signed URLs. Local filesystem calls are intercepted and proxied to S3, eliminating ephemeral Lambda storage limitations.

Yes. Vapor uses CloudWatch Events for scheduling and SQS for queue workers. Both integrate natively with Laravel's scheduler and queue API without additional servers.

Check CloudWatch Logs via the Vapor dashboard. Increase execution time in vapor.yml if cold starts cause timeouts, and optimize bootstrapping with Octane or provisioned concurrency.

Yes, but configure provisioned concurrency to eliminate cold starts and set appropriate memory limits. Monitor throttling metrics and adjust reserved concurrency based on actual traffic patterns.

Vapor eliminates server maintenance and auto-scales instantly but has higher per-request costs at scale. EC2 offers predictable pricing and full OS control for steady workloads.

Yes. Place your Lambda functions in the same VPC and subnets as your RDS instance. Configure security groups to allow Lambda access to the database port.

Store secrets in vapor.yml encrypted sections or AWS Secrets Manager. Never commit plaintext credentials. Vapor injects decrypted values into Lambda at runtime automatically.

Yes. Enable Octane with RoadRunner or FrankenPHP in vapor.yml to reduce cold start times significantly. This keeps the application bootstrapped between invocations.

Deployed AWS resources continue running normally. You lose access to the Vapor CLI and dashboard for new deployments, updates, and log viewing until resubscribing.