How to start a SaaS project #2: Necessary Features
In the first part of this series, I wrote about the importance of creating a data model first when building your project. This time, you'll learn what parts are necessary for a SaaS project to work, what technical challenges await you down the road, and how to avoid problems. Same as before, I want to keep this guide more high-level – explaining the concepts, rather than a concrete piece of code.
To reiterate our goals from the first part:
- 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
I'm going to talk about some important features every SaaS project needs and a few development decisions you'll have to make. Note: I use mainly Ruby on Rails for backend, so that's why most examples will be from that ecosystem. I don't want to pollute this article with tons of links, so if you use Node, Laravel, or something else, simply search for an alternative in your ecosystem.
Necessary SaaS features
Apart from business-specific features that are unique to your app, you need to think about some general aspects every SaaS app needs. It's the boring stuff nobody cares about, but important – authentication, billing, and teams.
You may see this sentence repeatedly in this article, but don't build your own. As a general rule, you should spend time on features that will make you money, not on boilerplate code. What's even more important, existing solutions are battle-tested in hundreds of real-world applications. This gives you an advantage of better security and user experience out of the box.
Keep in mind, that it's not only about creating an account and logging in. In a modern app, users expect to have the ability to use a social network to authenticate. To easily reset their forgotten password. To invite a teammate.
When using an existing solution, you get all that. There are two approaches:
- Using a hosted service like Auth0 – The main benefit is easy integration to any codebase and storing user data out of your database. If you're hacked, user data stays safe. On the other side, if you're going to have many user accounts, it can get pricey.
- Implementing an auth library like Devise or Passport – This approach is my favorite. The integration can be a bit more complicated (depending on your framework) and you have the responsibility of storing user data. But the main benefit is added flexibility and $0 cost.
Subscriptions & Billing
If you're planning to make money with your SaaS, you'll need a way to determine what to charge them for. I'm talking about pricing plans and their implementation. In the beginning, I advise going with the simplest pricing possible. For FeedBear, it was a single "Premium" plan with a 14-day trial period.
That way, you don't have to guard features based on the current user's plan or monitor their usage, which means less code. And less code means fewer bugs and more time.
Similar to authentication, don't build your own solution. There's a minefield of things that are very annoying to implement and can break easily. Like maintaining billing info, updating card details, calculating VAT, invoices, email notifications, refunds, ... you get the idea.
In general, you want two things:
- Process payments and charge money – That's what Stripe or Braintree is for. I also like to keep as much data there as possible. You don't really need to save the user's billing address or VAT ID to your database. Save only what you need, request other stuff via API.
- Allow users to pay and get access to your app – This is basically working with data from the first step. This is the hard part.
As with authentication, you can manage subscriptions with an external service or use a library.
- Using a payment service: Tools like Chargebee and Outseta provide drop-in solutions, specifically for SaaS, that you just hook to your backend and include on the frontend. The main disadvantage, of course, is added costs.
- Implementing a library: As you can probably guess, this is my favorite way to do it. It's free and pretty easy to set up (again, YMMV based on what framework you use). In the Rails ecosystem, there's a fantastic gem called Pay that works with Stripe or Braintree.
Oh, and by the way, your pricing will likely completely change multiple times as you grow. Not only prices but the number of plans and what they represent, too. Experimenting with pricing is essential when going through a product/market fit phase. Having a flexible solution will allow you to make those changes fast without fear of breaking stuff.
Accounts, Teams & Multi-tenancy
You may argue that you don't need to think about teams using your app when you're just starting out. That may be true, but in the B2B world, it's rare for a tool to be used by only a single person. Unless you target very small companies.
Fortunately, implementing teams at the beginning is easy and saves you a ton of trouble later. You don't even need any external solution. Look at your data model. You probably have a "User" table connected to something like "Project". A user has many projects and a project belongs to a single user. The only thing you need to change is to stick an extra table between them. Its often called "Account" or "Team".
On top of letting your users invite colleagues, this allows you to attach billing info to "Account", not "User". Often times, the person trying your product is not the one who will be paying for it.
Another important thing to consider is scoping data to an account. This is called multi-tenancy. You don't want to end up in a situation where data from one account "leaks" to another. For example, posts from one FeedBear project can never appear on another project.
Whatever you're building, there always be some boilerplate code that you don't want to spend time on. Maybe you don't even think about it. The best approach is to utilize existing solutions or libraries so you can focus on the business features.
When starting FeedBear, I didn't know how to implement subscriptions, billing, or multi-tenancy. I didn't implement teams from the start. And I regret it. I spent countless days fighting code that I didn't even need to write in the first place.
And when I'm talking about saving time and skipping boilerplate code, I have to mention Jumpstart. It's a Ruby on Rails template to start your project with all of the above features (and some more) implemented, ready to go. If you're into Rails, I can't recommend it enough. If it existed two years ago, it would save me months of struggle.
The next part of this guide will be about the stack – how to handle CSS easily, where to host so you don't need to worry about devops, which email service to use, etc. Stay tuned!