The goal of this article is to introduce you to the top 5 serverless AWS services which I think every tech-founder or Indie Hacker should know. This is not a deep dive on these services and I want to explain them in a high level fashion and tell you why they are worth using and learning. With these services you are able to build almost every web- and mobile application you can think of. Almost all high level programming languages such as Python, TypeScript, JavaScript and Java can be used with these services. So, let’s jump straight in.
Amplify CLI
I start with the obvious one, Amplify. Important to note is, that there are two (almost three) “services” called Amplify within AWS. We have to distinguish between:
- Amplify CLI: Bootstrap your backend
- Amplify Libraries (e.g. JS libraries): Frontend libraries for accessing AWS resources
- Amplify Console: CI/CD pipeline for frontend and backend
We talk about Amplify CLI here. With the Amplify CLI you are able to bootstrap your backend with a few commands within the Command Line Interface. Amplify has several categories you can add, for example these are:
- API: AppSync GraphQL or REST API Gateway
- Authentication: Cognito
- Storage: DynamoDB, S3
- Functions: Lambda
- Hosting: S3 & CloudFront
With a few commands you are able to build fullstack applications with a guided CLI.
The main benefit in my eyes is the graphql-tranform library. This library enables you to create your data schema with custom annotations like model or connection and the library transforms this schema to a valid GraphQL schema and at the same time creates CloudFormation templates for creating your backend resources such as DynamoDB tables, Cognito connections, etc.
Take this schema as an example:
type Holding @model {
id: ID!
ISIN: String!
currentPrice: Float! @funtion(name: priceResolver)
}
It creates the type Holding. The model annotation creates a table in DynamoDB with id as the primary key. currentPrice will be resolved by the lambda function priceResolver.
The main drawback in my eyes is that you are not as flexible as with building up your infrastructure with a typical IaC solution like CDK or Terraform. Since a lot of magic is happening with Amplify you will likely run into some issues, especially when you are working with several team environments and lambda layers.
Nevertheless, it is a great tool, it has a great community and the team is still developing the services further. The backend of deposur was completely bootstrapped with Amplify. If you want to learn one service, learn this one!
AppSync
This brings us to the next service, AppSync. AppSync is a fully managed GraphQL API by AWS. GraphQL enables you as a developer to get exactly the data you need without worrying about fetching too much or too less data overfetching & underfetching). In general you have three main functions within AppSync. These are Queries, Mutations and Subscriptions.
With Queries you can query data from different data sources. That means that you can have a type Holding for example which gets data from different sources. Lets take our example schema again:
type Holding @model {
id: ID!
ISIN: String!
currentPrice: Float! @funtion(name: priceResolver)
}
The attribute ISIN is a string which comes from DynamoDB, the currentPrice gets resolved by a Lambda function called priceResolver. Lambda resolvers give you the main flexibility here. In the lambda function you can have as much customised code as you need (request two different APIs, clean & preprocess data, …) and respond with exactly this data you need in your application. It doesn’t matter where your data lives, AppSync gives you the opportunity of resolving it under one hood for the application. This is a great deal of flexibility.
You can query your data then with:
query MyQuery {
getHolding(ISIN: "DE0005190003") {
ISIN
currentPrice
}
}
And it returns the following code:
{
"data": {
"getHolding": {
"ISIN": "DE0005190003",
"currentPrice": 90.94999694824219,
}
}
}
With Mutations you can change your data and update it. Subscriptions give you the ability to live update your data.
Why to learn AppSync as a founder?
Why should you learn AppSync as a founder? First of all you get the main benefit of using GraphQL which is working with type safety and giving the frontend developer the power of requesting exactly the data it needs. Secondly, you have so much flexibility by connecting every data source you need. Third, you let AWS doing most of the work. You have one single endpoint and no hassle with parsing requests and connecting different AWS services together. It will reduce your development time immensely.
Lambda
Now let’s go back to the roots, Lambda. Lambda is the most common known serverless service. When people talk about serverless many people just refer to lambda. The basic idea behind the lambda service is to run your code without ever thinking about infrastructure. AWS’s promise is just that your code will be executed. Lambda supports several runtimes such as Python, JavaScript, Java, C#, Rust, Go and many more. One of the latest features is that custom docker containers can be used as a runtime and that pricing happens every millisecond instead of every 100 ms. The maximum runtime of lambda is 15 minutes, take that into consideration when building your application. The only infrastructure setting is the memory setting.
Pricing: Lambda is cheap. The first million requests per month are free. From that point on it will be calculated based on the minutes the lambda runs.
Recommendations:
- Always increase memory to about 4 GB, the faster it runs the cheaper it is. There is a great library to test this assumption
- Declare all your static variables such as DynamoDb from boto3 outside of your handler function -> Decreases cold starts
- Keep cold starts in mind when designing your application. If you need certain response times pre-heat your lambda or provision concurrency before.
Why learn lambda as a founder?
Lambda gives you the ability of executing code without ever worrying about infrastructure. The pricing is really awesome. Your whole application can be based on Lambda. It depends on the use case and the overall architecture (go event-driven!) but most of the applications I know can be easily adopted to several lambda functions. You just pay on-demand, you have small development cycles and the deployment is way easier.
Cognito
Let’s look at Authentication. Cognito is AWS’s service for authentication and authorisation. You can use it for Sign-Up and Sign-In purposes, fine granular user group control and even federated logins such as Facebook, Google & Apple Login. If you start your SaaS business you really want to give users a seamless authentication experience and offer social logins. This is easily possible with Cognito. Cognito differentiates User Pools & Identity Pools.
User Pools: Directory of users with Sign-Up, Sign-In and federated login capability.
Identity Pools: Identity pools are for creating unique identities for users and giving them access to other AWS services. This is needed for example for generating temporary credentials for anonymous users.
For the typical authentication capabilities you will use User Pools.
Pricing: You pay per monthly active users and the first 50k are free!
Why?
Give your users the seamless authentication experience they deserve. With Cognito you are able to do that at any scale. You can customise your Sign-Up and Sign-In pages however you want or you can even use pre-built ones by AWS. With federated logins you are able to offer on-click logins.
DynamoDB
The last service I want to introduce is DynamoDB. DynamoDB is a fully-managed NoSQL database which is highly scalable and highly available. I build almost every use case and project now with DynamoDB and I am a huge fan of it.
The structure of DynamoDB is pretty similar to every other database. You have:
- Tables: A table has one or more items
- Items: That is a collection of different attributes
- Keys: You distinguish between primary and sort keys
- Streams: You can have streams for triggering something (e.g. a lambda function) on every update on a table
DynamoDB is basically a key, value database where you can store different datatypes as a value. A value can also be a nested list or nested list of objects (like JSON). A DynamoDB Item looks like that:
{
"ISIN":{
"S":"DE0005190003"
},
"name":{
"S":"BAY.MOTOREN WERKE AG ST"
}
}
The key is the column name (ISIN) and the value is the data type (S: String) with the actual value. The item can also be shown with a typical JSON syntax:
{
"ISIN": "DE0005190003",
"name": "BAY.MOTOREN WERKE AG ST"
}
Most SDKs are able to parse them into the correct DynamoDB representation.
DynamoDB has some great features for increasing the performance even more such as Global Tables, DynamoDB Accelerator, Point-In-Time recovery and many more. When designing DynamoDB tables it is always important to keep you access patterns in mind. Rick is doing a wonderful job explaining DynamoDB strategies in this video .
Pricing: Pricing is based on reading, writing and storing data. Again, if you just start out your SaaS product the price is so low that it won’t cost you a Dollar. If you have a predictable amount of read and write requests you can even use provisioned capacity which is even cheaper.
Final Words
Thats it! These are the services you should consider when building your application. All of these services have the great benefit of developing your application in a cloud-native way. These are:
- Risk-Free. If nobody uses your app you won’t be charged. That minimises your risk immensely.
- Scalable. If you acquire a lot of users AWS will scale with your users.
- Secure. You won’t secure your servers and applications as good as AWS engineers do. Concentrate on your business logic and let the boring stuff AWS do.
This was a high level overview of course and was not intended as a deep dive for the single services or to be complete. There are many more great services AWS offers. If you want to know more about building your SaaS service on AWS follow my Twitter !