I have been doing IT for 42 years.
I started with C. Anyone who learned C in the old days knows the feeling: every pointer is a small bet. You always know that somewhere in your code a dangling pointer or an off-by-one is waiting, and you write defensively because of it.
Later I moved to Java and C#, where the runtime takes that worry off you. Then I met Kotlin, and it changed what I expected from a language. It was concise and readable, and it didn't force me to choose between safe and pleasant to write.
That is where SMS comes from.
What SMS is
SMS is a scripting language with a Kotlin-flavoured feel. It is part of Forge4D, an open platform I build for native apps. Two things set it apart from most scripting languages:
- It runs two ways. In development you run it as a script through the interpreter: save, run, see the result. For release you compile it ahead of time (AOT) via C++ into a native binary. Same source, same behaviour in both modes.
- It is meant to be fast once compiled. The goal was never "fast for a script". It was to stand next to C++ and Go.
A few numbers from our own benchmarks (all published, including the ones we lose):
- Against Qt's QML/V4 engine, compiled SMS was faster on all five UI-logic benchmarks I wrote. That ranges from about 1.1x on grouping to 91x on a recursive Fibonacci, which is plain C++ speed.
- Against Go, SMS wins some micro-benchmarks, but I won't claim it is "7x faster than Go". Part of that gap is Go's slice growth and garbage collector on a multi-core machine. And SMS maps are still slower than Go's, by roughly 3x to 4x. That is a known weak spot.
I'd rather you hear the losses from me.
The real test: port something big
Benchmarks prove little. A language is proven when something you care about runs on it.
So I picked ForgeCMS, the content system behind my own websites. It is written in Go. The numbers:
- about 36,400 lines of Go (without tests)
- 335 tests
- eight sites running on it
- modules for blog, events, contact forms, newsletter, courses, Stripe, a shop, a marketplace paid in the Ğ1 currency, licences, and an admin area
The decision was simple: ForgeCMS gets rewritten in SMS, and one binary compiled from SMS replaces the Go one. The HTTP server is written in SMS itself. The C++ side only provides native primitives such as sockets, crypto and file access. No separate C++ host.
How I did it, because this part matters more than the result:
- Site by site, behind a reverse proxy. The first site moved on 2026-11-04. If something went wrong, switching back was one line.
- A comparison harness against the Go version. For each site I fetched every page from both servers and compared the output. The early sites came out 60/60, 84/84 and 140/140 identical. By the end the module test suites had reached more than 2,000 checks, byte-identical to Go except for a known list: syntax colours in code blocks, mailto autolinks in legal texts, and thumbnail JPEG bytes.
- Real traffic, real mail, real money. A visitor inquiry on one site went through the SMS binary and the email arrived. A real 1 Ğ1 purchase went through the marketplace.
Today, 2026-11-08, crowdware.info moved over. That was the last big one, with the shop, marketplace, courses, admin editor and login.
Five sites now run in production on a binary compiled from SMS.
Honest numbers
I measured this on a single core, because my production server has one.
| Go | SMS (AOT) | |
|---|---|---|
| Binary size | ~22 MB | ~2 MB |
| Memory (RSS) | 26–30 MB | 17 MB |
| Startup | 57 ms | 142 ms |
| p99 latency (home page, 1 core) | 150 ms | 81 ms |
Throughput is more mixed. On static files and simple pages SMS matches Go on one core, and it is faster on large static downloads. On template-heavy pages Go is ahead. After a round of optimisation my slowest page measured about 294 requests per second against Go's 666.
Where did the time go? The profile was humbling: most of it was the CMS code itself, not the language. I was rebuilding a translation table on every call and parsing the same catalog on every render. Fixing that took one page from 155 to 587 requests per second. The one fix that did need the compiler was cheap: string literals were being boxed again on every use.
One more fact: Go uses all cores and SMS currently uses one. On a 4-core machine Go would be several times ahead. For a small site on a 1-core VPS, that doesn't matter. For a big one it does, and a multi-process plan is written down and waiting for a bigger server.
So my claim is not "SMS beats Go". It is this:
A language I designed, compiled through C++, runs a 36,000-line production web application at the same order of speed as Go, in a tenth of the binary size.
That is what "can keep up" means to me.
What I learned
- A port is the best compiler test there is. A real application breaks things that benchmarks never touch. Missing natives, reserved words, a scoping edge case.
- Parity matters more than raw speed. The interpreter and the AOT compiler must behave identically, or the whole "script while developing, compile for release" pitch falls apart.
- Measure before you blame the language. Most of my slowness was my own code.
What's next
- Multi-process serving once there's a machine with more cores
- Better string handling across the runtime boundary
- More of the Forge4D UI stack, which is the real reason SMS exists: direct binding between script and native UI, with fast dev cycles and an AOT build for release
SMS and Forge4D are open source on Codeberg. If you've spent decades with C and its pointers and want a language that feels like Kotlin but compiles to native code, take a look. I'd like to hear where it breaks.
— Olaf