Saltar al contenido principal

¿Qué es Octane?

Laravel Octane es un paquete que mejora drásticamente el rendimiento de las aplicaciones Laravel usando servidores de aplicaciones de alto rendimiento. En un PHP-FPM normal, la aplicación se arranca y se termina en cada solicitud. Con Octane, la aplicación se arranca una única vez y se mantiene en memoria, procesando las siguientes solicitudes con gran rapidez. La mayor diferencia respecto a PHP-FPM es que el proceso de arranque de la aplicación (registro de service providers, etc.) no se repite en cada solicitud. Al arrancar una sola vez, las solicitudes se procesan a altísima velocidad.

Servidores compatibles

Octane admite los siguientes tres servidores.
ServidorLenguajeInstalaciónTareas concurrentesNotas
FrankenPHPGoAutomática (binario)Recomendado. Soporta HTTP/3 y Brotli
RoadRunnerGoAutomática (binario)Sencillo y fácil de configurar
SwooleExtensión de PHPManual con PECLOfrece tareas concurrentes y la caché de Octane
En Laravel Cloud se recomienda operar Octane con FrankenPHP y ofrece soporte totalmente gestionado.

Instalación y configuración

Instalación del paquete

composer require laravel/octane

Configuración inicial de Octane

php artisan octane:install
Al ejecutarlo se muestra un prompt para elegir el servidor. Al seleccionarlo se genera config/octane.php.

FrankenPHP

Al elegir FrankenPHP, Octane descarga automáticamente el binario. No hacen falta pasos adicionales.

RoadRunner

Al elegir RoadRunner, Octane descarga automáticamente el binario.

Swoole

Swoole se instala como extensión de PHP con PECL.
pecl install swoole
Para usar Open Swoole, ejecuta:
pecl install openswoole

Cómo arrancar

Arrancar el servidor

php artisan octane:start
Por defecto arranca en el puerto 8000. Accede en http://localhost:8000.

Indicar el servidor

php artisan octane:start --server=frankenphp
php artisan octane:start --server=roadrunner
php artisan octane:start --server=swoole

Indicar el número de workers

php artisan octane:start --workers=4
Para especificar también los task workers en Swoole:
php artisan octane:start --workers=4 --task-workers=6

Observación de cambios en archivos

Durante el desarrollo, los cambios en los archivos no se reflejan sin reiniciar el servidor. Con --watch se reinicia automáticamente.
php artisan octane:start --watch
Para usar --watch necesitas Node.js y Chokidar.
npm install --save-dev chokidar

Otros comandos de gestión

# Recargar workers (ejecutar tras el despliegue)
php artisan octane:reload

# Parar el servidor
php artisan octane:stop

# Comprobar el estado del servidor
php artisan octane:status

Consideraciones sobre inyección de dependencias

En Octane la aplicación se mantiene en memoria, por lo que register y boot de los service providers solo se ejecutan una vez, al arrancar el servidor. La misma instancia de la aplicación se reutiliza entre solicitudes, así que hay que tener cuidado al inyectar el contenedor o la solicitud en el constructor de un objeto.

Inyección del contenedor

Si inyectas el contenedor directamente en el constructor de un singleton, se reutiliza un contenedor antiguo.
// ❌ Problemático: se reutiliza un contenedor antiguo
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app);
});

// ✅ Seguro: obtén siempre el contenedor más reciente con un closure
$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance());
});
Los helpers globales app() y Container::getInstance() siempre devuelven el contenedor más reciente, así que son seguros.

Inyección de la solicitud

// ❌ Problemático: se reutiliza una solicitud antigua
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app['request']);
});

// ✅ Seguro: obtén siempre la solicitud más reciente con un closure
$this->app->singleton(Service::class, function (Application $app) {
    return new Service(fn () => $app['request']);
});

// ✅ Más recomendado: pasa solo el valor necesario al método
$service->method($request->input('name'));
Tipar Illuminate\Http\Request en los métodos del controlador o en closures de ruta es seguro. El helper global request() también devuelve siempre la solicitud actual.

Inyección del repositorio de configuración

// ❌ Problemático: si los valores cambian, se usa un repositorio antiguo
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app->make('config'));
});

// ✅ Seguro
$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance()->make('config'));
});
El helper global config() siempre devuelve el repositorio de configuración más reciente, así que es seguro.

Mitigación de fugas de memoria

Como Octane mantiene la aplicación en memoria, acumular datos en propiedades estáticas provoca fugas.
// ❌ Ejemplo de fuga: $data crece con cada solicitud
class Service
{
    public static array $data = [];
}

