home / skills / anilcancakir / my-claude-code / laravel-infrastructure

laravel-infrastructure skill

/skills/laravel-infrastructure

This skill optimizes Laravel infrastructure by coordinating Horizon, Octane, Reverb, Redis, and PostgreSQL to improve queues, caching, and real-time

npx playbooks add skill anilcancakir/my-claude-code --skill laravel-infrastructure

Review the files below or copy the command above to add this skill to your agents.

Files (4)
SKILL.md
6.2 KB
---
name: laravel-infrastructure
description: "Laravel Horizon queues, Octane performance, Reverb WebSockets, Redis caching, PostgreSQL database. ALWAYS activate when: working with queue jobs, cache, sessions, broadcasting, database performance, supervisor, worker. Triggers on: job failed, queue stuck, cache not clearing, Redis connection, broadcast event, WebSocket, real-time, Horizon dashboard, Octane memory leak, slow query, N+1, database timeout, connection refused, kuyruk çalışmıyor, cache temizlenmiyor, job başarısız, worker durdu, broadcast çalışmıyor, real-time gelmiyor."
---

# Laravel Infrastructure

Horizon, Octane, Reverb, Redis, and PostgreSQL patterns for Laravel 12+.

## Horizon (Queue Management)

### Installation

```bash
composer require laravel/horizon
php artisan horizon:install
php artisan migrate
```

### Configuration

```php
// config/horizon.php
'environments' => [
    'production' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default', 'high', 'low'],
            'balance' => 'auto',
            'maxProcesses' => 10,
            'minProcesses' => 1,
            'memory' => 128,
            'tries' => 3,
            'timeout' => 60,
        ],
    ],
    'local' => [
        'supervisor-1' => [
            'connection' => 'redis',
            'queue' => ['default'],
            'balance' => 'simple',
            'processes' => 3,
            'tries' => 3,
        ],
    ],
],
```

### Running Horizon

```bash
# Development
php artisan horizon

# Production (with Supervisor)
# /etc/supervisor/conf.d/horizon.conf
[program:horizon]
process_name=%(program_name)s
command=php /var/www/app/artisan horizon
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/app/storage/logs/horizon.log
stopwaitsecs=3600
```

### Dispatching Jobs

```php
// Dispatch to specific queue
ProcessOrder::dispatch($order)->onQueue('high');

// Delayed dispatch
ProcessOrder::dispatch($order)->delay(now()->addMinutes(5));

// Chain jobs
Bus::chain([
    new ProcessOrder($order),
    new SendConfirmation($order),
    new NotifyWarehouse($order),
])->dispatch();
```

---

## Octane (High Performance)

### Installation

```bash
composer require laravel/octane
php artisan octane:install

# Choose: Swoole or RoadRunner
```

### Running

```bash
# Development
php artisan octane:start --watch

# Production
php artisan octane:start --workers=4 --task-workers=6
```

### Important: Memory Leaks

```php
// AVOID: Static properties accumulating data
class BadService
{
    private static array $cache = [];  // Memory leak!
}

// GOOD: Use request-scoped or proper cache
class GoodService
{
    public function __construct(
        private readonly Repository $cache
    ) {}
}
```

### Octane-Safe Patterns

```php
// Reset singletons between requests
// AppServiceProvider
public function register(): void
{
    $this->app->singleton(ShoppingCart::class, function ($app) {
        return new ShoppingCart();
    });
}

// In Octane config
'flush' => [
    ShoppingCart::class,
],
```

---

## Reverb (WebSockets)

### Installation

```bash
composer require laravel/reverb
php artisan reverb:install
```

### Configuration

```env
BROADCAST_DRIVER=reverb
REVERB_APP_ID=my-app
REVERB_APP_KEY=my-key
REVERB_APP_SECRET=my-secret
REVERB_HOST=localhost
REVERB_PORT=8080
```

### Running

```bash
php artisan reverb:start
```

### Broadcasting Events

```php
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;

class OrderStatusUpdated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets;

    public function __construct(
        public Order $order
    ) {}

    public function broadcastOn(): array
    {
        return [
            new Channel('orders.' . $this->order->id),
        ];
    }

    public function broadcastAs(): string
    {
        return 'status.updated';
    }
}
```

### Frontend (Laravel Echo)

```js
Echo.channel('orders.123')
    .listen('.status.updated', (event) => {
        console.log('Order status:', event.order.status);
    });
```

---

## Redis

### Caching

