Avatar of Tim Nolet

Tim Nolet

Founder, Engineer & Dishwasher at Checkly
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

Heroku Docker GitHub Node.js hapi Vue.js AWS Lambda Amazon S3 PostgreSQL Knex.js Checkly is a fairly young company and we're still working hard to find the correct mix of product features, price and audience.

We are focussed on tech B2B, but I always wanted to serve solo developers too. So I decided to make a $7 plan.

Why $7? Simply put, it seems to be a sweet spot for tech companies: Heroku, Docker, Github, Appoptics (Librato) all offer $7 plans. They must have done a ton of research into this, so why not piggy back that and try it out.

Enough biz talk, onto tech. The challenges were:

  • Slice of a portion of the functionality so a $7 plan is still profitable. We call this the "plan limits"
  • Update API and back end services to handle and enforce plan limits.
  • Update the UI to kindly state plan limits are in effect on some part of the UI.
  • Update the pricing page to reflect all changes.
  • Keep the actual processing backend, storage and API's as untouched as possible.

In essence, we went from strictly volume based pricing to value based pricing. Here come the technical steps & decisions we made to get there.

  1. We updated our PostgreSQL schema so plans now have an array of "features". These are string constants that represent feature toggles.
  2. The Vue.js frontend reads these from the vuex store on login.
  3. Based on these values, the UI has simple v-if statements to either just show the feature or show a friendly "please upgrade" button.
  4. The hapi API has a hook on each relevant API endpoint that checks whether a user's plan has the feature enabled, or not.

Side note: We offer 10 SMS messages per month on the developer plan. However, we were not actually counting how many people were sending. We had to update our alerting daemon (that runs on Heroku and triggers SMS messages via AWS SNS) to actually bump a counter.

What we build is basically feature-toggling based on plan features. It is very extensible for future additions. Our scheduling and storage backend that actually runs users' monitoring requests (AWS Lambda) and stores the results (S3 and Postgres) has no knowledge of all of this and remained unchanged.

Hope this helps anyone building out their SaaS and is in a similar situation.

READ MORE
19 upvotes·287.3K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

Vue.js JavaScript vuex

If you run a SaaS, you probably want to show your users when they are almost running out of widgets. Or that they can get some cool feature on a more expensive plan.

Or, in other words, how can you be nice and commercial in dealing with plan limits?

We use Vue.js with Vuex for our front end, but the patterns and code examples here can be applied to any other SPA framework.

We implemented some very specific data structures in Vuex to make it easy for components to check what a user's status is with regard to plan limits and usage. This centralizes and encapsulates the knowledge about typical SaaS things in one place and leverages Vue's component system nicely. Read more in the dedicated blog post.

READ MORE
How we deal with plan limits in the front end of our SaaS app (blog.checklyhq.com)
13 upvotes·17.4K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

When adding a new feature to Checkly rearchitecting some older piece, I tend to pick Heroku for rolling it out. But not always, because sometimes I pick AWS Lambda . The short story:

  • Developer Experience trumps everything.
  • AWS Lambda is cheap. Up to a limit though. This impact not only your wallet.
  • If you need geographic spread, AWS is lonely at the top.
The setup

Recently, I was doing a brainstorm at a startup here in Berlin on the future of their infrastructure. They were ready to move on from their initial, almost 100% Ec2 + Chef based setup. Everything was on the table. But we crossed out a lot quite quickly:

  • Pure, uncut, self hosted Kubernetes — way too much complexity
  • Managed Kubernetes in various flavors — still too much complexity
  • Zeit — Maybe, but no Docker support
  • Elastic Beanstalk — Maybe, bit old but does the job
  • Heroku
  • Lambda

It became clear a mix of PaaS and FaaS was the way to go. What a surprise! That is exactly what I use for Checkly! But when do you pick which model?

I chopped that question up into the following categories:

  • Developer Experience / DX 🤓
  • Ops Experience / OX 🐂 (?)
  • Cost 💵
  • Lock in 🔐

Read the full post linked below for all details

READ MORE
Why I pick Heroku over AWS Lambda for my SaaS. But not always. (blog.checklyhq.com)
12 upvotes·8.5K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

Vue.js Intercom JavaScript Node.js vuex Vue Router

My SaaS recently switched to Intercom for all customer support and communication. To get the most out of Intercom, you need to integrate it with your app. This means instrumenting some code and tweaking some bits of your app's navigation. Checkly is a 100% Vue.js app, so in this post we'll look at the following:

  • Identifying a user with some handy attributes
  • Getting page views right with Vue Router
  • Sending events with Vuex
  • Some nice things you can now do in Intercom

After finishing this integration, you can actively segment your customers into trial, lapsed, active etc. etc.

READ MORE
How I integrated Intercom into my SaaS's Vue.js app (blog.checklyhq.com)
11 upvotes·22.1K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

PostgreSQL Heroku Heroku Postgres Node.js Knex.js

Last week we rolled out a simple patch that decimated the response time of a Postgres query crucial to Checkly. It quite literally went from an average of ~100ms with peaks to 1 second to a steady 1ms to 10ms.

