Library / SDK
amphp/amp avatar
amphp/amp

amphp/amp: futures and cancellation for PHP 8.1 fibers

A non-blocking concurrency framework for PHP applications. 🐘

4,432 stars257 forksPHPMIT

At a glance

What is it?
amphp/amp supplies the primitives (Future, cancellation, async()) that AMPHP's libraries build on, while Revolt owns the event loop. Here is what it gives you, how to install it, and where it stops being the right tool.
Who is it for?
Adopt amphp/amp if you are on PHP 8.1 or later and you are already inside, or planning to use, the AMPHP stack: byte-stream, socket, http-client, http-server, mysql or postgres. It is the wrong choice if your blocking work lives in a library you cannot rewrite, since one blocking call stalls every other coroutine in the process; amphp/parallel exists for that case.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 66 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What amphp/amp actually provides, and who it is for

The package is deliberately narrow. The README states that amphp/amp "specifically provides futures and cancellations as fundamental primitives for asynchronous programming." It is not a database driver, not an HTTP client, not a server. It is the layer that those packages agree on.

The intended reader is a PHP developer who has a program made of independent sub-programs: several queries, an API call, a file read. The README's motivation section puts it plainly: instead of sitting idle while waiting for a database response, you could already send the next query or make an HTTP call. That is the whole pitch, and it is a real one for I/O-bound work.

The second audience is indirect. If you install amphp/socket, amphp/http-client or amphp/mysql, you are consuming amphp/amp whether or not you write a Future by hand. The README lists those packages as the layer above these primitives. So the decision to adopt amp is often made for you by the choice of a higher-level AMPHP package.

Fibers, Revolt and the shape of a Future

The mechanism changed in 3.x. Earlier versions used generator-based coroutines and, before that, callbacks. The README says those approaches suffered from the "What color is your function" problem, and that AMPHP solved it by shipping fibers with PHP 8.1. The README also notes that fibers can be interrupted anywhere in the call stack, which makes the old Amp\call() boilerplate unnecessary.

A fiber is a call stack the runtime can suspend and resume. The README describes them as cooperatively scheduled by the event loop, and is explicit about the consequence: only one coroutine runs at any given time, all others are suspended. Coroutines are not preemptive. They give up control voluntarily. The comparison the README draws is a single CPU core running multiple programs, except that no program gets a fixed timeslot.

A Future is the result placeholder. The README notes that the name was chosen over "promise" because a Future has no then method, which most promise implementations do have. Futures are designed to be awaited inside coroutines, though they also expose methods that act on the result and return another future. A future is completed, errored, or pending.

The event loop itself is no longer part of this package. The README states that AMPHP now uses Revolt instead of shipping an event loop with amphp/amp, and that low-level suspension and resumption are handled by Revolt's Suspension API. That split matters: the loop is a separate dependency with its own release cycle, and the README advises requiring revolt/event-loop explicitly even though it arrives automatically.

Installing amphp/amp and running a first concurrent script

Installation is Composer-only. The README gives the package name and then recommends adding the event loop explicitly, since you will almost certainly want to schedule timers or callbacks.

bash
composer require amphp/amp
composer require revolt/event-loop

After that, the README's second usage example shows the shape of a first real script: a callback passed to Amp\async() runs as its own coroutine, Amp\delay() suspends it, and the main flow continues. The file examples/async.php in the repository is the runnable version of this.

php
<?php

require __DIR__ . '/vendor/autoload.php';

Amp\async(function () {
    print '++ Executing callback passed to async()' . PHP_EOL;

    Amp\delay(3);

    print '++ Finished callback passed to async()' . PHP_EOL;
});

print '++ Suspending to event loop...' . PHP_EOL;
Amp\delay(5);

print '++ Script end' . PHP_EOL;

Run it with php async.php. The output starts with "++ Suspending to event loop...", then the async callback prints, then after roughly three seconds it reports that it finished, and the script ends about two seconds later. What you should notice is that the final print is not delayed by the callback: the main flow suspended at Amp\delay(5) and the loop ran the other coroutine in the meantime. The README's first example does the same thing at a lower level with EventLoop::getSuspension() and EventLoop::delay(), which is worth reading if you want to see how suspension is wired to the loop rather than to amp.

The blocking-call trap that no amount of async syntax fixes

This is the limitation that decides most adoptions. The README is blunt: "Any blocking I/O function blocks the entire process while waiting for I/O. You'll want to avoid them." Because coroutines are cooperatively scheduled and never preempted, a single blocking call inside a coroutine freezes every other coroutine in the process, including timers. The async syntax does not protect you. Nothing in the runtime can interrupt a fiber that is sitting in a blocking syscall.

