50KB hello world - why your binary doesn't need a runtime
$ wyn build hello.wyn --release
$ ls -lh hello
-rwxr-xr-x 1 ao staff 50K Feb 25 01:00 hello
$ file hello
hello: Mach-O 64-bit executable arm6450 kilobytes (51,400 bytes). A native binary. No runtime, no VM, no interpreter. Just machine code and the parts of the Wyn standard library you actually used. The dev build - wyn build with no --release - is 51KB.
For comparison, measured on the same machine (Apple M3 Pro, macOS 26):
| Language | Hello world binary | Runtime required |
|---|---|---|
| C | 33 KB | No |
| Wyn | 50 KB (--release) | No |
| Rust | 421 KB | No |
| Go | 2.4 MB | No |
| Java | 0 KB (needs JVM) | ~200 MB JRE |
| Python | 0 KB (needs interpreter) | ~30 MB |
| Node.js | 0 KB (needs runtime) | ~80 MB |
Wyn compiles to C, then to native code. The 17KB between Wyn and a raw C hello world is the Wyn runtime - ARC, string handling, the scheduler entry points - linked in statically and dead-stripped down to what the program references.
Why this matters
Deployment is scp. Copy the binary to a server. Run it. There's no apt install python3 or nvm install 18 or "which version of the JRE do you have?" The binary runs.
Containers are optional. You can use Docker if you want (we ship a multi-stage Dockerfile). But you don't need it. A 50KB binary doesn't need a 200MB base image.
Cold start is cheap. Lambda functions, CLI tools, cron jobs - anything that starts and stops frequently benefits from a binary with nothing to initialize. Hello world's end-to-end wall time is 6.9ms, which is essentially the OS process-spawn floor (C measures 6.9ms on the same machine - the same number); Python's is 37ms.
How it works
Wyn compiles your source code to C, then invokes a C compiler (TCC for development, system cc for release builds) to produce a native binary.
hello.wyn → Wyn compiler → hello.c → cc → hello (native binary)The standard library is linked in statically, and --release builds compile with -ffunction-sections -fdata-sections so the linker can dead-strip everything the program never calls. That is why hello world lands at 50KB instead of pulling in the whole runtime.
There's no garbage collector. Memory is managed with ARC (automatic reference counting) with defer for cleanup patterns.
Deploy on Friday
From the Wyn flight rules:
Deploy on Friday. Your binary doesn't have dependencies.
When your deployment is "copy a 50KB file," there's nothing to go wrong. No dependency resolution, no version conflicts, no "works on my machine." The binary is the artifact.
$ wyn build server.wyn
$ scp server prod:/usr/local/bin/
$ ssh prod "systemctl restart myapp"Three commands. Friday afternoon. Sleep well.
A note on the numbers
This post originally quoted a 425KB dev build, from before --release dead-stripping landed in v1.10. The figures above are re-measured on the current toolchain (Wyn 1.21.0 release tarball, Apple M3 Pro): 51KB dev (52,696 bytes), 50KB with --release (51,592 bytes). For scale on the same machine: C 33KB, Rust 421KB, Go 2.4MB. Use --release for production deployments.
Related Posts
- I Built a Web Server Without Installing a Single Package - batteries-included in action
- Wyn Benchmarks - Honest Numbers on Apple M3 Pro - full performance data
- Wyn v1.10 Release - the release that brought 50KB binaries
Related Docs
- Memory Management - how ARC keeps binaries lean
- Deploying - deploy your binary to production
- Docker Deployment - 5MB container images with scratch base