Launch your SaaS and earn your first MRR with React SaaS Boilerplate.
Creative Designs Guru

The Modern Tech Stack to build a SaaS in 2024 as a team of one-man with Next JS and AWS

August 19, 2021

As someone who loves cutting-edge technology, I choose to build my first SaaS with a modern tech stack. With the rise of JAMStack and serverless architecture, I created PostMage with Next JS static generation for the frontend and the Node.js backend deployed to AWS.

Because I'm a solo full-stack developer, my time and resources are extremely limited. In this article, I'll share all the technologies I use to build my SaaS product: from programming language to development tools. You'll find how I overcome this challenge to build a SaaS as a solo developer.

Hope my story gives you inspiration to create your SaaS products.

TypeScript Everywhere

For building my SaaS, I wrote every line of code in TypeScript. Yes, all the code: Frontend, Backend and also, Infrastructure as code in TypeScript.

TypeScript programming language logo

The whole project only uses one and unique programming language. No time to learn new languages and save time by making the code easy to maintain.

Why did I choose TypeScript? It makes the development much more pleasant with strongly-typed and has better integration to IDE. So, if you are still a JavaScript developer, you should give it a try.

Frontend framework

For the frontend, I use Next.js. It's a React framework to build a complex application. The good news, Next JS supports TypeScript out-of-the-box.

I use Tailwind CSS styling the React components. As a developer, you usually build an ugly interface. With Tailwind CSS, you can have now build a not so ugly interface even if you aren't a designer.

Nextless React SaaS Template

As a true believer of JAMStack, I have previously taken some time to try Jekyll, Hexo and 11ty for different projects. I choose to build my SaaS in static generated mode using Next JS. So, at build time, all the pages are generated and pre-rendered. Perfect for SEO, cheap hosting, fast, secure and highly scalable.

Join my Newsletter for JS Devs
Get helpful content about Full-Stack React development with Next JS and Tailwind CSS. No spam, unsubscribe at any time.

Static hosting

I use Cloudflare Pages as a hosting service for the frontend, it's a brand new alternative to Netlify or Vercel. Cloudflare has announced it in December 2020 in beta and released it to the public in April 2021.

Cloudflare pages hosting

There is some small missing feature (nothing big) in Pages. Until the Cloudflare team solve it, I've found temporary workarounds. So, it isn't a big deal.

The good thing about Cloudflare Page is its generous free tier: unlimited bandwidth (Vercel and Netlify are limited to 100GB per month) and you can set up a password-protected website for free (not included for free in Vercel or Netlify).

If you like to host everything on AWS, you can also use AWS Amplify to host your frontend. It's the equivalent of Vercel or Netlify but on AWS. With AWS Amplify, you can also deploy automatically from your GitHub repository. Like all major providers, you can deploy at each commit or pull request.

Serverless REST API

On the backend side, I've built a REST API with Express.js and Serverless Framework. To support TypeScript in Serverless Framework, I use serverless-bundle plugin. Express.js needs another plugin to work with Serverless Framework named serverless-http.

For better developer experience, I've also used two other plugins: serverless-dotenv-plugin and serverless-offline. The first plugin is to support dotenv files and the second one is to run Serverless Framework on your local computer.

As a solo developer, I choose serverless architecture for making my life easier with easy deployment, low maintenance and scalable backend. No need to become a DevOps engineer: no need to SSH, make OS updates, configure proxy/webserver/load balancer/firewall, etc.

Authentication

The REST API is protected by the IAM authentication. It's AWS built-in feature to secure any AWS resources, in our case, API gateway and AWS lambda. It denies the API invocation when the user isn't connected to the SaaS application. So, when it's protected, external actors won't be able to invoke your resource.

Because the API is deployed to AWS, I choose to use AWS Cognito for authentication. The good thing is that Cognito saves a lot of time by providing everything you need to implement authentication for your SaaS. You get access without any effort to Email authentication and Social sign-in (Facebook, Google, Apple and Amazon).

AWS Cognito authentication provider

The connection between AWS Cognito and React frontend is done through AWS Amplify. Amplify provides React components and code for making your frontend integration to AWS easier and faster.

AWS Amplify logo

NoSQL Database

Major and well-known databases like PostgreSQL and MySQL don't fit very well in Serverless architecture. Due to the nature of serverless, it can create a lot of connections to the database and exhaust the database connection limit.

On most providers, even if you don't have any traffic on your SaaS, you still need to pay your DB instance. On the opposite, when your application starts to grow, your database can quickly become the bottleneck.

