# LaravelS: running Laravel on Swoole as a resident server

> LaravelS is an adapter that puts a Laravel or Lumen application inside a Swoole HTTP/WebSocket server instead of rebuilding it per request. It fits teams already on PHP 8.2 and Swoole 5 who need task queues, timers or WebSocket in the same process, and it fails badly for anyone who cannot give up per-request isolation.

**hhxsv5/laravel-s** — LaravelS is an out-of-the-box adapter between Laravel/Lumen and Swoole.

- Repository: https://github.com/hhxsv5/laravel-s
- Stars: 3,880 · Forks: 464
- Language: PHP
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/hhxsv5-laravel-s

## The problem LaravelS exists to solve

A standard Laravel deployment boots the framework on every request. The router, the service container, the config repository and the Eloquent bootstrapping all run again for each hit, and the process dies when the response is sent. For most applications that cost is invisible. For an application that answers thousands of requests per second, or that needs a WebSocket connection, a delayed job or a timer firing every few milliseconds, the per-request model becomes the constraint rather than the code you wrote.

LaravelS takes the opposite approach. It boots Laravel once inside a Swoole worker and keeps the framework in memory, so subsequent requests reuse the already-constructed container. The README describes it as an "out-of-the-box adapter between Laravel/Lumen and Swoole", and the feature list is really a list of things that only make sense once the application is resident: a built-in HTTP and WebSocket server, multi-port mixed protocol, custom processes, asynchronous event listening, an asynchronous task queue, millisecond cron jobs and graceful reload.

The audience is narrow and specific. You need PHP 8.2 or newer with the intl extension enabled, Swoole 5.0 or newer, and Laravel or Lumen 10 or newer. If your host cannot install a PHP extension, or you are on shared hosting, nothing here applies to you.

## How the adapter sits between Laravel and Swoole

LaravelS is not a fork of Laravel and it is not a Swoole wrapper library. It is a service provider plus a set of binaries. The provider is registered in config/app.php for Laravel (skipped on 5.5 and later because package discovery handles it) or in bootstrap/app.php for Lumen. Once registered, it wires Laravel's request handling into Swoole's server callbacks, so a Swoole worker receives the request, hands it to the framework, and returns the response without tearing the container down.

The binaries are the operational half. The install step publishes config/laravels.php together with bin/laravels, bin/fswatch and bin/inotify. The laravels binary is what you actually run; the other two exist for the auto-reload feature, which watches source files and restarts workers when they change. The configuration file is where listen_ip, listen_port and the worker counts live, and the README points to a separate Settings document for the full key list rather than enumerating everything inline.

Concurrency is handled the way Swoole handles it. LaravelS uses Swoole's Synchronous IO mode, so each worker serves one request at a time and throughput scales with worker_num. The README gives an explicit sizing rule: if one request takes 100ms and you want 1000 QPS, you need at least 100 workers, computed as worker_num = 1000/(1/0.1). More workers means more memory and more process-switching overhead, so the documentation tells you to find the number by incremental load testing rather than by copying a figure from a blog post. That is an honest admission that there is no universal setting.

## Installing LaravelS and starting the server

The install path is Composer plus one artisan command. The README pins the version constraint to the ~3.8.0 series for PHP 8.2 and newer, and notes that a separate ~3.7.0 line exists for PHP 5.5.9 through 7.4.33. It also warns that your composer.lock file should be under version control, which is standard Composer advice but worth repeating here because the published binaries change between releases.

```bash
composer require "hhxsv5/laravel-s:~3.8.0"
```

After the package is installed, register the provider. On Laravel 5.5 and later the README says package discovery makes this step unnecessary, so skip it. On Lumen you add the registration line to bootstrap/app.php.

```php
$app->register(Hhxsv5\LaravelS\Illuminate\LaravelSServiceProvider::class);
```

Publishing is the step people forget. It writes the configuration file and the three binaries into your project.

```bash
php artisan laravels publish
# Configuration: config/laravels.php
# Binary: bin/laravels bin/fswatch bin/inotify
```

At this point you edit config/laravels.php, at minimum listen_ip and listen_port, then start the server with the published binary. The README's Run section says to read the Important notices first, and that instruction is not decorative: the notices cover the memory-resident model and what it means for global state. After publishing, the expected result is a Swoole server listening on the address you configured, with your existing Laravel routes answering on it.

## The resident-process trap and other real limitations

The single biggest failure mode is state that survives between requests. In a normal PHP deployment, every global, static and singleton is created fresh per request, so a bug that leaves a value behind is invisible. Under LaravelS the worker process persists, and anything you stored outside the request lifecycle is still there when the next request arrives. The README's Important notices section exists precisely for this, and the project ships a KnownIssues.md and KnownIssues-CN.md at the repository root, which tells you the maintainers consider this a documented class of problem rather than an edge case.

Synchronous IO mode is the second constraint, and it is a design choice rather than a defect. Because each worker blocks on one request, a slow downstream call holds a worker for its full duration. The 100ms-to-100-workers arithmetic in the README is not a tuning suggestion, it is the shape of the system: latency and worker count are directly coupled, and memory grows with the worker count you choose. A single heavy endpoint can force you to over-provision workers for the whole application.

