[RFC] True Async RFC 1.7

php.internals

Edmond Dantes

250 days ago
Hello everyone! RFC https://wiki.php.net/rfc/true_async Here is the seventh version of the RFC, revised and expanded. ## Version 1.7 (December 2025) - **Fiber integration:** added `Fiber::getCoroutine()` method, ownership model, deadlock resolution - Added Coroutine methods: `getId()`, `getResult()`, `getException()`, `getTrace()` - Refined *Goals* section: improved clarity and technical accuracy of core value propositions - Function naming aligned with PHP coding standards: `currentCoroutine()` → `current_coroutine()`, `gracefulShutdown()` → `shutdown()`, `getCoroutines()` → `get_coroutines()` - Method renaming: `Coroutine::onFinally()` → `Coroutine::finally()` (brevity) - Interface renaming: `FutureLike` → `Completable` - Exception renaming: `CancellationError` → `Cancellation` (clearer semantics) - Moved `Cancellation` to the **root namespace** (`\Cancellation`) as a fundamental PHP mechanism - Changed `Cancellation` inheritance from `\Error` to `\Throwable`, following Python’s `CancelledError` pattern - Added backward compatibility notes for the new root namespace class - Renamed `DeadlockException` to `DeadlockCancellation` ## My Comments Since the vote took place, I have tried to bring together specialists in asynchronous programming to discuss the RFC, and I was surprised by the lack of serious disagreements. You can read the discussion on GitHub, where key opinions from representatives of different libraries and components are expressed. These discussions became the basis for refining the RFC. Compatibility research involving WordPress, Laravel, and AMPHP helped clarify future prospects and potential challenges. As part of the research, Xdebug was also adapted, without which debugging WordPress code in coroutines would have been inconvenient. A special version of Async-Worker for FrankenPHP was also developed. Memory models were not included in the RFC because none of them provide significant benefits, do not make the code noticeably better, and all of them have drawbacks. Instead, future versions are expected to introduce a separate API and philosophy for multithreaded coroutines. I returned to the original idea of defining the Cancellation exception directly in the PHP core. This was always the right decision, and it should not have been abandoned. The most important change in this RFC is support for fibers as an extended form of coroutines. It turned out to be a great idea. I finally came up with a good term to replace FutureLike, which had been really annoying me. ## Experiments To understand which code breaks, a special version of TrueAsync was created that made GLOBALS unique per coroutine. This made it possible to run WordPress as a stateful application with only a few changes. Two versions of the code were implemented. One where WordPress was fully initialized in each coroutine for every request, and another where WordPress cloned only a subset of its data structures. Similar experiments were also conducted on Laravel. No more than 1–2 hours were spent on code changes for WordPress and Laravel. In other words, there were almost no changes. Automatic analysis of the Laravel codebase showed that the number of components combining I/O operations with shared in-memory state is extremely small compared to the amount of code that can work without changes. Some WordPress functions with static variables continued to work as before because they did not contain any I/O operations. Overall, it became clear that the vast majority of the code remains functional in a concurrent environment and works without changes. This means that transparent async can actually save developers time and money. ## Key Conclusions - **One-thread coroutines** are a powerful pattern for web-oriented programming languages, providing a balanced trade-off between system complexity, code safety, and developer ergonomics. - **Coroutines running in other threads** do not contradict the one-thread model. They require further development and can integrate organically, complementing each other’s functionality. - **Actors** are likely to become the next key pattern for multithreaded programming. Their implementation is clear, feasible, efficient, and surprisingly safe. - **Memory isolation and transfer mechanisms** between PHP threads will not conflict with the current RFC. Instead, they will complement it and coexist alongside it. I think having two tools for async, concurrent coroutines and inter-thread interaction, can complement each other very well, and most importantly, they can be built gradually, step by step. This is, of course, a brief summary of the events of the past month, so if I missed anything, please feel free to ask. Merry Christmas to everyone!

Edmond Dantes

235 days ago
Hi everyone. I have completed the research on PHP core changes for multithreaded programming. The article briefly presents the main benefits of PHP multithreading: thread pools and actors. https://github.com/true-async/multithreaded-php/blob/main/mm-en.md This research makes it possible to look into a potential timeline of PHP’s evolution and imagine how the current RFC could interact with multithreading abstractions. The article examines how threads and actors can interact with coroutines. As for my personal opinion. I believe that actors are the safest and most sustainable pattern for the PHP language. They are much better than manual thread management and better than interacting with a thread pool. PHP should evolve toward higher-level abstractions that are not tied to OS-specific details. I am convinced that the presence of low-level APIs in PHP that mirror C functions is a historical design mistake that should be phased out. Actors allow writing sequential code without thinking about multithreading or thread pools. This is a solid tool with proven effectiveness and well-known trade-offs, focused on business logic. That is why actors are a perfect fit for PHP. A single-threaded coroutine model fits actors very well, creating the necessary illusion of sequential execution. The current amount of research, experimentation, and knowledge should be sufficient to make a well-balanced decision. Best regards, Ed

Edmond Dantes

232 days ago
Hello all. I think the New Year holidays are already over for most people. Therefore, it would be reasonable to set an approximate voting date if nothing changes. Today is January 12. I suggest aiming for February 1. Best regards, Ed

Talysson Lima

223 days ago
Em seg., 12 de jan. de 2026 às 06:54, Edmond Dantes <edmond.ht@gmail.com> escreveu:
> Hello all. > > I think the New Year holidays are already over for most people. > Therefore, it would be reasonable to set an approximate voting date if > nothing changes. Today is January 12. I suggest aiming for February 1. > > Best regards, Ed >
It's astonishing how such an important issue, one that could change the direction of PHP and is highly requested by the community – native asynchronous support in PHP – doesn't receive the necessary attention. It's almost disrespectful to the tremendous effort Ed put into it. Everyone knows that passing the RFC isn't necessary; it's a democratic process. But apparently, there's a closed group of people who mutually favor each other and exclude others. Perhaps if this had been proposed by someone like Nikita, it would have received more attention. I see many people with this same opinion going in this direction. Maybe we should improve our mindset? I see many features arriving and being discussed that don't have 1% of the impact that true async would bring to PHP. You just need to take the time to look at community groups. Isn't the community taken into consideration?

