All posts

June 3, 2026

Kestrel 0.16

Kestrel 0.16

Kestrel 0.16 is here.

Kestrel is a static-typed, compiled language built for a great developer experience, low memory usage, and the age of AI. New to Kestrel? Start with Introducing Kestrel for the full tour — this post covers what changed in 0.16.

New in 0.16

Opaque Types

// before func sorted[T, C](items: Array[T], compare: C) -> Array[T] where C: Comparator[T] // after func sorted[T](items: Array[T], compare: some Comparator[T]) -> Array[T]

Custom String Interpolation

// before let query = SQL("SELECT * FROM users WHERE email = $1", [email]); // after let query: SQL = "SELECT * FROM users WHERE email = \(email)";

some / null patterns

// before func authorize(request: Request) -> Response { match request.header("Authorization") { .Some(token) => match verifyToken(token) { .Some(user) => handleRequest(request, user), .None => Response(status: 401) }, .None => Response(status: 401) } } // after func authorize(request: Request) -> Response { match request.header("Authorization") { some token => match verifyToken(token) { some user => handleRequest(request, user), null => Response(status: 401) }, null => Response(status: 401) } }

Effectful Inits

// before — static factory method // let conn = Connection.open(path) static func open(path: String) -> Connection? // after — failable initializer // let conn = Connection(path: path) init(path: String)?

Chained Guards

// before guard let some user = database.find(id) else { return .NotFound; } if not user.isActive { return .Forbidden; } // after guard let some user = database.find(id), user.isActive else { return .NotFound; }

Keywords as Labels

// before — reserved words couldn't be used as labels func connect(usingPort port: Int64) func unwrap(withDefault value: T) -> T // after func connect(on port: Int64) func unwrap(or value: T) -> T

Partial Ranges

// before let first5 = array(0..<5); let allButFirst = array(1..<array.count); // after let first5 = array(..<5); let allButFirst = array(1..);

Bug Fixes

Computed Properties in Protocol Extensions

extend Collection { var isEmpty: Bool { get { self.count == 0 } } }

Default Type Params issue

open() variadic ABI mismatch on Mac

COW aliasing bug

MIR

Self as a static type

extend Point { static func origin() -> Self { Self(x: 0, y: 0) } }

Performance

0.16 brings large gains over the 0.16 beta:

Startup dropped from 23 ms to 9 ms, POST throughput jumped from 120 to 1,800 req/s, and memory after 1,200 requests fell from 23.3 MB to 3.0 MB. Baseline memory also improved slightly (3.0 MB → 2.7 MB).

A couple of honest caveats: deploy size grew a little (1.9 MB → 2.3 MB), and the GET benchmark now measures uncached HTML rendering rather than cached throughput, so it isn't directly comparable to the beta's number. The full picture — including how Kestrel stacks up against Node and Go — lives in Introducing Kestrel.

Install

Install or update through Jessup, the toolchain manager:

jessup install preview jessup default preview