public function index(Request $request): array
{
    Service::$data[] = Str::random(10);
    return [];
}

Reciclar workers con max-requests

Al reiniciar automáticamente el worker tras un cierto número de solicitudes se atenúan las fugas de memoria. El valor por defecto es 500 solicitudes.
php artisan octane:start --max-requests=250

Configuración del tiempo máximo de ejecución

Puedes definir el tiempo máximo de una solicitud en config/octane.php. Por defecto son 30 segundos.
'max_execution_time' => 30,
Si cambias max_execution_time, reinicia el servidor Octane.

Tareas concurrentes (solo Swoole)

Con Swoole puedes ejecutar varias operaciones en paralelo con Octane::concurrently().
use App\Models\User;
use App\Models\Server;
use Laravel\Octane\Facades\Octane;

[$users, $servers] = Octane::concurrently([
    fn () => User::all(),
    fn () => Server::all(),
]);
Las tareas concurrentes se ejecutan como “task workers” de Swoole en procesos separados. Indica el número con --task-workers.
php artisan octane:start --workers=4 --task-workers=6
A concurrently se le pueden pasar como máximo 1024 tareas (límite de Swoole).

Tick e Interval (solo Swoole)

En Swoole puedes registrar tareas que se ejecutan a intervalos regulares. Se registran en el método boot de un service provider.
use Laravel\Octane\Facades\Octane;

// Se ejecuta cada 10 segundos
Octane::tick('delayed-ticker', fn () => ray('Ticking...'))
    ->seconds(10);

// También se ejecuta inmediatamente al arrancar el servidor
Octane::tick('immediate-ticker', fn () => ray('Ticking...'))
    ->seconds(10)
    ->immediate();

Caché de Octane (solo Swoole)

Caché en memoria ultrarrápida basada en las tablas de Swoole. Soporta hasta 2 millones de lecturas/escrituras por segundo.
use Illuminate\Support\Facades\Cache;

Cache::store('octane')->put('framework', 'Laravel', 30);

Caché con intervalo

Caché que se actualiza automáticamente cada cierto tiempo.
use Illuminate\Support\Str;

Cache::store('octane')->interval('random', function () {
    return Str::random(10);
}, seconds: 5);
Los datos de la caché de Octane se pierden al reiniciar el servidor.

Tablas de Swoole (solo Swoole)

Puedes definir tablas en memoria accesibles desde todos los workers. Se configuran en tables de config/octane.php.
'tables' => [
    'example:1000' => [
        'name' => 'string:1000',
        'votes' => 'int',
    ],
],
Accede a la tabla con Octane::table().
use Laravel\Octane\Facades\Octane;

Octane::table('example')->set('uuid', [
    'name' => 'Nuno Maduro',
    'votes' => 1000,
]);

$row = Octane::table('example')->get('uuid');
Los únicos tipos de columna soportados por las tablas de Swoole son string, int y float. Los datos se pierden al reiniciar el servidor.

Operación en producción

Configuración Nginx + Octane

En producción es habitual ejecutar Octane detrás de Nginx. Nginx sirve los archivos estáticos y termina SSL, mientras que las solicitudes dinámicas se pasan por proxy a Octane.
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name example.com;
    root /home/forge/example.com/public;

    location /index.php {
        try_files /not_exists @octane;
    }

    location / {
        try_files $uri $uri/ @octane;
    }

    location @octane {
        set $suffix "";

        if ($uri = /index.php) {
            set $suffix ?$query_string;
        }

        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_pass http://127.0.0.1:8000$suffix;
    }
}

Ejecución permanente con Supervisor

En producción, usa Supervisor para mantener Octane siempre activo.
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/example.com/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/storage/logs/octane.log
stopwaitsecs=3600

Habilitar HTTPS

Para generar enlaces HTTPS a través de Octane, configura en .env:
OCTANE_HTTPS=true

Integración con Laravel Cloud

Laravel Cloud ofrece soporte totalmente gestionado para Octane con FrankenPHP. No necesitas configurar Nginx ni Supervisor: puedes activarlo en solo dos pasos.
1

Instalación del paquete

Instala Octane. Ejecutar octane:install es opcional.
composer require laravel/octane
2

Activar Octane en Laravel Cloud

En la configuración del cluster de cómputo del entorno, activa “Use Octane as runtime” y guarda/despliega. Laravel Cloud construirá y arrancará automáticamente la aplicación con FrankenPHP + Octane.
Consulta la documentación de Laravel Cloud para más detalles.

Recargar workers tras el despliegue

Tras un despliegue, recarga los workers para cargar el nuevo código en memoria.
php artisan octane:reload
Última modificación el 13 de julio de 2026