Deleu

223 days ago
On Wed, Jan 21, 2026 at 12:08 PM Talysson Lima <talyssonlima5@gmail.com> wrote:
> > > Em seg., 12 de jan. de 2026 às 06:54, Edmond Dantes <edmond.ht@gmail.com> > escreveu: > >> Hello all. >> >> I think the New Year holidays are already over for most people. >> Therefore, it would be reasonable to set an approximate voting date if >> nothing changes. Today is January 12. I suggest aiming for February 1. >> >> Best regards, Ed >> > > It's astonishing how such an important issue, one that could change the > direction of PHP and is highly requested by the community – native > asynchronous support in PHP – doesn't receive the necessary attention. > > It's almost disrespectful to the tremendous effort Ed put into it. > Everyone knows that passing the RFC isn't necessary; it's a democratic > process. But apparently, there's a closed group of people who mutually > favor each other and exclude others. Perhaps if this had been proposed by > someone like Nikita, it would have received more attention. > > I see many people with this same opinion going in this direction. Maybe we > should improve our mindset? > > I see many features arriving and being discussed that don't have 1% of the > impact that true async would bring to PHP. You just need to take the time > to look at community groups. Isn't the community taken into consideration? >
I think you might be attributing "lack of attention" to something that is far more likely to be caused by "complexity of the changes". Remember that pretty much everyone here (with a very small exception of some internal engineers) are doing voluntary work. Between our professional lives, personal lives, family matters and hobbies, we chime in for a few minutes a day to participate, discuss and improve the language we all enjoy using (although this is an assumption on my part, it's hard to justify contributing on your free time to something you don't actually like). The Async RFC, in any of its versions, has already taken more time from me than all the last 5 years of reading and/or participating in PHP RFCs combined. And even though I have invested a lot more time into it, I can barely say I understand 5% of it. I don't have a vote, so my input here is merely that of an observer, but if at least half the voters are in a similar situation as I am, its very easy to conclude that its not lack of attention or lack of understanding the community wishes. It has been voiced on Internals multiple times by multiple people that this RFC has the potential to be the biggest PHP impact in a very long time. I see no evidence whatsoever of anybody diminishing the value of the subject. We also have a collective knowledge that the PHP community has interest in async execution as stated by the existence of Swoole, ReactPHP, AMPHP, Symfony Runtime, Laravel Octane, Fibers and this RFC. Now, after reading this if you agree with me that 1) we know its big and valuable and 2) we know the community wants it, how do we move forward? I don't have 40 hours/week to dedicate into reading the RFC, understanding everything, running local tests, validating the design choices, and understanding potential BC Breaks. I have tried multiple times to take 30 minutes blocks here and there to go through the information available and try to understand how it would impact my existing projects, how I would use this in production and what could be done to make the experience for PHP developers better and frankly it hasn't gotten me anywhere. The RFC is too big, the concepts is too foreign and the impact is too unknown. If you look at the history of Nikita's proposals or even more recently the history of any RFC proposed and easily accepted, you will find an RFC text that you can skim through in roughly 20 minutes and you will understand: what is it about, whether it affects your usage of PHP or not (not every RFC affects every PHP developer), how localized/contained the change is and why it will be a positive change to the language. Meanwhile, for the Async RFC, I'm willing to bet $100 that if you pick 3 random participants of PHP Internals and magically give them 1 hour of time to digest, they will all come out with different understanding of the proposal and still not understanding enough to be able to cast a vote whether this can be integrated into PHP as-is or not. TL;DR: it's not about whether we think something is more or less important to the PHP community. It's about what we can read, understand, judge, suggest changes and decide if it belongs in PHP or not in our 30-minute per week time slot that we give PHP out of pure personal enjoyment of the language.
-- Marco Deleu

Rowan Tommins [IMSoP]

223 days ago
On 21 January 2026 14:59:52 GMT, Talysson Lima <talyssonlima5@gmail.com> wrote:
>It's astonishing how such an important issue, one that could change the >direction of PHP and is highly requested by the community – native >asynchronous support in PHP – doesn't receive the necessary attention. > >It's almost disrespectful to the tremendous effort Ed put into it. Everyone >knows that passing the RFC isn't necessary; it's a democratic process. But >apparently, there's a closed group of people who mutually favor each other >and exclude others. Perhaps if this had been proposed by someone like >Nikita, it would have received more attention.
It's astonishing, and disrespectful, how many people who have never participated in the mailing list feel entitled to jump in and make accusations about those who do. There is no secret cabal blocking discussion of this RFC, and no personality cult discrediting the effort put into it. Previous rounds of discussion produced huge numbers of replies - leading to the same conspiracy theories about why we weren't all just agreeing and getting on with it! The truth is, this is an extremely complex project, and the PHP project lacks any process suitable for tackling it. What is the right level of comment for a document with an estimated reading time of over an hour? Do we start with the principles of moving the language in this direction? Debate the philosophy of different async models? Jump straight into the details of every function name? The idea of a "working group" was discussed, but no process was established, no "charter", no milestones. Edmond has been doing an amazing amount of work, and I will repeat that I have huge respect for that effort. But if you drop an encyclopedia on someone's desk and say "discuss", is it really surprising that people don't know what to say? If there's a problem with the culture of the project, it's that there is too little central control; nobody has the authority or responsibility to make big organisational decisions. We have no "benevolent dictator", no corporate sponsor, no appointed Steering Committee. I don't know what to do to get this project moving forward, but accusing people of deliberately blocking it does not help anyone. Rowan Tommins [IMSoP]

Edmond Dantes