The third limitation is environmental. Swoole is a PHP extension, and the requirements table is strict: PHP 8.2 or newer, Swoole 5.0 or newer, Laravel or Lumen 10 or newer. Any of those three being older rules LaravelS out entirely. If you are on a managed platform that does not let you load custom extensions, or you are running PHP 7.x and cannot upgrade, this is the wrong tool and no configuration will change that.

Finally, the README does not document rollback. It says to republish after upgrading LaravelS because configuration and binaries change between versions, but it does not describe how to revert a release once it is running. Plan for that with your own deployment tooling.

## Where LaravelS stops and RoadRunner or FrankenPHP begins

The closest alternative in the PHP world is RoadRunner, a Go-based application server that speaks to PHP workers over a protocol rather than through an extension. The difference in approach matters more than any feature list. RoadRunner is a separate process you install, and your PHP application stays an ordinary PHP application that the server drives; you do not need Swoole compiled into PHP, and the worker lifecycle is managed from outside.

LaravelS takes the embedded route. Swoole is a PHP extension, so the server and the application live in the same process, which is what makes Swoole\Table, custom processes, millisecond timers and the task queue available to your Laravel code directly. That integration is the reason to pick LaravelS, and it is also the reason the requirements table is so strict. RoadRunner gives you a resident worker without an extension but does not hand you Swoole's in-process primitives; LaravelS gives you those primitives but ties you to a specific PHP and Swoole version pair.

If your reason for looking at LaravelS is only "I want fewer framework boots per request", RoadRunner is the lower-commitment option because it does not touch your PHP installation. If your reason is "I want WebSocket, async tasks and millisecond cron inside the same process as my Laravel app", that is the case LaravelS was built for and RoadRunner does not cover it the same way.

## Maintenance, licensing and the cost of upgrading

The repository is not archived, and the last push was on 2026-07-20. Recent releases follow a steady pattern: v3.8.6 on 2025-11-24, v3.8.7 on 2026-01-17, and v3.8.8 on 2026-07-20. The README's own Continuous Updates section asks readers to watch the repository for updates rather than promising a schedule, so treat release cadence as observed behaviour rather than a commitment.

The upgrade cost is real and specific. The README states plainly that after upgrading LaravelS you need to republish, and links to the releases page for the change notes of each version. That means config/laravels.php and the bin/ binaries are generated artifacts you must regenerate, and any local edits to the published config need to be reapplied or kept in a separate tracked file. The version constraints compound this: the ~3.8.0 line needs PHP 8.2 or newer, while ~3.7.0 covers PHP 5.5.9 through 7.4.33, so a PHP upgrade and a LaravelS upgrade are usually the same project.

The license is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are included. That is a permissive license with few obligations, but I am not a lawyer and this is not legal advice; if your organisation has a policy on bundled dependencies, check the LICENSE file at the repository root yourself.

## Conclusion

Adopt LaravelS if you are already on PHP 8.2, Swoole 5 and Laravel 10 or newer, and you want HTTP, WebSocket, asynchronous tasks and millisecond cron in one resident process. Do not adopt it if your application relies on per-request global state, or if you cannot run Swoole as a PHP extension at all, because the whole design assumes a memory-resident worker. Before writing any application code, verify three things in your own environment: that the intl extension is enabled, that your Swoole build is at least 5.0, and that every piece of state you currently keep in a global or static is either reset per request or moved into a Swoole\Table, since LaravelS does not clear that state for you.

## FAQ

### What is LaravelS used for?

LaravelS is an adapter between Laravel or Lumen and Swoole. It runs your application inside a Swoole HTTP and WebSocket server, keeping the framework in memory instead of booting it per request, and adds asynchronous task queues, millisecond cron jobs, custom processes and multi-port mixed protocol support.

### What are the requirements for installing LaravelS?

The README's requirements table lists PHP 8.2 or newer with the intl extension enabled, Swoole 5.0 or newer, and Laravel or Lumen 10 or newer. The Composer constraint for that combination is hhxsv5/laravel-s:~3.8.0.

### How many Swoole workers should I configure for LaravelS?

LaravelS uses Swoole's Synchronous IO mode, so each worker handles one request at a time. The README gives the formula worker_num = QPS / (1s / request time in seconds), so 1000 QPS at 100ms per request needs at least 100 workers, and it says to find the best value through incremental load testing because more workers cost more memory and process switching.

### What happens to global and static state in LaravelS?

Because the framework stays resident in the worker, state kept outside the request lifecycle persists between requests instead of being reset. The README points to an Important notices section for this, and the repository root carries KnownIssues.md and KnownIssues-CN.md as separate documents.

### Do I need to republish the LaravelS configuration after upgrading?

Yes. The README says that after upgrading LaravelS you need to republish, which regenerates config/laravels.php along with the bin/laravels, bin/fswatch and bin/inotify binaries, and it links to the releases page for per-version change notes.

## Sources

- [hhxsv5/laravel-s on GitHub](https://github.com/hhxsv5/laravel-s)
- [Issues](https://github.com/hhxsv5/laravel-s/issues)
- [License: MIT](https://github.com/hhxsv5/laravel-s/blob/PHP-8.x/LICENSE)
- [README](https://github.com/hhxsv5/laravel-s/blob/PHP-8.x/README.md)
- [Releases](https://github.com/hhxsv5/laravel-s/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hhxsv5-laravel-s
