Database
why DynamoDB?
RDBs (Relational Databases) have been dominating the space since the 80s. Back then the main concern was storage, which is why RDBs are designed to avoid duplication by normalizing data. As you might guess, compute is now the major bottleneck. Thats where NoSQL databases like DynamoDB come in. They are:
1. faster and more reliable than RDBs
NoSQL databases are optimized for speed. You can retrieve items in miliseconds and don’t have to use expensive join operations.
2. dirt cheap and scale to the moon
You can use on-demand pricing or provision a database starting at 0.95$ per month. They can be scaled virtually unlimited since sharding allows them to scale horizontaly.
3. easier to use
DynamoDB is fully managed. You will never have to worry about scaling, provisioning, security, backups, rollbacks, and everything else that comes along with a self-hosted database.
Here is an awesome post discussing the strenghts and applications of NoSQL databases
If this is the first time leaving the world of RDBs, the whole mindset of building table schemas will be quite confusing. However, getting used to it is definetily worth it. Check out this webinar on modeling data before you continue.
setting up the database
Now we will set up your database. While we could have done so programmatically in our IAS (Infrastructure as Code) template, I prefer not accidentaly delete my database when playing around in the CLI (I am speaking from experience).
For this follow the steps shown in this Introduction to DynamoDB and manually create a table. Otherwise you can follow this video and deploy it locally, but you will have to change the code accordingly.
! choose one region which you will use for all of your ressources from now on !
Set the primary key as email and leave the search key empty, as this is how we are going to find our users. Also
add a string property called package_id
, more on this later.
interacting through code
Now lets dive into the code and see how we interact with our database.
Open backend/db.py
.
As you can see, we establish a connection to our table based on its name, which is saved in an environment variable.
Add the name you just created to .env
as “DYNAMO_TABLE_NAME”.
To do that we use the AWS SDK for Python called boto3. Boto3 has multiple ways of authenticating itself. If the AWS-CLI is configured, it will pull the credentials from there, otherwise we will need to provide them manually or set them as environment variables.
What follows is a bunch of helper functions, including the add_user
function I mentioned in the last chapter.
We use a “ConditionExpression” to only add a user, if he does not yet exist. As you can see, each new user has a “package_id” key set to 0. What it does is represent what package the user has bought. For example:
- 0: none
- 1: cheap package
- 2: expensive package
This can then be used to only allow the user to access certain content, if he has bought the according package.
Our payment_required
decorator does exactly this:
The check_user_status only returns True, if the user has a “package_id” that is higher than 0.
When the user buys a package, we change the “package_id” in his Item to the according number, using our
set_user_package
function. To see when and how it is invoked, read the next chapter on payments.