223 days ago
> The idea of a "working group" was discussed, but no process was established, no "charter", no milestones. Edmond has been doing an amazing amount of work, > and I will repeat that I have huge respect for that effort. But if you drop an encyclopedia on someone's desk and say "discuss", is it really surprising that people don't know what to say?
As for the working group, it was created. AMPHP and Swoole officially responded to the proposal. Most of the discussions took place publicly. We can read them here: https://github.com/true-async/php-true-async-rfc/discussions I thought there would be more discussions, but the thing is that we don’t have any serious disagreements about the architecture. There are some doubts that the RFC won’t be accepted in its entirety, but that’s not a disagreement, rather secondary issues. This situation is largely expected, because this RFC doesn’t propose something new, but rather suggests bringing into the PHP core what has long been working in the form of "extensions". That’s why I’m not particularly surprised. The main obstacle, and the main doubts, are not about what needs to be done, but about whether it can be agreed upon. It would be good to discuss the global implications for PHP if this RFC is accepted. The global implications, or in other words a broader roadmap of changes that become possible and logical if the RFC is accepted. I tried to look at such implications in my article about multithreading. In an ideal world, I would like to be confident that everyone who will vote on this RFC clearly understands the foundation of what PHP is becoming: * a language oriented toward single-threaded concurrent execution, * with actors for multi-processor interaction. That’s how I see the end goal. A high-level language, with a high degree of abstraction over OS mechanisms. Without low-level elements. Without access to fine-grained tuning. As safe as possible and as simple as possible. A language with a built-in web server, socket server, and other types of servers. With asynchronous extensions enabled by default. The database connection pool should be available out of the box and look like the usual, familiar PDO classes, without significant changes. Single-threaded coroutines are a proven compromise between high complexity and ease of development. Actors are a proven, maximally safe approach to writing parallel code. None of these approaches is universal. On the contrary, they are all oriented toward the web. By voting for this RFC, you are voting specifically for a combination of these two approaches, which has long existed in Node.js (except for actors). It would be good if this were absolutely clear to all participants in the discussion.

Rowan Tommins [IMSoP]

223 days ago
On 21 January 2026 17:13:34 GMT, Edmond Dantes <edmond.ht@gmail.com> wrote:
>> The idea of a "working group" was discussed, but no process was established, no "charter", no milestones. Edmond has been doing an amazing amount of work, >> and I will repeat that I have huge respect for that effort. But if you drop an encyclopedia on someone's desk and say "discuss", is it really surprising that people don't know what to say? > >As for the working group, it was created.
Unless I missed something, there was never a discussion of what a Working Group should look like, what its aims were, how it would report back to the mailing list, etc. If the WG didn't have the backing of this list, it doesn't solve the problem of how this list can understand and approve the proposal.
>In an ideal world, I would like to be confident that everyone who will >vote on this RFC clearly understands the foundation of what PHP is >becoming: >* a language oriented toward single-threaded concurrent execution, >* with actors for multi-processor interaction. > >That’s how I see the end goal.
Defining that end goal, in my mind, would be the first job of a Working Group. Then presenting it, and making sure the wider community agrees with that goal. Right now, a "No" vote on the RFC could mean anything from "I disagree with the vision completely" to "I don't like the name of the 5th function on page 18". And so everyone ends up frustrated, because we never worked out where to start, or where we're trying to get to. Rowan Tommins [IMSoP]

Edmond Dantes

223 days ago
> Unless I missed something, there was never a discussion of what a Working Group should look like, what its aims were, how it would report back to the mailing list, etc.
Yes, we don’t have a working group like that. And I’m afraid I don’t know how it could come into existence. I don’t have the authority to create "such" a group, and I’m not aware of who does. Today, we have what is possible within the existing framework: a free association of free people. Best regards, Ed

Jakub Zelenka

222 days ago
On Wed, Jan 21, 2026 at 8:15 PM Edmond Dantes <edmond.ht@gmail.com> wrote:
> > Unless I missed something, there was never a discussion of what a > Working Group should look like, what its aims were, how it would report > back to the mailing list, etc. > > Yes, we don’t have a working group like that. And I’m afraid I don’t > know how it could come into existence. > I don’t have the authority to create "such" a group, and I’m not aware > of who does. >
Technically it could be done through the policy RFC like anything governance related. The issue is that this would be a significant change to our decision making and it might be potentially difficult to find an agreement. Also it requires extra time from people involved which might not be easy as well.. Kind regards, Jakub

Rowan Tommins [IMSoP]

222 days ago
On 21 January 2026 19:12:10 GMT, Edmond Dantes <edmond.ht@gmail.com> wrote:
>> Unless I missed something, there was never a discussion of what a Working Group should look like, what its aims were, how it would report back to the mailing list, etc. > >Yes, we don’t have a working group like that. And I’m afraid I don’t >know how it could come into existence. >I don’t have the authority to create "such" a group, and I’m not aware >of who does.
Indeed, nobody does, and that is a problem. It's not an insurmountable problem though: we just have to bootstrap our way towards one. A lot of management processes recognise that sometimes you have to step back and not just talk about how to build things, but talk about how to talk about building things. Ridiculous as it seems, sometimes you do need a meeting called "Project Planning Planning". So in this case, we need to start from what we *do* have: this list, and the RFC process. We can have a discussion on the list, leading to a policy RFC, about what "Working Groups" could be used for, how one would be set up, what powers and responsibilities they would have relative to existing processes, etc. Once we've agreed that policy, there *will* be someone with the authority to create a WG for True Async. (Or maybe during the discussion we decide "Working Group" is the wrong name and concept, but we agree *some* new process for Project Planning, or Roadmapping, or whatever. And then *that* process is available for True Async.) That may seem a bit tedious and bureaucratic, but I can't see any other way of tackling a change of this magnitude and importance. 25 years ago, a couple of Israeli students could come and say "we've got some bold ideas of turning this web page toolkit into a proper programming language", and just get on with it; but now, every decision we make affects millions of users, and becomes immensely difficult to undo. Rowan Tommins [IMSoP]

Edmond Dantes