However, that patch was just the last step of a longer journey:

  1. I looked at what API endpoints were using which queries and how their response time grew over time. Specifically the customer facing API endpoints that are directly responsible for rendering the first dashboard page of the product are crucial.

  2. I looked at the Heroku metrics such as those reported by heroku pg:outlier and cross references that with "slowest response time" statistics.

  3. I reproduced the production situation as best as possible on a local development machine and test my hypothesis that an composite index on a uuid field and a timestampz field would reduce response times.

This method secured the victory and we rolled out a new index last week. Response times plummeted. Read the full story in the blog post.

READ MORE
How I decimated Postgres response times for my SaaS (blog.checklyhq.com)
10 upvotes·44.7K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

PostgreSQL Heroku Node.js MongoDB Amazon DynamoDB

When I started building Checkly, one of the first things on the agenda was how to actually structure our SaaS database model: think accounts, users, subscriptions etc. Weirdly, there is not a lot of information on this on the "blogopshere" (cringe...). After research and some false starts with MongoDB and Amazon DynamoDB we ended up with PostgreSQL and a schema consisting of just four tables that form the backbone of all generic "Saasy" stuff almost any B2B SaaS bumps into.

In a nutshell:cPostgreSQL Heroku Node.js MongoDB Amazon DynamoDB

When I started building Checkly, one of the first things on the agenda was how to actually structure our SaaS database model: think accounts, users, subscriptions etc. Weirdly, there is not a lot of information on this on the "blogopshere" (cringe...). After research and some false starts with MongoDB and Amazon DynamoDB we ended up with PostgreSQL and a schema consisting of just four tables that form the backbone of all generic "Saasy" stuff almost any B2B SaaS bumps into.

In a nutshell:

  • We use Postgres on Heroku.
  • We use a "one database, on schema" approach for partitioning customer data.
  • We use an accounts, memberships and users table to create a many-to-many relation between users and accounts.
  • We completely decouple prices, payments and the exact ingredients for a customer's plan.

All the details including a database schema diagram are in the linked blog post.

READ MORE
Building a multi-tenant SaaS data model (blog.checklyhq.com)
8 upvotes·64.7K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

JavaScript Node.js hapi Vue.js Swagger UI Slate

Two weeks ago we released the public API for Checkly. We already had an API that was serving our frontend Vue.js app. We decided to create an new set of API endpoints and not reuse the already existing one. The blog post linked below details what parts we needed to refactor, what parts we added and how we handled generating API documentation. More specifically, the post dives into:

  • Refactoring the existing Hapi.js based API
  • API key based authentication
  • Refactoring models with Objection.js
  • Validating plan limits
  • Generating Swagger & Slate based documentation
READ MORE
How we added a public API to our existing SaaS app (blog.checklyhq.com)
7 upvotes·65.6K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

Hotjar GitHub MailChimp Drift

When I started Checkly, I had no clear strategy on collection, managing and acting on customer feedback.

Over the last year, going from private beta to the first couple dozen customers I found my way in the jungle of customer feedback tooling and found something that worked for me and my company.

The linked post is a bit less technical than normally. The post goes into:

  • Using Hotjar and how it sorta worked for me.
  • Using Drift and why I was totally wrong about chat widget.
  • Using GitHub as a public roadmap.
READ MORE
How I manage customer feedback for my bootstrapped SaaS (blog.checklyhq.com)
6 upvotes·13.4K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

Let's Encrypt Amazon EC2 Heroku Node.js Vue.js JavaScript

We recently went through building and setting up free SSL for custom domains for our #SaaS customers. This feature is used for hosting public status pages and dashboards under the customers' own domain name.

We are in the #Node.js, #AWS and #Heroku world, but most of the things we learned are applicable to other stacks too.

The post linked goes into three things:

  1. Configuring the Let's Encrypt / ACME client called Greenlock.
  2. Getting DNS right on Amazon Route 53
  3. Actually determining what content to serve based on hostname.

All seem pretty straightforward, but there are gotcha's at each step.

Hope this helps other budding SaaS operators or ops peeps that need this functionality.

READ MORE
How I set up SSL with Let's Encrypt for my SaaS customers' dashboards (blog.checklyhq.com)
6 upvotes·11.2K views
Avatar of tim_nolet
Founder, Engineer & Dishwasher at Checkly ·

AWS Lambda Serverless Amazon CloudWatch Azure Functions Google Cloud Functions Node.js

In the last year or so, I moved all Checkly monitoring workloads to AWS Lambda. Here are some stats:

  • We run three core functions in all AWS regions. They handle API checks, browser checks and setup / teardown scripts. Check our docs to find out what that means.
  • All functions are hooked up to SNS topics but can also be triggered directly through AWS SDK calls.
  • The busiest function is a plumbing function that forwards data to our database. It is invoked anywhere between 7000 and 10.000 times per hour with an average duration of about 179 ms.
  • We run separate dev and test versions of each function in each region.

Moving all this to AWS Lambda took some work and considerations. The blog post linked below goes into the following topics:

  • Why Lambda is an almost perfect match for SaaS. Especially when you're small.
  • Why I don't use a "big" framework around it.
  • Why distributed background jobs triggered by queues are Lambda's raison d'être.
  • Why monitoring & logging is still an issue.

https://blog.checklyhq.com/how-i-made-aws-lambda-work-for-my-saas/

READ MORE
How I made AWS Lambda work for my SaaS (blog.checklyhq.com)
5 upvotes·29.3K views