Skip to main content

Laravel Cloud

Laravel Cloud is our deployment platform, replacing Laravel Vapor for hosting Laravel services. Not all projects are on Cloud yet - we're migrating incrementally.

Current State

Services

ServiceStatusNotes
farfallaVaporCore monolith
farfalla-https-guardCloudFirst migrated service
farfalla-integrationsVapor
medusaVapor
coniglioVapor
castoroVapor

How We Deploy

Deployments are triggered via deploy hooks from GitLab CI:

deploy:staging:
script:
- curl -X POST "$LARAVEL_CLOUD_STAGING_DEPLOY_HOOK"

deploy:production:
script:
- curl -X POST "$LARAVEL_CLOUD_PRODUCTION_DEPLOY_HOOK"

Deploy hooks are async - the curl returns immediately and the actual deployment happens in the background. No post-deploy health checks.

CI variables per project:

  • LARAVEL_CLOUD_STAGING_DEPLOY_HOOK
  • LARAVEL_CLOUD_PRODUCTION_DEPLOY_HOOK

Build & Deploy Commands

Configured in the Laravel Cloud dashboard per environment.

Build commands (typical):

composer install --no-dev --optimize-autoloader
php artisan event:cache
php artisan config:cache
php artisan route:cache

Deploy commands:

php artisan migrate --force
php artisan optimize

Custom Domains

We point custom domains to Laravel Cloud via Cloudflare CNAME (proxy ON), then disable the default .laravel.cloud domain.

Monitoring

Server-side PHP monitoring uses Laravel Nightwatch (auto-injected env vars by Cloud). Keep Sentry JS SDK for frontend monitoring.


Configuration Reference

Persistent DB Connections

Enabled for better performance, but disabled in tests (breaks parallel execution and Bus::batch()):

// config/database.php
'options' => [
PDO::ATTR_PERSISTENT => app()->environment('testing') ? false : true,
],

Valkey (Redis-compatible)

Cloud uses Valkey (Redis-compatible) with ACL auth. Needs both username and password:

// config/database.php, redis connection
'username' => env('REDIS_USERNAME'),

Symptom: Horizon can't connect to Valkey. Cause: Vapor didn't need a username. Cloud uses Valkey ACL requiring both.

Queue Connection

Cloud does NOT auto-set QUEUE_CONNECTION. Must add QUEUE_CONNECTION=redis to env vars manually, otherwise jobs run synchronously.

Symptom: Jobs not appearing in Horizon despite worker being active. Cause: Defaults to sync, so jobs run inline instead of being queued.

Horizon

  • Move laravel/horizon to require (not require-dev)
  • Cloud does NOT auto-protect Horizon - add HTTP Basic Auth middleware
  • Configure supervisors per environment in config/horizon.php
  • Create a Worker Cluster in Cloud dashboard with php artisan horizon
  • Schedule horizon:snapshot for non-local environments

Note: Vapor auto-protected Horizon in production. Cloud doesn't - you must add auth middleware yourself.

artisan optimize

Requires resources/views directory to exist. Create an empty one if your project doesn't have views.

Symptom: php artisan optimize fails with view:cache error.

Deploy Hooks Are Async

Deploy hooks return immediately; deployment happens in the background. Remove any post-deploy health check scripts that expect the deploy to be done.

Persistent DB Breaks Tests

Persistent connections cause issues with parallel test execution. Bus::batch() inserts and reads immediately, fails when connections are shared across test processes.

Fix: Disable in test environment (see Persistent DB Connections config above).


Resources

X

Graph View