222 days ago
Hello.
> Indeed, nobody does, and that is a problem. It's not an insurmountable problem though: we just have to bootstrap our way towards one.
Even if a project is governed democratically, a decision-making hierarchy must exist. I have nothing against development processes. I don’t consider them bureaucracy. I consider it bureaucracy when there is an attempt to imitate development processes. Bureaucracy is the creation of an illusion of work, which should be avoided. A good decision-making flow, on the other hand, is a completely different matter. Theoretically, I could of course create an RFC to change the PHP development processes, including the voting principles. It’s "possible", but it would most likely be extremely inefficient. I currently have two options. 1. I can run a vote with several questions to find out what people actually want. 2. Help with implementing changes to the decision-making processes, if there is such a desire. ---- Best regards, Ed

Peter Kokot

222 days ago
Da.
-- Peter Kokot On Thu, Jan 22, 2026, 10:07 Edmond Dantes <edmond.ht@gmail.com> wrote:

Edmond Dantes

223 days ago
Regarding the group, I want to once again express an important point. The main problem, the primary blocking issue, is that nobody believes this RFC has any real chance. It’s like in the banking system: if you convince people that stocks will fall, then even if it’s not true, the stocks will fall. At the same time, I agree with this assessment. We are facing a paradox. To make changes to the language, you need to believe that these changes can be accepted. Previously, there were doubts about whether such changes could even be implemented. That problem has been solved. What remains is the lack of trust in acceptance. How can this be resolved? I think there are ways, and they are known. They are just all outside the scope of the current RFC. ---- Ed

Deleu

223 days ago
On Wed, Jan 21, 2026 at 4:29 PM Edmond Dantes <edmond.ht@gmail.com> wrote:
> Regarding the group, I want to once again express an important point. > The main problem, the primary blocking issue, is that nobody believes > this RFC has any real chance. > > It’s like in the banking system: if you convince people that stocks > will fall, then even if it’s not true, the stocks will fall. > > At the same time, I agree with this assessment. > We are facing a paradox. > > To make changes to the language, you need to believe that these > changes can be accepted. Previously, there were doubts about whether > such changes could even be implemented. That problem has been solved. > What remains is the lack of trust in acceptance. > How can this be resolved? I think there are ways, and they are known. > They are just all outside the scope of the current RFC. > > ---- > Ed >
I doubt the problem is about trust. You can trust that a company will not go bankrupt, you still need to understand how to operate and buy stocks. I think most readers are more likely to agree that you've put a tremendous amount of work forward and it's not that hard to trust you've done a great job so far. But if we don't know how things work, we can't help you make even better decisions nor can we make use of what you've built. I also don't think it's fair to expect from PHP's RFC process a position of: "trust me, this is the best, lets just merge it". Even if you were the best and smartest software engineer in the world, PHP is used by an immeasurable amount of people from all backgrounds, in many contexts and many approaches. Its not humanly possible for a single individual to know every possible way PHP is used and the RFC process is here for people from many backgrounds to provide their own perspective of things and voice how they think such a change will affect them or their project - be it a positive or a negative impact. Right now, I think the "fairest" assumption is that we don't have many such voices because nobody can read, understand, interpret and predict how this RFC would play out in their projects and their work. It's far too big of a change with too many concepts, mainly foreign to many people working with PHP and there isn't a clear path of contributing to the discussion. How do we solve that?
-- Marco Deleu

Edmond Dantes

222 days ago
If that were the case. But it isn’t. For example, the Swoole project has existed for more than 7 years. This means that anyone here can check how coroutines actually affect their code. There is already extensive experience with Laravel and other applications. All of this has existed for a long time. If people cannot read the RFC and understand that these are JavaScript-style coroutines, then why do they have votes? 🙂 That’s a strange idea. Yes, there are issues with understanding. However, a year has passed since the publication. In one year, it should have been possible to clarify any questions, if there were any. In other words, if PHP had never had such coroutines, that could be understood. But the situation is exactly the opposite. As for trust, the problem is that people don’t want to waste their time. They don’t want to play for a team with no chance of success. What can be done? A lot of things can be done. Last time there were several proposals. But all of these proposals go beyond the scope of the RFC. They require organizational changes. I can once again propose having two votes and an experimental mode. The first vote would be on the core principles of the language’s development for the next 5–10 years. A vote on this RFC. Or another option. There is more than one. For example, you could vote in a first approximation, and then a year later in a second round. So... ср, 21 янв. 2026 г., 22:15 Deleu <deleugyn@gmail.com>:

Deleu