The practical consequence is that amphp/amp is the wrong tool when the blocking work is outside your control. An older ORM, a client library that uses blocking sockets, a filesystem call on a slow mount: each of these can stall the loop. The README points at amphp/parallel for exactly this, describing it as providing parallel processing to utilize multiple CPU cores and offload blocking operations. If a large share of your work is blocking and unchangeable, running separate PHP processes is the honest answer, and amp's futures add ceremony without buying concurrency.

The second constraint is the file-descriptor limit. The README says extensions are only needed for a high number of concurrent socket connections, and that the limit is usually configured up to 1024 file descriptors. That is a ceiling on how many sockets one process can hold, and it is a system setting rather than a library one. If your design assumes tens of thousands of simultaneous connections, amp alone does not get you there.

The third is the PHP floor. PHP 8.1 or later, no extensions required. On 7.x this package is simply not an option, and the generator-based 2.x line is a different programming model: the README notes that previous versions used generators and required boilerplate that fibers removed.

amphp/amp against ReactPHP and Swoole

The closest comparison, and the one people search for, is ReactPHP. Both are event-driven PHP libraries with a shared lineage in non-blocking I/O. The difference in approach is visible in the code you write. ReactPHP's model is built around promises with then callbacks and an explicit loop object; control flow is expressed as chains. amphp/amp's README rejects that shape on the grounds that a Future has no then method, and pushes you toward awaiting inside a coroutine. With fibers, an amp program reads like blocking code: call, await, use the result. ReactPHP predates fibers and carries the callback style through its API.

Swoole is a different kind of answer. It is a PHP extension that provides its own coroutine runtime and network layer, so concurrency comes from the extension rather than from userland code. amphp/amp requires no extensions. That is a deployment advantage on shared or restricted hosting, and a performance question that this article does not settle either way.

The honest summary: if you want coroutine-style code without an extension, and you are on PHP 8.1+, amp is the natural fit. If your codebase is already deep in promise chains, migrating to amp means rewriting control flow, not swapping a dependency.

Maintenance, licence and the cost of tracking 3.x

The repository is not archived, and the last push was on 2026-07-26. The most recent release, v3.1.3, carries the same date; v3.1.2 came on 2026-06-21. There is also a 2.6.5 release dated 2025-09-03, so the 2.x line has seen maintenance within the past year. The default branch is 3.x.

Upgrade cost is concentrated in one place: the 2.x to 3.x move. The README says previous versions used generators for a similar purpose and required boilerplate such as Amp\call(), which fibers made unnecessary, and that the event loop was previously shipped inside amphp/amp. Both changes touch call sites. If you are pinned to 2.x because a dependency has not moved, you are on the older programming model, and the 2.6.5 release suggests that line is still being patched rather than abandoned.

The licence is MIT, which permits commercial and closed-source use. Because amphp/amp is a library you link into your application rather than a service, the practical obligation is preserving the copyright and permission notice in copies you distribute. This is a description of the licence text, not legal advice; check it against your own distribution model.

Editorial conclusion

Adopt amphp/amp if you are on PHP 8.1 or later and you are already inside, or planning to use, the AMPHP stack: byte-stream, socket, http-client, http-server, mysql or postgres. It is the wrong choice if your blocking work lives in a library you cannot rewrite, since one blocking call stalls every other coroutine in the process; amphp/parallel exists for that case. Before committing, verify three things in your own codebase: that PHP is at least 8.1, that no code path in your request handling calls a blocking I/O function, and that the file-descriptor limit is adequate if you plan to hold many concurrent socket connections. Start from examples/async.php and examples/cancellation.php in the 3.x branch rather than from the README snippets, because those two files show the API in a runnable form.

Frequently asked questions

What is asynchronous PHP and how does it work?

In amphp/amp, asynchronous code runs inside fibers that are cooperatively scheduled by the Revolt event loop. Only one coroutine runs at any given time and the others are suspended, so a coroutine must voluntarily give up control; the README notes that any blocking I/O function blocks the entire process.

What is AMP the company?

The README does not describe an AMP company. It covers amphp/amp, the AMPHP package that provides futures and cancellations for asynchronous PHP, plus the wider set of AMPHP libraries such as amphp/socket and amphp/http-client.

What does AMP stand for in technology?

Here it is not an acronym. AMPHP is the name of the collection of event-driven PHP libraries, and amphp/amp is the package inside it that provides futures and cancellations as primitives.

What is AMP software?

In this context it is amphp/amp, a Composer package for PHP 8.1 or later that supplies futures and cancellations, with Revolt handling the event loop. The README lists the packages built on it, including amphp/byte-stream, amphp/socket and amphp/mysql.

Official sources

  1. amphp/amp on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/amphp-amp.svg)](https://hysenlabs.com/projects/amphp-amp)