As a solo full-stack developer, I wanted something extremely easy to manage and 100% compatible with serverless. So, I choose DynamoDB as a primary database.

AWS DynamoDB serverless database

DynamoDB is a NoSQL database fully managed by AWS and I use it to store user states. They almost handle everything and I just need to focus on my code.

Infrastructure as code

As you can see, I use several AWS services for my SaaS app. It's extremely painful to set up manually cloud resources in each environment (development, staging or production) and hard to maintain consistency between them.

AWS gives developers access to AWS CDK where you can define your cloud resources in TypeScript. In one command, you can deploy to your AWS account and get everything provisioned.

AWS CDK infrastructure as code

Testing

Testing is often overlooked by developers, especially when you are a solo developer. Building a SaaS product is a long journey and you need to make sure your code is reliable and stable. Testing is the only way to make sure your SaaS product is ready for production and don't lose your time to run manual tests.

For testing the frontend, I use Jest and React Testing Library to test React components. For testing the backend, I use Jest and Supertest to test the REST API. Finally, to test the whole stack, I use Cypress for end-to-end testing.

Deployment

Like many developers, I use Git and GitHub for version control of my code. Many modern hosting services like Vercel and Netlify, Cloudflare pages automatically build and deploy your code at each commit. If you work with Git branches, you can also live preview the results without pushing to production.

GitHub developer collaboration tool

For the backend and the infrastructure, I use a third-party service named Seed.run to deploy automatically at each commit. Like the frontend, it also builds and deploys the backend resources on AWS.

Email service

For sending emails, I choose to use AWS SES. It's a fully managed email service by AWS. Like all other services, everything is hosted and managed by AWS. So, it make the infrastructure much more simple and easy to maintain.

With AWS SES, you can send transactional emails and marketing emails. On top of that, you don't need to worry about the server, the IP reputation, the spam filters, etc. Perfect for a solo developer.

DNS and CDN

As you can doubt, I use Cloudflare for DNS and CDN without any surprise ;) Cloudflare Pages automatically deploy your code in the Cloudflare network, I only need to point my domain to Cloudflare DNS server and they handle the rest. Using Cloudflare, you get plenty of security features like a firewall and a DDoS protection for your SaaS products.

Cloudflare DNS and CDN provider

Error tracking

I use Sentry as the error tracking solution. It automatically reports when something goes wrong with useful information like stack trace, breadcrumbs (a trail of events that happened before an issue), browser information, OS information, etc. It makes debugging in production much easier with enriched data:

Sentry exception tracking

Sentry is only set up for the frontend and not for the REST API, I keep using the native solution. Indeed, Sentry with AWS lambda creates a lot of overhead and the setup wasn't straightforward. In the next section, you'll find the solution I use for error tracking in the backend.

Sentry error tracking

Logging, monitoring and alert

AWS Lambda automatically sends logs to AWS CloudWatch, so no need to use Sentry. Here is an example of logs stored in CloudWatch:

Cloudwatch log example

You also get access to your lambda metrics. Perfect to understand how your serverless functions behave and detect if there are any errors.

Lambda dashboard with metrics

I also use Lumigo to have additional information for my logging and monitoring. The interface is easier to use compared to Cloudwatch:

Lumigo log example

You can also enable tracing in Lumigo where you can visualize your AWS service and external API calls. It makes your debugging session easier by letting you know if there is an error in your code or it's from an external service.

Lumigo log example

Payment and subscription

The last piece of a SaaS and the most important thing for a business is to accept payment. Accepting a one-time payment is hard but, the task for recurrent payment is much complex. Unfortunately, for a SaaS business, we need to handle the second case.

Your customers need to choose the plan and enter their personal information when they subscribe for the first time.

Stripe hosted checkout session

After that, your users should have a self-service portal where they can manage their plan: upgrade, downgrade, cancel, pause, resume their subscription plan.

They sometimes also need to update their personal information. And, they also need access to their invoice history when needed.

Stripe customer portal

Stripe can manage everything I mention in this section, it hides all these complexities and makes the integration to payment easier.

Stripe logo

Conclusion

It took me 5 months of development to build this full-stack React SaaS template. Instead of focusing on my business, I was solving these technical details. Building the first version of your SaaS should only take 1 month and not 5.

By going through this long journey, I've learned so many things and I've made tons of mistakes. I hope others developers won't do the same mistakes, so I build Nextless JS, React Boilerplate for SaaS products.

Next JS SaaS Boilerplate Starter

With Nextless.js, you get everything I mentioned in this article without you writing any line of code. Save you time, focus on things that matter and launch your SaaS faster.