A notional modern SaaS app architecture
July 05, 2021
Architecting a Software-as-a-Service (SaaS) app is hard and there are more choices than ever. In this post, I am going to discuss a notional modern architecture.
Of course, there’s no one-size-fits-all architecture. This particular setup works for a lot of use cases, but it certainly won’t work for others. Additionally, it works well if you know these technologies, but if you’re trying to get a minimum viable product (MVP) to market quickly and would be much more comfortable writing a monolith, then by all means do that. The last thing I’d recommend is getting bogged down in learning new tech when you’re perfectly capable of getting an MVP off the ground with tech you already know.
Some baseline requirements
Before we get into the weeds of the architecture, let’s talk some baseline requirements.
Our SaaS will need the following things:
- A public-facing website with marketing materials.
- Blog posts to attract search traffic.
- A private web app that offers the core SaaS services once customers have signed up. This web app likely will need to store both text data and media somewhere.
Thinking about architecture
There are a few important questions I like to ask myself when coming up with an app architecture.
How can I architect this app so that I can choose the best technology for each need?
This is a big one and, in my opinion, where a modular architecture really shines. For example, a great blogging platform will likely not also be a great platform for the core app. So can we choose an architecture that lets a strong blogging tool do the blogging piece and a strong web app tool do the web app piece?
How can I make sure the app will scale (in all the right places)?
Your core app may or may not need to scale. Your blog may or may not need to scale. Or one might need to scale and the other might not. Whatever the need, you should try to position yourself to scale up only the parts of your app that will need to scale and not waste money being forced to scale up an entire monolith to accomodate the needs on one part.
How can I divide the app up so specialists can work in isolation on their respective parts?
Marketers creating blog posts and writing copy for the public-facing app probably shouldn’t be mucking around in the SaaS app codebase. Going even further, you likely don’t want to force backend engineers to write front-end code and vice versa.
This consideration may be less important if you’re a one-person shop, but separating concerns like this will probably lead to better separation of concerns in the long run and better maintainabilty.
How can I keep all the different pieces synchronized?
While it’s optimal to keep all of the different pieces of your application functioning separately, it’s inevitable that you’ll need to sometimes coordinate the deployment of the public-facing application with the web app. How can we have a bunch of different parts of the application isolated yet synchronized?
The proposed architecture
Okay, so let’s get down to details. Barring any special requirements to make me think otherwise, I would likely architect the application as follows:
- A static site generator for the public-facing website and blog.
- A single page application for the front-end of the SaaS web app.
- An API server for the backend of the SaaS web app.
- A cloud-hosted database for the app’s data. SQL or NoSQL depending on the need.
- A cloud-based object store for your media.
- A monorepo to host the code for these various components together.
The specific technologies I would choose for each piece are as follows and are very heavily influenced by what I have experience with:
|Component||Architecture choice||Tech choice|
|Public-facing website and blog||Static site generator||Gatsby hosted on Netlify|
|SaaS front-end||Single page application||React hosted on Netlify|
|SaaS backend||API||Node hosted on Heroku|
|Text data store||SQL or NoSQL datbase||Postgres or MongoDB hosted on Heroku|
|Media store||Cloud object store||Amazon S3 bucket|
Now to dive a bit more into why I like these choices!
Using a static site generator for the public-facing website and blog
Static site generators (SSGs) have emerged as an excellent choice for, well, generating static sites. As a developer you get excellent control over the look and feel of the site but you can use additional tooling like Contentful to offer blog content producers a convenient UI for creating and schedule content posts.
SSGs often have community-built (or official) components to help achieve excellent SEO. Many are blazingly fast and score very highly with Google Lighthouse.
When you combine your SSG with a service like Netlify, deploying becomes as easy as pushing your code to Github. Netlify will pull your code from the repository, build the static app, and deploy it for you. Netlify handles content delivery with their own Content Delivery Network (CDN) and you generally don’t have to worry about heavy traffic.
I specifically selected Gatsby as the SSG simply because I have a lot of experience with it (you’re looking at a Gatsby blog right now). There are plenty of other great SSGs out there!
Using a single page application for the SaaS front-end
Single page applications (SPAs) have become the standard for web apps. It seems that the expectation at this point is to have a very fluid experience with minimal page reloading. SPAs also helpfully isolate your view layer from your backend. For a lot of the same reasons as the static site, I recommend using a plug-and-play service like Netlify to host the SPA.
I would choose React as my front-end because I have a lot of experience with it. Again, there are plenty of great choices that aren’t React.
An API-based backend
This is kind of what you’re left with given that you’ve selected a SPA front-end. You can host an API service somewhere like Heroku pretty easily. The API layer will take requests from your front-end, take action as necessary, and return data back to the front-end.
A bonus of breaking your app into a front-end and API is you can easily have API offerings for your consumers if that’s part of the SaaS model.
Note: It may be worth looking at “severless functions” as an alternative to a monolithic API layer. Rather than having to worry about a service, serverless functions let you just write the handler function for API endpoints and the serverless function provider (e.g., Amazon, Netlify, others) handle making sure a server is available to serve them.
SQL or NoSQL database
Probably nothing too controversial here: choose a SQL database for tabular data or NoSQL for document data. Possibly add in something like Redis for caching. Assuming I’m using Heroku for the app’s backend, it’s a reasonable choice to also use it for the data layer simply because I don’t feel like managing a ton of different accounts.
Cloud object store
If you’re storing any non-text data like pictures or videos, an Amazon S3 bucket seems to be a really reliable, secure, and fast choice. Amazon has easy enough software development kits for most backend stacks.
Using a monorepository
Just because you’re not using a monolith doesn’t mean you can’t host all your code together. I really like monorepositories because you can have separate services for different parts of your application but more easily keep them in sync—you can make sure that change to your sign-up form in the public-facing application is released at the exact same time your API is ready to accept the new fields.
How it all fits together
The following architecture gives you a picture of how our notional stack fits together:
Users enter in at the public-facing application and possibly peruse the blog. They might choose to sign up or login (I would probably include those pages in the public-facing site). Once login occurs, they are sent to the Single Page Application. From there, all requests are sent to the API, which performs any data operations on the database and object store, as well as integrating with third party APIs (e.g., an authentication provider).
I hope you enjoyed this quick tour through a notional SaaS app design. Of course, it’s absolutely impossible to create one SaaS architecture to rule them all, but I’m hopeful this gets you moving in the right direction as you consider the idiosynchracies of your system.
If you'd like to support this blog by buying me a coffee I'd really appreciate it!
Nick Scialli is a senior UI engineer at Microsoft.