Skip to main content
Preslav Rachev

For all the progress we’ve made in web development, designing emails still feels like coding for Internet Explorer 6. Tables everywhere. Inline styles. No flexbox, no grid, and every email client with its own quirks. Without knowing it, you step into a time machine, only you’re not sure if you’ll ever make it back (and if you do, Outlook will be waiting).

That’s why frameworks like MJML exist. They let people write clean, modern markup and compile it down to the gnarly HTML that actually works in Outlook and Gmail. But the thing is, MJML’s official implementation is Node.js-based. If you’re building backend services in Go, that means shelling out to Node, running a separate process, or calling a web API. It works, but it’s clunky. It’s not Go. Plus, it’s darn slow. Try running the MJML compiler at scale, and you’ll quickly explode your server costs.

MJML - The Responsive Email Framework

MJML - The Responsive Email Framework

The only framework that makes responsive email easy. MJML is a markup language designed to reduce the pain of coding a responsive email.

https://mjml.io

For what it’s worth, my team and I use MJML for pretty much all of our projects, and we genuinely love it. But frankly, it’s always a bit of a pain having to manually convert MJML into HTML, keep both versions in your repository, and deal with the inevitable “did I forget to recompile this one?” moments.

Smoothing that friction out is exactly why I set out to build gomjml.

preslavrachev/gomjml

Repository information unavailable

-
-
-

gomjml is a native Go implementation of the MJML framework. It lets you take MJML markup and compile it directly to responsive HTML, all within your Go application. No Node, no external dependencies, just Go.

Why bother? Because I wanted something fast, embeddable, and easy to deploy. I wanted to remove the friction of email generation from my Go projects. And honestly, I was tired of the “just use Node” workaround. Sometimes, you want your tools to speak the same language.

And the numbers back this up:

Tool50x Total (ms)Avg (ms)Max RAM (MB)Avg CPU (%)
gomjml162320
mrml96110
mjml (JS)135302709020.9

In our benchmarks, gomjml compiles a real-world MJML template in about 3ms, using just 2 MB of RAM. The official JavaScript MJML compiler? Try 270ms and 90 MB of RAM, plus a hefty chunk of CPU. If you’re generating lots of emails, those differences add up—fast. And thinking long-term, this isn’t saving money is only one side of the coin—using less compute and memory also means a smaller carbon footprint for our software. That’s a win for everyone.

A quick disclaimer: I didn’t build gomjml alone. I leaned heavily on Claude Code (AI) to help me wrangle the sheer size and complexity of this project. Honestly, writing a full MJML compiler from scratch would have been a massive undertaking. Using AI sped things up, but it wasn’t magic—there were plenty of bumps, rewrites, and head-scratching moments along the way. It’s been a fascinating learning experience, and I’m still figuring out how to best use AI as a tool in my workflow. No shame in that.

gomjml is still new and in active development, but it already covers all the core MJML components and is fast enough for real-world use. If you’re curious about the technical details or want to try it out, check out the README and the repo.

One important note: while MJML is the original framework, my reference for gomjml has actually been MRML—the excellent Rust implementation of MJML. MRML is fast, native, and closely tracks the MJML spec, making it a much better fit for building a Go-native compiler than the official Node.js version. So if you notice gomjml behaving a bit more like MRML than MJML, that’s by design.

Email is still a mess. But at least, with gomjml, it’s a mess I can more easily handle with Go code.

Thank you for reaching this point! If you enjoyed this post or found it helpful, consider supporting my creative journey! Every coffee helps me keep writing and sharing new ideas.

Have something to say? Send me an email or ping me on social media 👇

Want to explore instead? Fly with the time capsule 🛸

You may also find these interesting