# Laravel best practices

This page collects practical advice for running a fast, stable Laravel application on TurboStack. Laravel is a [configuration-only application](deploy.md): the platform provisions PHP, the web server, MySQL and (optionally) Redis, while you bring and deploy your own code through [Git deployment](../../platform/hosts/applications/git-deployment.md). Most performance work therefore happens in your repository, while the platform provides the runtime and services to support it.

> [!NOTE]
> Because you control the code, the platform never runs Artisan commands for you. Compiling caches, running migrations and starting workers are steps you build into your own deploy process.

## What TurboStack configures for you

When you set an app's type to `laravel`, the platform applies an opinionated runtime so the framework works without manual web-server editing:

- **Nginx vhost** with the document root pointing at the application's public directory (`public_html`) and the standard front-controller rewrite (`try_files $uri $uri/ /index.php?$query_string`). This ensures clean URLs and route handling work without additional configuration.
- **PHP-FPM backend** per application, with a generous FastCGI timeout for longer requests and dotfile protection (everything under `/.` except `/.well-known` is denied).
- **OPcache** available in the PHP runtime to cache compiled bytecode.
- **MySQL** as the relational database, and **Redis** when you enable it as a service for cache, sessions and queues.
- **Supervisor**, available per system user, for keeping long-running processes such as queue workers alive.

Manage these building blocks from the host's [Services](../../platform/hosts/services.md) and [Applications](../../platform/hosts/applications/index.md) tabs.

## Recommended optimizations

Combine Laravel's own production guidance with the platform features above.

- **Cache configuration and routes** - run `php artisan config:cache` and `php artisan route:cache` in your deploy so framework bootstrapping is fast.
- **Cache views and events** - add `php artisan view:cache` (and `event:cache` if used) to precompile Blade templates and listeners.
- **Use the optimize shortcut** - `php artisan optimize` bundles the common production caches in one command.
- **Enable OPcache** - keep OPcache on in your PHP runtime; tune it under [Services](../../platform/hosts/services.md) > PHP advanced options.
- **Move cache and sessions to Redis** - set `CACHE_STORE=redis` and `SESSION_DRIVER=redis` once Redis is enabled, to offload the database and the local filesystem.
- **Run queues on Redis** - use `QUEUE_CONNECTION=redis` and process jobs with a worker rather than the `sync` driver for slow tasks (mail, exports, webhooks).
- **Keep workers alive** - run `php artisan queue:work` under a supervisor so jobs process continuously and restart on failure. Use the per-user Supervisor, or run the worker as a [user system service](../../technologies/system-services/manage-user-services.md). To clear a backlog faster, run several workers in parallel - but keep the total within the host's processor budget (see [Scale throughput with more instances](../../technologies/system-services/manage-user-services.md#scale-throughput-with-more-instances)).
- **Schedule with the scheduler** - point a single cron entry at `php artisan schedule:run` every minute and define tasks in Laravel rather than many crontab lines.
- **Optimize the autoloader** - deploy with `composer install --no-dev --optimize-autoloader` to drop dev dependencies and speed up class loading.
- **Optimize assets** - build front-end assets ahead of deploy (e.g. `npm run build` with Vite) and serve them as static files; add a Content Delivery Network (CDN) for heavy media.

> [!TIP]
> After any code or config change, re-run the cache commands. Stale `config:cache` output is a common cause of "my `.env` change had no effect".

## Sizing and scaling

TurboStack auto-tunes service memory from the host's resources, so the defaults suit most Laravel sites. Override the tuning variables only when you have measured evidence (slow queries, Redis evictions, OPcache restarts):

| Variable | Tune when |
| --- | --- |
| `mysql_innodb_size` | The InnoDB buffer pool is too small for your working set. |
| `redis_memory` | Redis is evicting keys you expect to persist (cache/queue churn). |

Make one change at a time and re-measure. See [Performance tuning](../../concepts/performance-tuning.md) for the full method, and scale PHP-FPM workers there too.

## Stability

- **Back up before changes** - confirm [Backups](../../platform/hosts/backups.md) cover the database and any user-uploaded files in `storage/`.
- **Watch [Health](../../platform/hosts/health.md)** - monitor CPU, memory and service status, especially after a deploy.
- **Keep versions current** - track Laravel long-term support (LTS) and PHP releases, and bump the PHP runtime under [Services](../../platform/hosts/services.md) on a supported version.
- **Test on a staging clone** - validate upgrades, migrations and cache changes on a copy before publishing to production.
- **Run migrations deliberately** - include `php artisan migrate --force` in your deploy step and review it for destructive changes first.

## Related

- [Deploy Laravel on TurboStack](deploy.md)
- [Troubleshooting Laravel](troubleshooting.md)
- [How to manage user system services](../../technologies/system-services/manage-user-services.md)
- [Services](../../platform/hosts/services.md)
- [Performance tuning](../../concepts/performance-tuning.md)
