Asynchronicity is not concurrency.
In the Zig Roadmap 2026 stream Andrew announced a new way of doing I/O, let’s see what are the goals of this upcoming design and how that relates to the revival of async / await in Zig.
The new I/O Interface
The most notable change to Zig is the introduction of a new interface in charge of all I/O operations. Most importantly, the Io interface is now expected to be provided by the caller, just like we already do with Allocator .
Old Zig:
const std = @import ( "std" ) ; fn saveData ( data : [ ] const u8 ) ! void { const file = try std . fs . cwd ( ) . createFile ( "save.txt" , . { } ) ; defer file . close ( ) ; try file . writeAll ( data ) ; const out = std . io . getStdOut ( ) ; try out . writeAll ( "save complete" ) ; }
New Zig:
const std = @import ( "std" ) ; const Io = std . Io ; fn saveData ( io : Io , data : [ ] const u8 ) ! void { const file = try Io . Dir . cwd ( ) . createFile ( io , "save.txt" , . { } ) ; defer file . close ( io ) ; try file . writeAll ( io , data ) ; const out : Io . File = . stdout ( ) ; try out . writeAll ( io , "save complete" ) ; }
The main implication of this change is that now the author of a program is able to decide the concrete I/O implementation and inject it also into code coming from dependencies.
The Io interface is also in charge of concurrency operations as those can intertwine with I/O, especially in the case of event loops. If a piece of code properly expresses concurrency of operations, then the Io implementation will have the opportunity of introducing parallelism.
... continue reading