222 days ago
On Wed, Jan 21, 2026 at 5:42 PM Edmond Dantes <edmond.ht@gmail.com> wrote:
> If that were the case. But it isn’t. >
Let's agree to disagree.
> For example, the Swoole project has existed for more than 7 years. This > means that anyone here can check how coroutines actually affect their code. >
And in those 7 years, it hasn't been adopted by 100% of PHP projects. In fact, I'd take a wild guess that its adoption is very likely below 20% of PHP projects out there. Just because it exists doesn't mean every PHP Software Engineer would benefit from it or that it's undeniably useful for any project or business. I first heard of Swoole in 2020. Ever since, I've had the desire to try it out, but never had a business case for it. If your RFC requires people to dive deep into knowing Swoole and understanding how it works and how it affects everyone's code, I would consider that to be one of the top reasons why the RFC hasn't gotten more traction.
> There is already extensive experience with Laravel and other applications. > All of this has existed for a long time. >
Just because it has existed doesn't mean it is universally used.
> If people cannot read the RFC and understand that these are > JavaScript-style coroutines, then why do they have votes? 🙂 That’s a > strange idea. >
I see this statement as you going out of your way to offend the very people that have the power to vote on your RFC. They have a vote because they have contributed to the ecosystem of PHP enough to have a vote. An ecosystem that has existed without Async PHP for 3 decades. An ecosystem that requires thorough development, documentation, release, testing, bug fixing, security fixing. They have volunteered their time in proposing changes, getting those changes ironed out, implemented, adopted. They have improved the language. Just because they don't have your level of knowledge in asynchronous programming does not make their contribution any less meaningful or any less important. I can understand and sympathise that it must be very frustrating for you to put so much thought and care into this proposal and have no clear path as to how to make it land on PHP Core. But that is not an excuse to offend contributors of the project, especially given how narrow the subject matter is. There's definitely an appetite to have Async PHP and you're not going to get anybody on your side by implying that they are the problem in understanding your RFC. This is not a "one or another person" problem. There are plenty of extremely smart people participating in the development of PHP for years. How can the RFC be easy to digest so that they can participate more?
> Yes, there are issues with understanding. However, a year has passed since > the publication. In one year, it should have been possible to clarify any > questions, if there were any. >
The RFC is complex enough that giving it chunks of 30 minutes spread across many weeks is not enough to put forward every question that it warrants. 1 year or 10 years is not going to solve that. In other words, if PHP had never had such coroutines, that could be
> understood. But the situation is exactly the opposite. > > As for trust, the problem is that people don’t want to waste their time. > They don’t want to play for a team with no chance of success. >
I see no evidence of that. There is no one team vs another here. The change either lands or it doesn't. Being such a promising change to the PHP Ecosystem, it would be in any volunteer's interest to have been able to participate and shape the biggest change in the PHP Language in decades. But its not about "wasting time because its a loss cause". Its about not having volunteering time to grasp such a hard RFC. What can be done? A lot of things can be done. Last time there were several
> proposals. But all of these proposals go beyond the scope of the RFC. They > require organizational changes. > > I can once again propose having two votes and an experimental mode. > The first vote would be on the core principles of the language’s > development for the next 5–10 years. > A vote on this RFC. > Or another option. There is more than one. For example, you could vote in > a first approximation, and then a year later in a second round. > > So... > > ср, 21 янв. 2026 г., 22:15 Deleu <deleugyn@gmail.com>: > >> >> >> On Wed, Jan 21, 2026 at 4:29 PM Edmond Dantes <edmond.ht@gmail.com> >> wrote: >> >>> Regarding the group, I want to once again express an important point. >>> The main problem, the primary blocking issue, is that nobody believes >>> this RFC has any real chance. >>> >>> It’s like in the banking system: if you convince people that stocks >>> will fall, then even if it’s not true, the stocks will fall. >>> >>> At the same time, I agree with this assessment. >>> We are facing a paradox. >>> >>> To make changes to the language, you need to believe that these >>> changes can be accepted. Previously, there were doubts about whether >>> such changes could even be implemented. That problem has been solved. >>> What remains is the lack of trust in acceptance. >>> How can this be resolved? I think there are ways, and they are known. >>> They are just all outside the scope of the current RFC. >>> >>> ---- >>> Ed >>> >> >> I doubt the problem is about trust. You can trust that a company will not >> go bankrupt, you still need to understand how to operate and buy stocks. I >> think most readers are more likely to agree that you've put a tremendous >> amount of work forward and it's not that hard to trust you've done a great >> job so far. But if we don't know how things work, we can't help you make >> even better decisions nor can we make use of what you've built. >> >> I also don't think it's fair to expect from PHP's RFC process a position >> of: "trust me, this is the best, lets just merge it". Even if you were the >> best and smartest software engineer in the world, PHP is used by an >> immeasurable amount of people from all backgrounds, in many contexts and >> many approaches. Its not humanly possible for a single individual to know >> every possible way PHP is used and the RFC process is here for people from >> many backgrounds to provide their own perspective of things and voice how >> they think such a change will affect them or their project - be it a >> positive or a negative impact. >> >> Right now, I think the "fairest" assumption is that we don't have many >> such voices because nobody can read, understand, interpret and predict how >> this RFC would play out in their projects and their work. It's far too big >> of a change with too many concepts, mainly foreign to many people working >> with PHP and there isn't a clear path of contributing to the discussion. >> >> How do we solve that? >> >> -- >> Marco Deleu >> >
-- Marco Deleu

Jakub Zelenka

222 days ago
> I can once again propose having two votes and an experimental mode. >
I don't like this experimental model or introducing API stability levels as it is confusing for users. It requires extra checking for users to do for each API (no one usually does it and with AI it will be even more problematic because it might not tell that the generated code uses experimental API). This would just become pain for user and I don't think it would be good for PHP.
> The first vote would be on the core principles of the language’s > development for the next 5–10 years. >
That can be already done but it will never guarantee that the second vote will succeed. People even might change their mind between votes so I'm not sure it's really useful. It might be easier to just ask people after the vote why they voted no. I think most of them will tell you if you politely ask them privately. Kind regards, Jakub

Edmond Dantes

223 days ago
How the TrueAsync RFC evolved over time: The first version proposed a fairly low-level API for controlling the Scheduler, philosophically very close to AMPHP. It quickly became clear that this approach had many drawbacks, including issues with consistent PHP behavior. The code was completely rewritten. Core changes became more significant. In the second version, the PHP execution flow was changed so that any code could be asynchronous. The second RFC version introduced structured concurrency, close to modern equivalents. At the same time, the garbage collector code was rewritten several times. One version went through code review, after which a simplified variant appeared. Today, Async GC exists in a lightweight form. The implementation code was modified and optimized according to approaches used in Swoole. The next RFC version received fixes and improvements to the description. The RFC was split into several parts and significantly reduced in size. Around this point, the first vote and major discussions took place. Their result was the creation of a working group. Another important outcome was the integration of Fibers as coroutine generators, which removed the problems of previous RFCs. Various experiments were conducted, extended memory models were tested, and Globals isolation was explored. WordPress and Laravel were run as stateful applications under FrankenPHP + TrueAsync. A small MVP was written for a multithreaded PHP memory manager capable of correctly working with PHP objects across different threads. The possibilities of sharing and transferring memory between PHP threads were investigated. Compared to document 1.6, document 1.7 contains one new section: Fiber. Everything else remains without significant changes. Best regards, Ed

