My First SaaS: Building the MVP

In my previous posts, I talked about 7 things I learned from my first SaaS, how I chose the tech stack, and how I defined the MVP.

Now I will share how I built the MVP for https://hostifi.net, a UniFi controller hosting platform.

The SaaS Stack

If you read how I chose the tech stack for HostiFi, then you already know about how I struggled with Django early on and eventually gave up on it. I ended up getting started with WordPress and a combination of Easy Digital Downloads plugins.

In particular, I purchased Recurring Payments and Stripe

Between these plugins, WordPress, and the Startuply theme I had purchased from ThemeForest, I had all the basic SaaS functions taken care of — landing page, subscriptions, checkout, billing, user account management.

After purchasing a server subscription, the user was taken to a blank PHP dashboard page, where I could build a custom interface.

The Server Creation Script

A snippet from HostiFi’s server creation script

It was time to build the actual product, the UniFi server creation part.

But there was a problem. I had already written the entire server building script in Python weeks beforehand because I was expecting to integrate it into Django later.

The Python script made API calls to Vultr, the VPS provider I had chosen to use. It would create a server, SSH into it, and automatically run the commands to install UniFi and create an admin account for the user who signed up. Then it would need to provide a link to the server and UniFi credentials to the user’s dashboard.

Integrating WordPress and Python

So now I had to figure out how to integrate that Python script that I had written with the WordPress website so that a server could be built after a user purchased a subscription.

At first, I was looking at using Zapier. Easy Digital Downloads makes a plugin for it. It had the ability to receive a hook when a user signed up, and I could pass that information to trigger the Python script.

It seemed like a perfect solution at first, but after looking into Zapier’s pricing plan, for under $50/month, the Zaps only run once every 15minutes.

That was too long for a customer to wait for their server, so I tried to figure out how I could make my own integration.

I was looking at the WordPress database trying to reverse engineer how it all worked, and I had an idea.

I noticed that a row is created in the table “wp_edd_subscriptions” when a user signs up.

I created my own custom table and named it “servers”.

Then I wrote some code in Python to read the subscriptions and servers tables from the database. The script would save the rows to a list and then compare the two lists.

Now the Python script was able to determine two scenarios:

  • If a server exists without a subscription, then it needs to be canceled
  • If a subscription exists without a server, it needs to be built

I created a cron job to run the Python script once every minute that way it would be constantly checking for new customers.

As simple as it seems, that was really one of the biggest breakthroughs for me on the entire project!

Now I was finally able to automatically create a UniFi server after a customer signed up, and the Python script saved that server address into the server table along with the UniFi credentials, and customer identifier.

The User Dashboard

A screenshot of the HostiFi user dashboard on launch day — May 24, 2018

The only step left was to write the PHP user dashboard.

That part was pretty straightforward, I had a little bit of experience with writing basic PHP, and I was able to get it done with less than 100 lines of code.

The dashboard page PHP code only had to check for a couple of scenarios:

  • If the user is logged in, but no servers are being built, display a message asking them to purchase a subscription
  • If a server row exists but hasn’t completed yet, display a table and server status as “provisioning” along with a message saying it will take a few minutes. I also included a simple line of Javascript to hard reload the page automatically every 15 seconds until no more servers were being built
  • If a server row exists and is complete, display the server info in a table

Closing thoughts

I’m not really recommending this tech stack to anyone, just sharing my experience. Anyone who knows anything about programming recognizes right away the insanity of this duct-taped solution.

There’s a major scalability issue with the server creation script, for example.

It’s not multi-threaded, so it can only build one server at a time. Each server takes about 5 minutes to build.

I think about it all the time, and it bothers me.

But it’s never been a problem because I’ve never had a bunch of people signing up at the exact same time. No one has ever waited more than 10 minutes for a server to build.

More than likely, that script will never need to be optimized.

It works...

It’s making money every month…

Customers are very happy with it.

I’ve had zero complaints about the speed, design, or function of the website after serving over 75 customers.

I guess the theme of these posts is that you don’t have to be an incredible programmer to create value. Your customers care about how well you solve the problem that they have, not the web framework or obscure solution design choices that you made along the way.