How to start a SaaS project #3: The Stack
In the previous parts, I wrote about the importance of having a data model and some necessary features every SaaS project needs. Today, I'm going to write about the tech stack – i.e. the services and tools your project needs. This time, it's not possible (nor useful) to keep it high-level without mentioning concrete examples. This time, I'm going to tell you what tools and services I personally use to stay true to the original goals:
- Fantastic user experience – To make your users happy
- Building as little as possible – To be able to make changes easily
- Fast development – So you can focus on marketing too
- System resiliency – To be able to catch and fix errors easily
- Easy for a solo developer – You don’t have team, act accordingly
This post is a kind of an assortment of development decisions and tips I wish I knew when I was starting out. Many of the points could be a separate article on their own but I try to keep it short and simple. If something in particular interests you, you should be able to learn more just by googling the right keywords. And as always, don't hesitate to reach out if you get stuck.
Before we get to the actual stack, I need to mention one critical aspect you need to consider when starting a SaaS project.
Monolith vs. microservices
I probably should have talked about this in the previous article, but since I forgot, I'm adding it here.
A monolith in this context means having the whole application in one codebase, deployed as a single unit. A stack of microservices means splitting the app to multiple parts (usually by features), maintaining and deploying each one separately.
There are pros and cons to both, but when it comes to small, bootstrapped software businesses, I'm a monolith kind of guy. When starting out, you want things to go smooth and fast (see the goals above). You don't want to spend time on additional dev-ops work. Leave microservices to large enterprises, where they make more sense. An article by DHH sums it up nicely.
Similar to the "monolith vs. microservices" debate, you need to choose between NoSQL and a relational database system. Relational databases require a defined schema for the data you're storing. In contrast, NoSQL databases can work with a constantly changing data structure.
As a manifestation of a model we talked about in the first part, you should use a relational database. There are specific cases – like working with geospatial data – where a NoSQL approach makes more sense, but they are rare. For the average SaaS, relational databases like PostgreSQL or MySQL are a perfect choice. They are reliable, fast, and predictable, which makes them easy to work with.
The downside is that they are more difficult and expensive to scale, but let's be honest – you'll be happy to come to the point where you have those problems.
There's one common use case for a NoSQL DB used alongside a relational one and that's background processing. You don't want your notification emails to slow down and block the main app. And it's not a scaling issue – you'll encounter this problem with your first active user. Without a background processing system in place, any action that triggers an email notification will wait for that email to render and send. Databases like Redis are used to store jobs like this until the server is ready to process them.
Similar to other aspects of solo SaaS development, you don't want to spend a second more than is necessary on deployment and server management. Those things are not fun and can block you for days.
Don't make your life harder and start your project on Heroku. People always tell me it's expensive, but its Hobby tier for $7 per month is more than enough to power a small SaaS until you start making some numbers. Even then the upgrades are not that expensive. And when you really start to grow, it's fairly easy to migrate to your own servers.
Heroku will build and deploy your app with a single command. You can hook it up to your Github repo so every time you push, the build starts automatically. Quite a time-saver.
A great alternative I discovered recently is Hatchbox by Chris Oliver. It's basically a Heroku-like service but you provide your own servers. So there's absolutely no lock-in and you get full access to your server as usual (Heroku doesn't allow this).
Fact: You will need to send emails to your customers. Another fact: You will need them to arrive fast and to the inbox (not spam). For that reason, you want to separate marketing and transactional emails to different services. Services that send marketing emails get a lot of spam reports which decrease their deliverability rates.
For transactional emails (password reset, reply notification, invoice, ...) I absolutely recommend Postmark. They specialize in fast and reliable delivery of transactional emails and hook you up with well-tested templates so you don't have to fiddle with email design. They don't offer a free tier but start at $10/mo which is fairly cheap to start.
For marketing emails like onboarding and monthly newsletter, I like to use MailerLite. They offer a generous free tier that includes an automation tool, so you can tailor your onboarding sequence easily.
CSS? That's a weird thing to mention together with deployment and email services in one article... but hear me out: Write as little CSS as possible.
Writing CSS takes a long time and it's very frustrating when something doesn't work or you have to fight with the framework to make an element look right.
And I don't mean keep your app without styling – I'm not totally crazy. Utility-first CSS frameworks like Tailwind lets you stay in HTML and style your components with low-level classes. It takes a few hours to master, but with a VS Code IntelliSense plugin, it's a game-changer.
When I tried it the first time (with Tachyons) I found it impractical and threw it away. Oh, what a mistake. I gave it chance again a few months later with Tailwind. This time, I made an effort to learn the classes (it's really not that hard, they are very intuitively named). The development speed increase came so fast I think you might need a seatbelt.
What's even more awesome is that you're not forced to any particular style. The look of your app is completely up to you.
If you want to learn more and get really efficient, check out Sam Selikoff's excellent video.
These are some of the tips I wish I'd known when starting FeedBear. I hope it helps you save time and focus on what matters. As developers, we often like to tinker with stuff to make it perfect and custom. But when building a business, it's best to resist that temptation. Spend time on stuff that brings value to your customers.
Building a monolith instead of a cluster of microservices will make your app easier to develop and maintain. Don't worry about scaling too soon. When it happens, you'll have the resources to do what's needed.
The same applies to picking a database. A relational database is fast and reliable. It's easy to work with a fixed schema. Use a simple NoSQL (Redis) for scheduled jobs.
Deploy your app with Heroku or Hatchbox so you don't need to fiddle with setting up a server. It's one less thing to worry about.
Use different services for transactional and marketing emails. Mixing those two can hurt your deliverability rates for important messages.
And as a cherry on top – write as little CSS as possible with Tailwind. Learning the class names to be truly fast takes a while but the reward is so worth it, it's hard to put into words.
If you get stuck on anything or if you think you have a better approach to a problem I mentioned, please let me know. I always try to help and I'm always happy to learn something new.