MEAN: the monolith crusader.

This is part 1 of a 3 part series on the MEAN stack. Part 2. Part 3.

The MEAN stack is a popular set of components used to build modern web applications. It’s quite a bit different from how we’ve architected systems in the past and offers the chance to build maintainable, scalable, fast systems. But first, let’s talk about the old way to build a web application.

The Monolith

The Monolith is that project you’re probably working on right now. It’s that Rails server that some long-gone consultants or ambitious 10x developers threw together to get the prototype out but now you’re maintaining it. It’s still on Rails 2.3 and even though Rails 4 is out, you have no idea how you’re going to be comfortable enough updating it to Rails 3.x.

It sucks to work in, it’s on a framework and language version so old it’s not even supported anymore. It’s hurting recruitment because no engineer wants to learn an old system.

The system contains a lot of expensive front-end and back-end code. The cost of a rewrite seems outrageous before you would even begin such a project.

Eventually what happens is these projects do fall under a rewrite. Maybe not today, maybe not tomorrow, but someday it happens. A new monolith is built by another ambitious developer and the cycle begins again.

The rewrite happens in parallel with the existing system. Now the old code is understaffed with the less ambitious developers in the company — not that this is a bad thing, ambition isn’t necessarily a good quality for an engineer to have. The rewrite project drags on for twice the length of time it was supposed to, and when it finally does come out, it’s so full of bugs it had to be rolled back for another few months of bug fixes. The thing about software projects is they accrue tons of domain knowledge (why is that conditional there?) that is difficult to see when embarking on a rewrite.

This is not the developer’s fault, but the common web frameworks and conventions of today (Django, Rails) really encourage this kind of architecture. Put everything under one, opinionated roof and your product will be out the door quickly. The trouble comes later.

What you really need is the ability to segment out a system into smaller chunks so once something becomes outdated enough either due to performance, security, or product reasons, it can easily be swapped out. No throwing out the baby with the bathwater.

This isn’t microservices

Don’t get too excited about breaking up a system into tiny chunks. To be clear, I am proposing you split the system into 2 parts, the back-end and the front-end, no more. This process is not really one you do for technical reasons (though there are some), it’s one you do for human reasons. Having too many engineers in a codebase bottlenecks the entire project. A good number of engineers in a single codebase is probably 7±2.

Why not have a service for every part of the app? Because each service is another thing to manage, it’s another thing to log centrally, it’s another thing to give security patches to, another thing to monitor. There is a huge cost to adding a new service. Don’t get crazy with SOA. That’s worse than the monolith.

Still, architecting your application in this way puts you in a good place if SOA is a direction you want to head.

The MEAN Stack

JavaScript is all about composability. Using various components for a database, web server, front-end framework, you can build up a system that matches the product you’re developing. As a back-end JavaScript engineer, your task is to put the right components in the right place to build a working system.

This is in contrast to web frameworks that were popular last decade such as Django and Rails. These frameworks came batteries-included with heavy opinions on how your application should look. For example, they all came with an ORM that pretty much required you to use a SQL database.

Neither approach is good nor bad. They each have their merits and downsides.

The main advantage of an opinionated web framework is that the developer doesn’t have to think so hard when building the app or learning how to use it. There is a “right way” to do things and moving away from them is discouraged simply on principle. The downside is lack of flexibility. If you don’t like the CSS preprocessor that it comes with, it’ll be an uphill battle to switch it out for a different one.

The main advantage of a composable system that doesn’t have a heavy framework is that you get unlimited flexibility into how your application will work. The downside is you’ll want to be aware of all the options at hand, and you have to write your own boilerplate to plug it all in.

This is where the MEAN stack comes in. By sticking to some smart defaults of MongoDB, Express.js, Angular.js, and Node.js, you can start building your app right away as well as take advantage of plenty of documentation and existing boilerplate to achieve the same level of productivity you would have with an opinionated web framework. In other words, you can take the opinions but not be forced to use them.

JSON

The most important part of the MEAN stack unfortunately didn’t fit into the cute acronym. It’s JSON. JSON is how the web speaks. It has by far taken over XML at this point as the most popular web framework. It’s easy for humans to read, easy to parse in any language, simple enough to be reliable, but flexible enough to handle almost any web task. Unsurprisingly, JavaScript and JSON go together really well. You won’t have to do as much type coercion as you might in other language since JSON is already JavaScript.

The MEAN stack is made up of tools that pair well with JSON for this reason.

Node.js

Node.js is a JavaScript runtime used to run JavaScript code outside of a web browser, turning it into a more general purpose language. Most commonly Node is used to build web servers.

Node is built on top of Google’s V8 engine. This engine empowered web applications written in JavaScript to reach performance levels that can surpass even C code in some cases. In my opinion, it’s the most important piece of software ever developed.

