# amphp/http-server freezes the whole process when a handler calls sleep

> amphp/http-server is a PHP 8.1+ non-blocking HTTP/1.1 and HTTP/2 server built on Revolt and Amp, and its documentation spends more space on the one mistake that breaks concurrency than on any feature. The relevant limits are on the constructor you choose, not on the request handler.

**amphp/http-server** — An advanced async HTTP server library for PHP, perfect for real-time apps and APIs with high concurrency demands.

- Repository: https://github.com/amphp/http-server
- Website: https://amphp.org/http-server
- Stars: 1,325 · Forks: 103
- Language: PHP
- License: MIT
- Published: 2026-10-17 · Updated: 2026-10-17 · Language: en
- Canonical page: https://hysenlabs.com/projects/amphp-http-server

## One blocking call stops the whole process

The README states the rule plainly: do not use any blocking I/O functions in the HTTP server.

The mechanism is worth understanding rather than memorising. Nearly every built-in PHP function performs blocking I/O, meaning the executing thread, which is mostly equivalent to the process in the case of PHP, is halted until the response is received. The examples given are `mysqli_query`, `file_get_contents` and `usleep`, and the rule of thumb offered is that every built-in PHP function doing I/O does it in a blocking way unless you are sure otherwise.

The consequence is demonstrated with a deliberately bad handler:

```php
$handler = new ClosureRequestHandler(function () {
    sleep(5); // Equivalent to a blocking I/O function with a 5 second timeout

    return new Response;
});
```

Start a server with that handler and hit it twice, and you wait for the full five seconds before the second request is handled. That is the whole point. There is no preemption and no request isolation, because concurrency in this model comes from every handler returning control to the event loop rather than from parallelism between requests. One handler that never returns control halts the loop for everyone.

The mitigation is a library ecosystem rather than a setting. The README points at non-blocking implementations for the common cases, covering network sockets, file access, HTTP requests, WebSockets, MySQL, Postgres and Redis. Where blocking I/O or a long computation is genuinely necessary, the Parallel library runs that code in a separate process or thread, which is the escape hatch rather than an optimisation.

## The four things a server needs before it can start

The construction example is longer than a hello-world usually is, and the reason is that four collaborators are required rather than optional.

They are a `RequestHandler` to respond to incoming requests, an `ErrorHandler` to provide responses to invalid requests, an instance of `Psr\Log\LoggerInterface`, and at least one host and port to listen on.

```php
$server = SocketHttpServer::createForDirectAccess($logger);
$server->expose('127.0.0.1:1337');
$server->start($requestHandler, $errorHandler);

// Serve requests until SIGINT or SIGTERM is received by the process.
Amp\trapSignal([SIGINT, SIGTERM]);

$server->stop();
```

The handler contract is one method, and the response is constructed with named arguments for status, headers and body:

```php
public function handleRequest(Request $request) : Response
```

Two details in the surrounding example are worth carrying into any project. The logger is a PSR-3 implementation, and the example uses Monolog only as an illustration, which means you can substitute whatever you already run. And the server traps SIGINT and SIGTERM before calling `stop()`, so shutdown is graceful rather than a process kill that drops in-flight requests.

The library provides `SocketHttpServer` as the implementation suited to most applications, built on components from this package and from `amphp/socket`. The note after the example is a performance one rather than a correctness one: Nagle's algorithm can negatively affect benchmarks on some systems, and it is disabled by passing the result of `Amp\Socket\BindContext::withTcpNoDelay()` as the second argument to `expose()`.

## Which constructor you pick decides who is your client

`SocketHttpServer` has two static constructors for common cases, in addition to the normal constructor for advanced and custom uses, and the README describes what each implies.

`SocketHttpServer::createForDirectAccess()` creates an HTTP application server suitable for direct network access, which means clients connect to it directly. The defaults under this mode are specific numbers worth knowing: adjustable limits are imposed on connections per IP, total connections and concurrent requests, set to 10, 1000 and 1000 respectively. Response compression may be toggled on or off and is on by default, and request methods are limited to a known set of HTTP verbs by default.

Those numbers are the security-relevant part. A server meant to face the internet is given adjustable per-IP and global connection caps by default, which can help limit resource use.

The second constructor is described in the README under a different name for the case where the server sits behind something else, and the repository's `examples/` directory shows the shapes of real deployments: `behind-proxy.php`, `delayed-response.php`, `event-source.php`, `exception.php`, `hello-world.php` and `state.php`.

`behind-proxy.php` is the one to read before deploying. Behind a reverse proxy, the per-IP limit is meaningless if every request appears to come from the proxy's address, and the header handling determines whether the client address is even visible. That is a configuration decision with a correctness dimension, not just a tuning one.

`event-source.php` and `delayed-response.php` are the examples worth reading if you are building a realtime or streaming endpoint, since long-lived responses are exactly where the blocking-I/O rule bites hardest.

## Feature scope is deliberately spread across packages

The feature list in the README is mostly a list of other packages, and that is the architecture rather than an omission.