Edmond Dantes

217 days ago
Hello. At the moment, this RFC has no chance of being accepted. And it’s not about the text itself. Therefore, a different approach is needed. So: 1. The vote scheduled for **February 1 is canceled**. 2. Daniil Gentili is officially joining TrueAsync and will help with the RFC discussion. 3. Aaron Piotrowski has also received an invitation. 4. In addition to the features described in the RFC, other experimental capabilities will also be developed. This also means that from now on, this RFC will be the result of the work of several people. If anyone else would like to join, please let me know. I also officially invite maintainers of frameworks and web servers to take part in testing, in order to adapt them for async operation. It would be great if someone built WebSocket integration. The PHP community has been waiting for this for a long time for about 15 years already. As for what happens next, I think Daniil Gentili will explain it himself.

Tim Düsterhus

223 days ago
Hi Am 2025-12-25 08:57, schrieb Edmond Dantes:
> - Function naming aligned with PHP coding standards: > `currentCoroutine()` → `current_coroutine()`, > `gracefulShutdown()` → `shutdown()`, > `getCoroutines()` → `get_coroutines()` > - Method renaming: `Coroutine::onFinally()` → `Coroutine::finally()` > (brevity) > - Interface renaming: `FutureLike` → `Completable` > - Exception renaming: `CancellationError` → `Cancellation` (clearer > semantics)
Having a new discussion thread for each version of the RFC (and the amount of changes) make it hard for me to keep up with the RFC. I've just taken a quick look at the stubs though and am noticing that the “base exception” is incorrectly named, as I had previously mentioned in my email in the voting thread: https://news-web.php.net/php.internals/129308 It should be `class AsyncException extends \Exception {}` and `class AsyncCancellation extends \Cancellation { }` as per: https://github.com/php/policies/blob/main/coding-standards-and-naming.rst#throwables Best regards Tim Düsterhus

Edmond Dantes

223 days ago
Hello
> I've just taken a quick look at the stubs though and am noticing that > the “base exception” is incorrectly named, as I had previously mentioned > in my email in the voting thread:
> The base exception should be \Async\AsyncException.
Yeah, so the Async prefix should be present. OK, got it. Thank you.

Jakub Zelenka

223 days ago
Hi, On Thu, Dec 25, 2025 at 9:00 AM Edmond Dantes <edmond.ht@gmail.com> wrote:
> Hello everyone! > > RFC https://wiki.php.net/rfc/true_async > > Here is the seventh version of the RFC, revised and expanded. > > ## Version 1.7 (December 2025) > > - **Fiber integration:** added `Fiber::getCoroutine()` method, > ownership model, deadlock resolution > - Added Coroutine methods: `getId()`, `getResult()`, `getException()`, > `getTrace()` > - Refined *Goals* section: improved clarity and technical accuracy of > core value propositions > - Function naming aligned with PHP coding standards: > `currentCoroutine()` → `current_coroutine()`, > `gracefulShutdown()` → `shutdown()`, > `getCoroutines()` → `get_coroutines()` > - Method renaming: `Coroutine::onFinally()` → `Coroutine::finally()` > (brevity) > - Interface renaming: `FutureLike` → `Completable` > - Exception renaming: `CancellationError` → `Cancellation` (clearer > semantics) > - Moved `Cancellation` to the **root namespace** (`\Cancellation`) as > a fundamental PHP mechanism > - Changed `Cancellation` inheritance from `\Error` to `\Throwable`, > following Python’s `CancelledError` pattern > - Added backward compatibility notes for the new root namespace class > - Renamed `DeadlockException` to `DeadlockCancellation` > >
I think it would be more reasonable to target 9.0. We were discussing it and it might potentially happen after 8.6 or in the worst case in the following release (after 8.7) if we have a big TODO list of things (another thing that we want there is conversion of streams from resources to objects). We could potentially manage it as some sort of release branch (that would need to be agreed) but I think it would be more reasonable for feature like this as it would give us time to properly stabilise it. Kind regards, Jakub

Edmond Dantes

223 days ago
Hello.
> I think it would be more reasonable to target 9.0.
I would prefer flexible targets. 8.6 if it works out. And if not, everything else. In this respect, the RFC is very flexible: it specifies what the functions should be, but does not require them to support asynchronicity right away. Best regards, Ed

Jakub Zelenka

222 days ago
Hi, I mentioned some things privately but will repeat them here as I think it's important. On Wed, Jan 21, 2026 at 8:19 PM Edmond Dantes <edmond.ht@gmail.com> wrote:
> Hello. > > > I think it would be more reasonable to target 9.0. > > I would prefer flexible targets. 8.6 if it works out. > And if not, everything else. > In this respect, the RFC is very flexible: it specifies what the > functions should be, but does not require them to support > asynchronicity right away. >
I think PHP 9 is flexible target because we won't likely release it until it's ready. PHP 8.6 is not flexible and likely this won't make it there anyway. I think it just too big and the BC break (global changes during suspension) is not acceptable for minor release either. On the other side PHP 9 can accommodate for big changes. In fact I think it would be good for marketing to have a big feature for a big release. Kind regards, Jakub

Larry Garfield