It’s bizarre to me that a scripting language like JavaScript that doesn’t even have integers could ever reach these kind of performance numbers, but however it works, it certainly does. Scripting languages are great for web development. They offer a rapid development process unmatched with compiled code. The downside is usually performance, but not really with V8.

In addition to just being “fast”, more importantly JavaScript is concurrent. I wont get into the specifics, but concurrency is much more important for web servers than simple speed. Concurrency affects how many users can use a system at the same time which is almost always what we try to optimize for. Speed is good too, but it’s secondary to concurrency. Read up on the Node event loop for more on how this works.

The event loop also allows JavaScript/Node to easily support WebSockets, which is not something that could be said about other languages. WebSockets allow you to push data to the browser (for example, notifications or two-way chat). It isn’t something that every application needs, but it allows you to build more immersive applications when it fits the domain.

With every language/tool comes a culture, and the culture behind Node is one that really encourages back-to-basics coding. You’ll find yourself opening TCP sockets directly, making sure you only attempt to open a file once before using it, and working with an admittedly naive (but awesome) package manager. It’s a bit more work on your end, but the payoff is really knowing how your application works and not simply piling magic on top of magic (and we all know how that ends).

It’s been around since 2009 and plenty of very large systems are running on it. It’s a favorite of startups for its rapid development and huge open source ecosystem. It’s a favorite of enterprise for its performance and the simplicity pays off in terms of maintenance. Netflix, Groupon, SAP, LinkedIn, Microsoft, Yahoo, Walmart, PayPal, and Salesforce all use Node.js in production.

Express.js

Express.js is the first and most popular web framework for Node. If you come from another languages “web framework” might be calling it a bit too much. It’s very simple and very basic. A simple server looks like the following:

That’s really about all it is. Everything else (database connections, authorization) is handled by you. Again, it’s more work to write this boilerplate yourself, but it gives you much more flexibility and knowledge about exactly what your app is doing. A bit more up-front work, but huge payoffs later when it inevitably stops working the way you expect. It’s also simply more fun.

MongoDB

MongoDB is a popular database choice for Node applications and the most popular “NoSQL” database today. NoSQL is kind of a silly term, it should be Non-Relational, but that somehow doesn’t have the same punch.

More importantly than no SQL is no tables. If all you know is SQL you might have a tough time understanding how MongoDB is different (and you’ll likely incorrectly use it the same way). If you’re a new developer and you don’t know SQL, you’re in luck. I know from teaching that people without DB experience often have an easier time understanding MongoDB than people with a SQL background.

MongoDB has collections, which are kind of like tables, but they’re different because they’re basically JSON documents and as such, support much more complex structure than a row would. For example, if you wanted to have multiple emails for a user, you would simply have a document like the following:

{
"user": "Jeff Dickey",
"emails": ["jeff@gmail.com", "jeffrey@gmail.com"]
}

MongoDB isn’t exactly JSON, it stores this in a format called BSON which is essentially binary JSON (fast JSON) but with a few more features. You can generally just think of it as storing JSON though. Also because it’s JSON it doesn’t have a schema. This means you can write your app more quickly without having to generate table migrations and gives you the flexibility to have heterogenous structure in your data.

It doesn’t have the same level of queryability as SQL and it’s missing some functionality like JOIN. However it is designed from the beginning to be horizontally scalable so when you need more DB power, you just add a new box to the cluster.

Because it doesn’t use SQL, it also doesn’t need a heavy ORM to work with it. Since Node is JavaScript and JSON is JavaScript, and the query language is also JavaScript, you can seamlessly query the language from inside your app code. This just means there are less moving parts and under the hood the interaction between the server and the DB is much simpler.

All this adds up to a fast, scalable database that’s a great pair to JavaScript/JSON code.

AngularJS

AngularJS is a front-end JavaScript framework used to build thick web clients. These clients act more like a mobile app would by making asynchronous JSON requests for content and updates. This is opposed to the old way of building applications where the server emits the HTML angle brackets and the JavaScript just pretties it up. In this case, the browser is generating (almost) all the HTML and interacting with a JSON API.

This means that the front-end code is separate from the back-end code. They’re still linked to some extent, the back-end server will serve up an initial page to bootstrap Angular, but after that the browser creates the page itself. This keeps the back-end really just a simple JSON API and prevents conflating it with the front-end code.

In other words, this prevents the Monolith.

All together now

Combined, these components allow you to build a flexible system. Using a stateless back-end you can scale up as many app nodes as you want (though you won’t need many with Node’s performance anyways). With MongoDB you’ll have a fast, scalable database.

Most importantly, your front-end is separate enough from the rest of your code. Nobody needs to be an expert in both. Rather than drive yourself to drinking over the thought of a rewrite, you’ll be able to rewrite just small components as technology improves and your product develops but continuing to stick to JSON as the lowest common denominator of your system.