This package provides the server core. Static file serving is `amphp/http-server-static-content`. WebSockets are `amphp/websocket-server`. Dynamic application endpoint routing is `amphp/http-server-router`. Request body parsing is `amphp/http-server-form-parser`. Sessions are `amphp/http-server-session`. CORS is noted as coming from a third party, `labrador-kennel/http-cors` rather than from the AMPHP organisation.

What this package does provide itself is the protocol layer: full TLS support, customisable GZIP compression, HTTP/1.1 and HTTP/2, and middleware hooks.

The reason to understand this is that adopting the server does not give you routing, sessions or WebSockets. You add them individually, and each is a separate version to track. That is a fair trade for a small core, but it means the dependency list of a finished application is assembled by you rather than by a meta-package.

The concurrency model is the same split. The server is built on the Revolt event loop and the Amp non-blocking concurrency framework, so it inherits their primitives and you can use any non-blocking library built on Revolt. The README makes a point of the prerequisites here: it says you should make yourself familiar with the `Future` concept, with coroutines, and be aware of the several combinator functions to really succeed at using the HTTP server.

That note is the honest description of the learning curve. The API surface is small, a request handler is one method, and the difficulty is entirely in adopting futures and coroutines rather than in the server itself.

## Maintenance, project layout and the nghttp2 note

The repository is not archived and the last push was on 2026-10-10, one week before today. Releases move on the 3.x line with the default branch named `3.x`: 3.4.7 on 2026-10-10, 3.4.6 on 2026-06-27 and 3.4.5 on 2026-05-01.

The cadence is slower than the maintenance date suggests, with a gap of over three months between the last two releases. That is consistent with a mature library rather than an active one, and it is a reasonable expectation for something that sits under a production server.

Licensing is MIT with the LICENSE file at the repository root, which permits use in a closed-source commercial application with the notice retained.

The repository layout shows a normal, well-instrumented PHP project: `src/` and `test/`, `examples/`, `resources/`, `tools/`, a `phpunit.xml.dist` and a `psalm.xml` for static analysis, a `.php-cs-fixer.dist.php` for code style, an `infection.json.dist` for mutation testing, and a `composer-require-check.json`, which is a check that the declared requirements match what the code actually uses. There is also a `.phpstorm.meta.php` and `.gitmodules` at the root.

The one installation detail worth carrying forward is optional and easy to miss: the README says you might want to install the `nghttp2` library to take advantage of FFI to speed up HTTP/2 and reduce memory usage. Since HTTP/2 support is a headline feature, the FFI path is the difference between HTTP/2 being available and HTTP/2 being efficient, and nothing in the requirement list forces it.

## Conclusion

amphp/http-server fits a PHP team that has already committed to the Amp event loop and needs non-blocking I/O for a high-concurrency API or realtime endpoint, since the surrounding ecosystem of socket, file, MySQL, Postgres and Redis clients is the reason to choose it. Do not adopt it as a drop-in front end for an existing blocking codebase, because one `sleep` or one `mysqli_query` in a handler stops every concurrent request, not just its own. Verify first that every I/O path in your handlers can use an Amp client, and decide deliberately between `createForDirectAccess` and the constructor for reverse-proxy deployments before writing handlers.

## FAQ

### How do I install amphp/http-server?

As a Composer dependency with `composer require amphp/http-server`. PHP 8.1 or newer is required, and the README notes you may also want the `nghttp2` library installed to use FFI, which speeds up HTTP/2 and reduces memory usage.

### Why does amphp/http-server stop handling requests when I call sleep()?

Nearly every built-in PHP function performs blocking I/O, halting the process until the response arrives. Concurrency comes from handlers returning control to the event loop, so a handler that never returns control halts the loop for every other request. The README's example shows a handler calling `sleep(5)` delaying a second request by five seconds.

### What do I need to create a SocketHttpServer?

Four things: a RequestHandler, an ErrorHandler for invalid requests, a `Psr\Log\LoggerInterface` instance, and at least one host and port to listen on. You then call `expose()` with the address and `start()` with both handlers.

### What are the default limits in createForDirectAccess()?

It creates a server suitable for direct network access with adjustable limits on connections per IP, total connections and concurrent requests, set to 10, 1000 and 1000 by default. Response compression is on by default and request methods are limited to a known set of HTTP verbs by default.

### Does amphp/http-server include WebSockets, routing and sessions?

No. This package provides the server core with TLS, GZIP, HTTP/1.1, HTTP/2 and middleware hooks. WebSockets, static file serving, routing, body parsing and sessions are separate packages, and CORS comes from a third-party library.

### What license is amphp/http-server released under?

MIT, with the LICENSE file at the repository root. The project is on the 3.x line with 3.4.7 released on 2026-10-10, and the repository includes phpunit, psalm, php-cs-fixer and infection configuration files.

## Sources

- [amphp/http-server on GitHub](https://github.com/amphp/http-server)
- [License: MIT](https://github.com/amphp/http-server/blob/3.x/LICENSE)
- [Project website](https://amphp.org/http-server)
- [README](https://github.com/amphp/http-server/blob/3.x/README.md)
- [Releases](https://github.com/amphp/http-server/releases)

---

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