Skip to content

Building the Package Registry in Wyn ​

December 2025

The package registry at pkg.wynlang.com is written in Wyn. This was partly practical - we needed a registry - and partly a test of whether the language is ready for real server work.

The setup ​

The server is about 130 lines. Each incoming request gets its own spawned task. SQLite stores package metadata. Tarballs go on the filesystem.

wyn
fn handle_request(req: string, db: int) {
    // parse the request, route it, write the response (elided)
}

fn main() -> int {
    db = Db.open("/opt/pkg/registry.db")
    server = Http.listen(3001)
    while true {
        req = Http.accept(server)
        if req != "" {
            spawn handle_request(req, db)
        }
    }
    return 0
}

No framework, no middleware stack, no dependency injection. Just a loop that accepts connections and spawns handlers.

What worked well ​

The standard library covered everything we needed. HTTP server, SQLite, JSON parsing, file I/O, crypto for API keys. We didn't install a single package to build the registry.

spawn per request turned out to be the right default. No thread pool sizing, no async/await ceremony. The M:N scheduler handles the rest.

Single binary deployment is the best feature nobody talks about. The registry is a single small binary - a comparable 92-line web REST API measures 69KB. Deploy means scp and systemctl restart. No Docker, no container orchestration, no dependency resolution on the target machine.

What was rough ​

Error messages from the type checker were sometimes confusing when working with nested function calls. We've since improved these - the compiler now shows both the expected and actual types with a suggestion for how to fix it.

String interpolation didn't work in all contexts (match arms, struct field initializers). This is still a known limitation we're working on.

The numbers ​

  • Server binary: a single static binary (a comparable 92-line web REST API is 69KB)
  • Memory at idle: ~2MB
  • Lines of Wyn: 130 (server) + 80 (API handlers)
  • Deploy time: ~5 seconds
  • Uptime since launch: no crashes

The registry handles package search, publish, and install. It's not going to win any scalability awards, but for a language ecosystem with dozens of packages, it's more than enough.

MIT License - v1.22.0