218 days ago
On Thu, Dec 25, 2025, at 1:57 AM, Edmond Dantes wrote:
> Hello everyone! > > RFC https://wiki.php.net/rfc/true_async > > Here is the seventh version of the RFC, revised and expanded.
Notes, collected as i go: - Most RFCs have an example in the introduction of what the proposed syntax looks like in a small but meaningful example. Please include such, as it helps "set the stage" and provide context for the rest of the RFC. - Please break up the API Overview code block into several pieces by type to make scrolling easier. - As I've said before, I'd rather have keywords than functions for the main API. - Please please do NOT have finally() be a function on its own. current_coroutine()->finally() is sufficient. Having it on its own is going to be too confusing with the finally keyword for exceptions. Can we find a better name for it that isn't confusing with exceptions? onCompletion()? What is the difference then between $coroutine->finally() and register_shutdown_function(), when the current coroutine happens to be main? - getSpawnFileAndLine() and getSpawnLocation() - It's non-obvious when they're first mentioned what the difference is. I don't know if they're described better further down, but they should have a docblock here to avoid confusion. - getAwaitingInfo(): array - Hell no, no struct arrays. Make it a class. - Remember, we now have PFA, so `spawn('sleep', 2)` can now be spelled `spawn(sleep(2, ...))`, to make it available for IDE analysis. :-) (I'm not sure what the implications of that are/should be for all the other "callable and arg array" cases.) But at very least, please use `func_name(...)`, not a string, in all examples. Function name strings should basically never be used again. (Another argument in favor of keywords.) - "The non-blocking version of the file_get_contents function is not part of this RFC." - Wait, I'm confused. I though the entire point of this RFC was that we don't need a user-exposed alternate version of file_get_contents(). It just blocks or doesn't as needed. Now you're saying that's not the case? We need to use the silly spawn() syntax or it will block our coroutine? That's a no-go for any existing library that happens to have a file_get_contents() in it, which would then block if it gets called inside a coroutine it doesn't expect. If that's not the case, then this comment is highly misleading. Either way, it's scary. - "This means that multiple calls to select <Awaitable> may produce different results. " - I don't believe a select keyword or function has been discussed to this point, so this line is confusing. - Completable interface section needs an example. I don't grok what it means in practice. I also don't understand what Awaitable is for other than being a parent of Completable. At least not yet by this point in the RFC. - The examples seem very inconsistent. Some are using foo(...), some are using strings, and the "await with cancellation" example is using a long-closure syntax for reasons I do not fathom. The inconsistency is making it difficult to get a sense for what typical usage will be like. - "As soon as the $cancellation is triggered, execution is interrupted with an exception " - What does triggered mean? When it starts? Ends? Something else? What's a use case here other than sleep? This is all very unclear. - In Fibers, in the basic example, "start() blocks until the fiber completes" - I assume that means it blocks the calling coroutine? Or does it block the whole system until it completes? - I have no idea what it means for coroutines to be "symmetric". This is stated as a thing, but I have no clue what that means. That makes much of the Fibers section incomprehensible. - I will have to defer to the existing async gurus (especially Aaron P of AmPHP, who wrote the Fibers RFC) to determine if the FIber integration is logical and reasonable. For me, it feels very complicated but that may be necessary. I am not sure. - "Active coroutines (running or suspended) are protected from collection while they have pending operations" - If I'm reading that correctly, it means `span(very_long_function(...))` will start a coroutine, but not assign it to a variable. So I cannot track it or refer to it, but it will still run in the background until it completes, at which point it will get GCed. Is that correct? - The FrankenPHP example linked to... doesn't seem to do anything to start a coroutine. I don't know what it's supposed to be demonstrating other than FrankenPHP itself. - OK, now all the way at the bottom we get to an explanation of getSpawnFileAndLine() vs getSpawnLocation(). I am not convinced we need both, and the naming is highly confusing. More discussion to have here. - Non-Async code can use Cancellation, but... what does that even mean or do? Why would someone use it? This is sneaking in a 3rd error type without much guidance. catch(Throwable) is surprisingly common (rightly or wrongly), so this feels like a major pothole potential. - Oh crap, Scopes are now a SEPARATE RFC, of similar length? See previous "this thing is huge" comment... I do not have the bandwidth right now to review that, but I feel like I have to in order to speak to this one intelligently. I also haven't gotten to read any of the linked references, as I have run out of time. More general comments: This seems mostly logical as a low-level API. As I have stated before, though, I don't want a low-level API. I want a *safe* API. I am not convinced those are compatible. And I certainly do not want to see the low-level API in one release and then have to wait for the next release for the safer API. Having pipes and PFA in separate releases is bad enough. :-) That this allows for zombie coroutines or "lost" background coroutines to exist is, to me, a major problem. I realize changing that means bringing scopes back in, which makes it bigger, but... I don't want to hand footguns to a million PHP developers with no async experience. I don't trust us with that kind of power to not do something grossly stupid. As I've said before, I don't like await, spawn, etc. being free-standing functions rather than keywords. That is very limiting on the syntax they can use. It also means, as the examples show, we get this pattern very often: await(spawn($fn)); That's very clumsy. It introduces two layers of wrapped functions, which means a lot of extra parentheses. I... have no idea what would happen if one used pipes here, but that's also an open question. I think it would be: $result = $fn |> spawn(...) |> await(...); I am not sure if I like that or not. But regardless, the "start coroutine and block until it's done" operation is common enough that it needs a cleaner way of writing it than two nested function calls. We can debate what exactly that is, but we need it. I would much rather have $cor->onComplete() than finally(). And absolutely no global function by that name, which is way too easy to confuse with the existing keyword. All the use of inline function callbacks also, once again, demonstrates why our current long-closure syntax is a problem. We need to fix that, for simple ergonomics if nothing else. It makes this sort of code a pain in the ass. --Larry Garfield

Edmond Dantes