```php
use Illuminate\Support\Facades\Cache;

// Store
Cache::put('key', 'value', now()->addMinutes(10));
Cache::forever('key', 'value');

// Retrieve
$value = Cache::get('key', 'default');
$value = Cache::remember('key', 60, fn () => expensive());

// Remove
Cache::forget('key');
Cache::flush();

// Tags
Cache::tags(['users', 'orders'])->put('user:1:orders', $orders, 60);
Cache::tags(['users'])->flush();
```

### Sessions

```env
SESSION_DRIVER=redis
```

### Locks

```php
$lock = Cache::lock('processing-order-' . $orderId, 10);

if ($lock->get()) {
    try {
        // Process order
    } finally {
        $lock->release();
    }
}
```

---

## PostgreSQL

### Configuration

```env
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=myapp
DB_USERNAME=postgres
DB_PASSWORD=secret
```

### PostgreSQL-Specific Features

```php
// JSONB columns
Schema::create('settings', function (Blueprint $table) {
    $table->id();
    $table->jsonb('data')->default('{}');
    $table->index('data', 'settings_data_gin')->using('gin');
});

// Query JSONB
$users = User::whereJsonContains('settings->notifications', 'email')->get();
$users = User::where('settings->theme', 'dark')->get();

// Full-text search
$products = Product::whereFullText('name', 'laptop')->get();
```

## References

| Topic | Reference | When to Load |
|-------|-----------|--------------|
| Horizon details | [references/horizon.md](references/horizon.md) | Supervisor, tags, batches |
| Octane caveats | [references/octane.md](references/octane.md) | Memory, concurrency |
| Reverb channels | [references/reverb.md](references/reverb.md) | Private/presence channels |

## Quick Commands

```bash
# Horizon
php artisan horizon
php artisan horizon:status
php artisan horizon:pause
php artisan horizon:continue
php artisan horizon:terminate

# Octane
php artisan octane:start
php artisan octane:reload
php artisan octane:stop

# Reverb
php artisan reverb:start

# Cache
php artisan cache:clear
php artisan config:cache
php artisan route:cache
```

Overview

This skill provides production-ready patterns and operational guidance for Laravel infrastructure: Horizon queues, Octane performance, Reverb WebSockets, Redis caching, and PostgreSQL. It focuses on reliable queue management, real-time broadcasting, memory-safe Octane usage, cache and session reliability, and database performance techniques. Activate when working with jobs, workers, caching, broadcasting, or database tuning.

How this skill works

The skill inspects queue and worker definitions, Horizon supervisor configuration, and common queue failure modes to diagnose stuck jobs or worker crashes. It checks Octane-safe coding patterns, singleton flush lists, and exposes memory-leak risks. It validates Reverb broadcast configuration and WebSocket connectivity, and verifies Redis caching, locks, and session settings. It also highlights PostgreSQL-specific schema and query patterns for JSONB, full-text, and slow-query detection.

When to use it

  • When a job fails or repeatedly retries
  • When queues are stuck or workers stopped
  • When cache entries won’t clear or Redis connections fail
  • When broadcast or WebSocket events don’t arrive in real time
  • When Octane shows memory growth or unexpected behavior
  • When PostgreSQL shows slow queries, N+1 issues, or connection timeouts

Best practices

  • Define Horizon supervisors per environment and limit memory/tries to prevent runaway processes
  • Use Octane-safe patterns: avoid request-accumulating statics and flush singletons between requests
  • Use Redis locks for idempotent job processing and Cache::tags for targeted invalidation
  • Run Horizon under Supervisor in production with long stopwaitsecs and proper user permissions
  • Broadcast via Reverb with authenticated channels and test with Laravel Echo in staging
  • Use JSONB indices, full-text search, and eager loading to prevent N+1 and speed queries

Example use cases

  • Diagnose a stalled Horizon queue and restart supervisors with safe job backoff
  • Harden Octane by identifying singleton services to flush and reducing worker counts to test memory behavior
  • Fix missing real-time updates by validating Reverb env vars, ports, and Laravel Echo listeners
  • Implement Redis tag-based cache invalidation to avoid full cache flushes in production
  • Tune PostgreSQL queries: add JSONB GIN indices, convert slow Eloquent loops to batched queries

FAQ

What should I do when Horizon shows jobs stuck in reserved state?

Check worker processes, ensure Supervisor is running, review job timeouts and memory limits, and inspect Redis for connection errors. Restart Horizon after addressing root cause.

How do I find Octane memory leaks?

Search for static properties, long-lived singletons, or in-memory accumulators. Add classes to Octane flush config and prefer request-scoped services or external caches.