The HAM Stack - A Simple Scalable Tech Stack for building modern web apps fast and cheap
Date: 2024-02-21 | featured | create | tech | hamstack | fsharp | hypermedia | moduliths |
I build a lot of projects. Over the years I've iterated on my technology choices to make it easier for me to build better projects for less cost.
In this post I'll share my latest iteration of the best tech stack for building modern web apps fast and cheap - The HAM Stack.
The HAM Stack
The HAM in HAM Stack stands for Hypermedia on A Modulith
:
- Hypermedia - Frontend is Hypermedia-based, currently I'm using HTML w HTMX + Alpine
- on A
- Modulith - Backend is a Modulith built with whatever you want, I currently use F# / Giraffe with a Postgres DB
This may seem overly simplistic and generic. Afterall, Hypermedia can be built with many different tools and a Modulith is simply an architectural pattern and thus can be built with basically any programming language.
However I think it's useful for realizing that good software (and systems) can generally be built with any technology - it's avoiding the common pitfalls that counts. This stack does that - it is specific enough to avoid common pitfalls while general enough so you can make your own choices for fulfilling it.
I was heavily inspired by HTMX's HOWL Stack (Hypermedia On Whatever you Like) - but felt it was a bit too generalized leading to common pitfalls so the HAM Stack fills in some guidance gaps.
In the rest of this post I'll dive into a bit more of the philosophy behind each layer.
Hypermedia
The web is here to stay. It's the best way we've created to connect all of humanity and the best "build once, run anywhere" implementation to reach production and stand the test of time.
Hypermedia is the language of the web (HTML is a Hypermedia). Everything on the web can be simplified down to rendering and updating HTML. Even your favorite SPAs (React, Vue, Svelte, etc) simply abstract this Hypermedia manipulation away from you.
I have a few theories ab the future of the web:
- We will be more connected, not less - better internet for more people
- We will have better tools to build once, run anywhere - the web already won, it will lean into Hypermedia
- Closed ecosystems that force you to use specialized, vendor-specific APIs (a la iOS and Android) will be subverted w better tooling, die due to competition (open model > closed model), and/or be more trouble than they're worth
Which leads me to believe that the web is here to stay and will only get more powerful, accessible, and easy to build on.
So Hypermedia is my choice for building frontends - it's a Simple Scalable System that gives you a ton of benefit for v small cost:
- Build once, run anywhere
- Extremely flexible with a huge ecosystem to leverage
- Accessible via the entire internet (i.e. any device, any platform, anywhere)
I am not too picky on how you build this Hypermedia.
- Use a SPA if you want
- Go low-js with things like HTMX and Alpine
- Build your thing w a wasm wrapper (a la Blazor etc)
Any of these will allow you to target the greatest interface humanity has ever created.
Personally I've grown to like HTMX and Alpine for building modern web apps. It's very simple with minimal overhead which allows me to build modern apps faster and cheaper - which is the whole goal. Plus it's backend agnostic which gives even more flexibility for your next choice.
Related: HTMX vs AlpineJS - Which should you use for your web app?
on A Modulith
A Modulith is a Modular Monolith. Moduliths scale - often way more than your overpriced, underpowered, overly complex alternatives like microservices or serverless functions (nanoservices is a more apt term). Thus Moduliths are a great way to build modern apps.
- Scalability - In terms of performance a Modulith can outperform essentially any distributed workload in terms of Outcome per UnitOfWork simply because it doesn't rely on intermediate network (read: IO) calls. This assumes a workload can fit on a single Modulith instance but compute is fast and cheap so if you're not FAANG then it probably can.
- Simplicity - People think distributed software makes things simpler. Yet it doesn't get simpler than a single codebase running on a single instance. The bottleneck in most systems is not performance - it's change velocity - so simplicity is likely what you want to optimize for.
- Still don't agree? What does your distributed software's CI, deployment patterns, orchestration, configs, network mesh, control plane look like? If I were to destroy all of it and leave you with just your codebase - could you get it running again?
- Flexibility - The simpler the system is the easier it is to change safely. Once we've built a system that can reliably run workloads on autopilot the next biggest advantage of software is to change it to leverage new insights about the world. Moduliths are often much more flexible than their distributed counterparts for the simple reason that they're simpler and more scalable.
Thus I'm a fan of Moduliths - they're Simple Scalable Systems for building software for most workloads.
In general I like building with a single Modulith where possible. Multiple Moduliths are okay when necessary (usually separating disparate, specialized, and intensive workloads) but this rarely happens until you've hit hyperscale and even then is often an antipattern.
My current tools of choice are:
- Backend: F# / Giraffe using Giraffe.ViewEngine for HTML generation
- Hosting: Serverless containers - benefits of single-server moduliths without the overhead of maintaining a server (Google Cloud Run or Digital Ocean App Platform)
But I'm not married to these - they're simply the best tools I've found for the job.
Next
Overall I've been very happy and productive with the HAM Stack. It's made building fullstack apps joyful again and really shames these overcomplicated, overengineered, and underperforming systems I see so often in enterprise.
While I'll likely continue iterating on the specific technologies I implement HAM Stack with in the future, I think the core value system is here to stay as long as the web functions reasonably similarly to how it does today.
My guess: a long time.
Hopefully we can get some enterprises to take note and build some Simple Scalable Systems - it's better for the business and way more fun for us engineers.
If you want to get started with the HAM Stack, checkout CloudSeed - An F# project boilerplate that will set you up with a fullstack HAM Stack implementation in 10 minutes.
If you liked this post, you might also like:
- Monoliths FTW: Software Monoliths for Scale
- Hypermedia > SPAs: How HTMX allows you to build modern web apps faster and cheaper than bloated client-side SPA Frameworks
- F# + HTMX: Simple Interactive Islands with F# and HTMX
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.