218 days ago
> Most RFCs have an example in the introduction of what the proposed syntax looks like in a small but meaningful example. Please include such, as it helps "set the stage" and provide context for the rest of the RFC.
usage examples are provided immediately after the API Overview, as agreed.
> As I've said before, I'd rather have keywords than functions for the main API.
As discussed earlier, introducing new keywords is better addressed in a separate RFC.
> getAwaitingInfo(): array - Hell no, no struct arrays. Make it a class.
The getAwaitingInfo function is intended to retrieve debugging information that can be used for telemetry or debugging purposes. Different reasons for suspending a coroutine may have different metadata, which is difficult to standardize. Therefore, an associative array with keys is used as the ideal data structure for storing information without a contract, and one that is easy to serialize.
> Function name strings should basically never be used again. (Another argument in favor of keywords.)
The question goes beyond the scope of this RFC. However, what would be useful to discuss is the possibility of narrowing the interface down to Closure. For some reason, a year has already passed, and that discussion still has not happened.
> "The non-blocking version of the file_get_contents function is not part of this RFC." - Wait, I'm confused.
This is a consequence of the lack of agreement on what should be included in an RFC and what should not. I will remove this block.
> The examples seem very inconsistent. Some are using foo(...),
The term “inconsistency” cannot be applied in this case, since all examples are consistent with subsets that belong to the same set. In PHP, all these expressions are callable.
> - In Fibers, in the basic example, "start() blocks until the fiber completes" - I assume that means it blocks the calling coroutine? Or does it block the whole system until it completes?
Non-blocking behavior is the default. Therefore, of course, it is the coroutine that is blocked.
> - I have no idea what it means for coroutines to be "symmetric". This is stated as a thing, but I have no clue what that means. That makes much of the Fibers section incomprehensible.
There is a terminology error here. It should be “asymmetric.”:
>> Asymmetric coroutine mechanisms (more commonly denoted as semi-symmetric or semi coroutines) provide two control-transfer operations: one for invoking a coroutine and one for suspending it, the latter returning control to the coroutine invoker. >> While symmetric coroutines operate at the same hierarchical level, an asymmetric coroutine can be regarded as subordinate to its caller, the relationship between them being somewhat similar to that between a called and a calling routine.
In other words, according to the official PHP documentation, the following conditions must be met:
>> Suspends execution of the current fiber. The value provided to this method will be returned from the call to Fiber::start(), Fiber::resume(), or Fiber::throw() that switched execution into the current fiber.
> - I will have to defer to the existing async gurus
This is not complex enough to require asking a guru. Fibers transfer control according to the following scheme: ``` Fiber::start() -> Fiber::suspend() -> Fiber::resume() FiberA FiberB FiberA ``` A -> B -> A This logic remains valid for coroutines as well: ``` Fiber::start() -> Fiber::suspend() -> Fiber::resume() CoroA CoroB CoroA ``` A -> B -> A I hope someone actually read the Fibers RFC, right?
> If I'm reading that correctly, it means `span(very_long_function(...))` will start a coroutine, but not assign it to a variable. > So I cannot track it or refer to it, but it will still run in the background until it completes, at which point it will get GCed. Is that correct?
Yes. The spawn function will return a Coroutine object, which can be used like any other object. The reference count of such an object will be 2. If the result of spawn is not used, the coroutine will live for as long as it is executing.
> The FrankenPHP example linked to... doesn't seem to do anything to start a coroutine. I don't know what it's supposed to be demonstrating other than FrankenPHP itself.
Here, FrankenPHP handles HTTP requests in separate coroutines. That is, it demonstrates how coroutines can help improve performance for a web server. The coroutine is created inside the FrankenPHP extension, and the user provides the request-handling function. Thus, each request is handled in a separate coroutine.
> What is the difference then between $coroutine->finally() and register_shutdown_function(), when the current coroutine happens to be main?
There is no difference. Most likely, the finally handler will be invoked before register_shutdown_function, although I am not 100% sure.
> Non-Async code can use Cancellation, but... what does that even mean or do? Why would someone use it? > This is sneaking in a 3rd error type without much guidance. catch(Throwable) is surprisingly common (rightly or wrongly), so this feels like a major pothole potential.
In this RFC, there is no non-async code. Where does this text come from?
> Oh crap, Scopes are now a SEPARATE RFC, of similar length?
I thought that when you voted the previous version of the RFC, you had at least read the first page. I see. In fact, the Scope API was separated a long time ago. This was done in order to reduce cognitive load.
> This seems mostly logical as a low-level API
The term *low-level* is used incorrectly here. *Low-level* is applicable when an API exposes internal implementation details or operates at a lower level of abstraction. For example, drawing a pixel versus drawing a point. Drawing a pixel is low-level. In this case, coroutines themselves (unlike Fibers in the past) are a high-level abstraction that hides all implementation details from the user. If you analyze the API surface of Scope versus this RFC, you will see that the APIs are at the same level of abstraction. Therefore, neither the Scope API nor the Async Base API is low-level.
> I want a *safe* API. I am not convinced those are compatible. And I certainly do not want to see the low-level API in one release and then have to wait for the next release for the safer API.
In programming, the term “safe” is used in different meanings and is usually not applied in the context in which you are using it. I do not recommend using the term **safe** in this case, as the U.S. security services might read this message and ban the use of PHP on the grounds that PHP has no *safe* variables. In this case, the code remains safe even without the Scope API.
> Having pipes and PFA in separate releases is bad enough. :-)
It was originally assumed that the Scope API, as well as the Context API, would be approved immediately after this RFC. However, given the pace of the discussion, or rather the complete lack of it, this seems unlikely.
> That this allows for zombie coroutines or "lost" background coroutines to exist is, to me, a major problem.
You wrote that something is a problem, but you forgot to explain why it is a problem. The Scope API does not prohibit the use of zombie coroutines.
> As I've said before, I don't like await, spawn, etc. being free-standing functions rather than keywords. That is very limiting on the syntax they can use. It also means, as the examples show, we get this pattern very often:
Nevertheless, this is the only reasonable solution for the gradual approval of the API. Moreover, even if keywords are added later, the functions will not need to be removed.
> $result = $fn |> spawn(...) |> await(...);
(wipes away bloody tears) Oh God, why am I reading this :) A pipe is sequential execution of something. That means if something asynchronous is called inside a pipe, the pipe must wait for it out of the box, without any additional functions. In other words, a “dereferencing” operation of the future must be applied: ```php $result = $data |> strtolower(?) |> spawn(someFunction(...), ?) |> strtoupper(?); ``` I haven’t studied the new syntax yet, but I think the idea is clear. In other words, the pipe must wait for the completion of the asynchronous operation. If PHP can adopt a new, cleaner syntax for closures, then it will be possible to introduce a new spawn keyword for coroutines and create a single, elegant syntax. But in essence, this changes nothing. ---- Ed.