App autoscaling presents non-trivial challenges. Here I share my experiences deploying with Laravel Vapor, a serverless platform.
Project Size
The project exceeds 650MB, exceeding Lambda's 250MB unzipped limit. We removed binaries from composer dependencies and dev dependencies, but this proved insufficient.
The solution involved leveraging Lambda layers via Docker, which supports up to 10GB per layer. Implementation required adding:
runtime: docker
Then creating an associated Dockerfile using:
vapor env my-environment --docker
Building Assets
Docker-based local development required adjusting deployment scripts. Standard composer install doesn't work locally; commands must run via:
docker-compose exec
Working Directories
The storage directory is not available via Lambda. Files and configurations stored there became inaccessible in production.
Laravel Passport
Lambda containers reset with each request, breaking persistent storage. Solutions included using EFS (expensive) or storing certificates in environment variables via Secrets Manager.
The code block requiring removal:
Passport::loadKeysFrom(storage_path("some_path"));
Reference: Laravel Passport documentation
Public Folder File Limits
Vapor restricts public folders to 400 files maximum. Many projects have more than 400 files there, making this a significant limitation. Assets must upload to S3 externally, and use Laravel's asset() helper for URLs.
Debugging Challenges
Serverless debugging proves difficult. SSH access is unavailable; deployments consume several minutes (up to 8 minutes observed), making iterative debugging time-consuming.
Queues
Vapor uses SQS instead of Horizon. Configuration requires checking config/queues.php. Job queue names must be explicitly specified; omitting them causes failures.
SQS executes jobs sequentially across all queues. This creates bottlenecks: for example, if you have lots of cron jobs and someone signs up at that moment, all jobs will be put on one queue. It will take some time for a user to receive a confirmation code which is not a good experience.
Environment Variables and AWS Keys
AWS credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) appeared null in config files despite existing in the environment. Debugging required creating a custom CLI command:
<?php
namespace App\Console\Commands\Vapor;
use Illuminate\Console\Command;
class GetEnv extends Command
{
protected $signature = 'tc:vapor:get_env {--env=} {--config=}';
protected $description = 'Get env value';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$env = $this->option('env');
if ($env) {
$this->info('ENV VALUE:');
if (env($env)) {
$this->info(env($env));
} else {
$this->warn('No value');
}
}
$cfg = $this->option('config');
if ($cfg) {
$this->info('Config VALUE:');
if ($value = config($cfg)) {
if (!is_string($value)) {
dump($value);
} else {
$this->info($value);
}
} else {
$this->warn('No value');
}
}
}
}
Running via Vapor dashboard avoided repeated deployments with debugging code.
Multiple AWS Accounts
Vapor supports multiple AWS accounts under single team ownership, useful for multiple clients. Add accounts via Team Settings, then select the appropriate account when creating projects.
Exif Extension
Installing the Exif extension requires Dockerfile modification:
FROM laravelphp/vapor:php74
RUN docker-php-ext-configure exif
RUN docker-php-ext-install exif
RUN docker-php-ext-enable exif
COPY . /var/task
Conclusion
Production migration remains unsuitable due to limitations and unresolved issues. Vapor represents excellent tooling for new applications expecting heavy traffic but falls short for mature projects requiring traditional infrastructure patterns.