Serverless Explained
We talk about the Serverless Trend and dive into Functions as a Service. Plus, a quick intro to Mathematical Combinatorics and Counting. Also, things that you'll probably need when building an app.
Hey Everyone,
Today we’ll be talking about
An overview of the Serverless Trend
We’ll be focusing on FaaS (Functions as a Service)
We cover how to use them, how they work, statelessness, execution duration and cold starts.
Things that you’ll probably need when building an app
YAGNI is a famous acronym that stands for you aren’t gonna need it. Don’t waste time adding features until you need them.
We’ll discuss PAGNIs, things that you’ll probably need to build in your app sooner rather than later.
How to bootstrap a JavaScript library to $20k a month in revenue
Rik Schennink created Pintura, a JavaScript Image Editing library and sells it on his personal website.
He’s recently passed $20,000 a month in revenue, so he answered some questions on how he did it on IndieHackers.
Unfortunately, Gmail likes to filter our email in the Promotions tab!
Therefore, don’t forget to move our emails to Primary so you don’t miss them.
Gmail users—move us to your primary inbox
On your phone? Hit the 3 dots at the top right corner, click "Move to" then "Primary"
On desktop? Back out of this email then drag and drop this email into the "Primary" tab near the top left of your screen
A pop-up will ask you “Do you want to do this for future messages from quastor@substack.com” - please select yes
Apple mail users—tap on our email address at the top of this email (next to "From:" on mobile) and click “Add to VIPs”
Serverless Architectures
This is an amazing blog post that goes into the depths of Serverless computing. The post is from 2018, so some of the specific numbers and services may be outdated, but the concepts are all still relevant.
Here’s the summary
Severless encompasses two different, but overlapping areas:
Backend as a Service (BaaS) - A Serverless application will incorporate third-party, cloud-hosted applications to manage server-side logic and state.
Server-side logic is not written by the developer. Instead, the developer communicates with a third party service through their API.
Rather than managing his own database, he’ll utilize a cloud database like Google Cloud Firestore. Instead of handing user authentication, he’ll use a service like AWS Cognito.
These Backend as a Service offerings from cloud providers are what started the Serverless trend.
Functions as a Service (FaaS) - With FaaS, server-side logic is still written by the developer, but it’s run in stateless compute containers that are event-triggered, ephemeral, and fully managed by a third party.
For example, let’s say you’re running a video hosting site on AWS. You allow users to upload videos and store them in S3.
You want to minimize the dollars you pay to Mr. Bezos, so you decide to compress all the videos to reduce the amount of storage you’re using.
You can set up an Lambda function (AWS’s FaaS product) that gets notified anytime a video gets uploaded to S3. Your lambda function can then compress the video and then terminate.
The main point of FaaS is that you can run backend code without having to manage your own server systems or long-lived server applications.
Deployment is incredibly simple since all you have to do is upload the code for your function to the cloud provider.
FaaS providers are also very flexible with what language your code is written in.
For example, AWS Lambda natively supports Python, NodeJS, Ruby, any JVM language, Go, PowerShell, C# and provides a runtime API that allows you to use any additional programming language.
FaaS functions are event-driven. Your FaaS function will be inactive (and you won’t be charged for anything) until an event triggers your function to execute. Your function will then complete some action, send back a response and then terminate.
The triggering event can be an inbound HTTP request, or you can configure your FaaS function to respond to things like an update in your database or even subscribe to your messaging queue.
Stateless
FaaS functions have significant restrictions when it comes to local state (variables stored in memory or data stored on disk).
You do have such storage available, but you should not assume that the state from one invocation of a FaaS function will be available to another invocation of the same function.
For this reason, FaaS functions are often described as stateless, but it’s more accurate to say that any state of a FaaS function that is required to be persistent needs to be externalized outside of the FaaS function instance.
If you want a state-oriented FaaS function, then you should write the state to a cloud database.
Execution Duration
FaaS functions are limited in how long your function can run when invoked.
For example, AWS Lambda limits your FaaS functions to 15 minutes. If your function is still running after 15 minutes, then AWS will automatically terminate it.
Therefore, if you have long-lived tasks then you may have to chain together several FaaS functions to stay under the time restriction.
Startup Latency and Cold Starts
When your event first fires, your cloud provider has to go through a series of steps to get your FaaS function up and running.
They have to allocate a server for you, create a container instance, start the function host process, etc.
The amount of time this takes (the latency you experience) depends on the language you’re using, how many libraries you’ve imported, how much code you have, the configuration of your FaaS function, and a ton of other factors.
The total time between the first event firing to your FaaS code actually running is known as the cold start time. Cold start times can range from a few milliseconds to several seconds.
After your FaaS function finishes executing it’s code, your cloud provider will keep the instance used running for 20-30 minutes longer (the exact time is not known).
If another event fires while the instance is still alive, then your FaaS function can start executing code immediately. This is known as a warm start and it can result in far lower latencies vs. a cold start.
If your FaaS functions are getting called a couple of times a day, at completely different time intervals, then you’ll have a far larger impact from cold starts than if you were constantly calling your FaaS function.
Therefore, to avoid cold starts, you may have to work on a “pre-warm” strategy, where you invoke your cloud functions periodically so that your cloud provider continuously allocates containers for them. You can read more about pre-warm strategies here.
Be sure to check out the blog post for the full analysis!
Also, if you’re interested in an in-depth comparison of the three largest FaaS providers (AWS, Google and Azure), check this out!
Tech Snippets
Bootstrapping a JavaScript Image Editor library to $20,000 a month in revenue
Pintura is a JavaScript Image Editing library that allows developers to easily embed mobile-friendly image editing tools into their products.
The library is maintained by a solo developer, Rik Schennink, and he’s recently managed to hit $20,000 in monthly revenue (with nearly all of it being profit).
Pintura is used by over 1000 customers, including companies like Dropbox, Square and ConvertKit.
Rik recently did an AMA on IndieHackers where he talked about how he built his business.
Some tips he gave out were
Find a popular product and make it 10x better - A common fear founders have is that they won’t be able to find product-market fit. Well, if you start with a popular product and make it better, then you’ll already have a solid base of potential customers.
Focus on user experience to differentiate - There are many free, open source tools that compete with Pintura. However, none of them have a UX that’s anywhere near as good as Pintura’s.
Put extra effort on marketing materials when launching - When launching a product, make sure you have top-notch photos and copy writing. If you can’t design a nice landing page, consider hiring a designer.
Check out the full AMA here.
A list of PAGNIs (features that you’ll probably need)
YAGNI is a famous acronym that stands for You Aren’t Going to Need It. The principle behind YAGNI is to not waste time adding features that’ll be used later.
Instead, focus on shipping and deal with issues/feature requests when they become necessary.
Simon WIllison recently wrote an interesting blog post on PAGNIs, things that you will probably need and should consider adding. Here’s the list…
A kill-switch for your mobile apps - If you’re building a mobile app, make sure to ship a kill-switch feature: a mechanism by which you can cause older versions of the application to show a “you must upgrade to continue using this application” screen when the app starts up.
Automated deploys - Setting up automated deploys with something like Github Actions takes a few minutes but pays off instantly.
Continuous Integration (and a test framework) - Introducing a test framework at the start of your project is much easier than introducing it halfway through.
API Pagination - Never build an API endpoint that isn’t paginated. Any time you think “there will never be enough items in this list for it to be worth pagination”, one of your users will prove you wrong.
Detailed API Logs - If you’re building an API, having a mechanism that provides detailed logs is invaluable. It’s an inexpensive way of maintaining a complete record of what happened with your application.
Check out Simon’s full blog post for all the details!
Interview Question
Given an integer n
, return the least number of perfect squares that sum to n
.
Here’s the question in LeetCode.
We’ll send the solution in our next email, so make sure you move our emails to primary, so you don’t miss them!
Gmail users—move us to your primary inbox
On your phone? Hit the 3 dots at the top right corner, click "Move to" then "Primary"
On desktop? Back out of this email then drag and drop this email into the "Primary" tab near the top left of your screen
A pop-up will ask you “Do you want to do this for future messages from quastor@substack.com” - please select yes
Apple mail users—tap on our email address at the top of this email (next to "From:" on mobile) and click “Add to VIPs”
Previous Question
As a refresher, here’s the last question
A robot is located at the top-left corner of a mxn
grid.
The robot can only move either down or right at any point in time.
The robot is trying to reach the bottom-right corner of the grid.
How many possible unique paths are there?
Here’s the question in LeetCode.
Solution
The easiest way to solve this question is with combinatorics, specifically permutations.
A permutation is a way of counting the number of ways you can order n
distinct objects.
If you want to order 5 people in a line, then you have 5 choices for the first spot in the line.
Then, you have 4 choices for the second spot.
3 choices for the third spot.
2 choices for the fourth spot.
And 1 choice for the last spot.
The number of orderings is therefore 5 * 4 * 3 * 2 * 1
or 5!
.
Going back to our question, let’s take the example where m = 4
and n = 8
.
In other words, we will have to make 3 moves down and 7 moves right in order to reach the bottom right corner.
You can imagine this as 3 downs and 7 rights, or 3 Ds and 7 Rs, and we have to figure out the total number of orderings of downs and rights.
You can represent this in a string as “DDDRRRRRRR” with 3 Ds and 7 Rs.
Our goal is to find the total number of orderings for that string.
Since we have 10 total items (3 + 7), then the total number of orderings is 10!
.
However, each D is not distinct from another D. The same applies for the Rs. Each R is not different from another R.
Therefore, solely doing 10!
results in overcounting.
How much are we overcounting by?
Well, we’re double counting by the number of D permutations (which is 3!) and overcounting by the number of R permutations (which is 7!).
Therefore, we can divide 10! by (3! * 7!) to get our answer.
Generalizing this, the formula we can use for our answer is
((m - 1) + (n - 1))! / ((m - 1)! * (n - 1)!)
Here’s the Python 3 code…