DynamoDBBoto3FastAPI

    Building First CRUD API with AWS DynamoDB, FastAPI and Boto3

    Introduction After learning Amazon EC2, IAM, S3 and API Gateway, I wanted to explore Amazon DynamoDB, AWS's fully managed NoSQL database service. Instead of reading only the docume...

    Aug 4, 2026
    5 min read
    20 views
    Building First CRUD API with AWS DynamoDB, FastAPI and Boto3

    Introduction

    After learning Amazon EC2, IAM, S3 and API Gateway, I wanted to explore Amazon DynamoDB, AWS's fully managed NoSQL database service.

    Instead of reading only the documentation, I decided to build a small FastAPI application that performs basic CRUD operations using boto3. During this process I learned how DynamoDB tables are designed, how Global Secondary Indexes work, how AWS authentication is configured locally, and how pagination works.

    In this article, I'll walk through everything I learned while building my first DynamoDB application.


    What is Amazon DynamoDB?

    Amazon DynamoDB is a fully managed NoSQL database service provided by AWS.

    Unlike PostgreSQL or MySQL, DynamoDB does not require you to manage servers, install database software, or configure replication. AWS handles all of that automatically.

    DynamoDB supports both Key-Value and Document data models, making it suitable for applications that require high performance and automatic scaling.

    Some common use cases include:

    • User profiles
    • Shopping carts
    • Session storage
    • Gaming leaderboards
    • IoT applications

    Creating an IAM User

    Before connecting Python with DynamoDB, I created an IAM user that has permission to access DynamoDB.

    For learning purposes, I attached the managed policy:

    text
    AmazonDynamoDBFullAccess

    After creating the IAM user, AWS generated:

    • Access Key ID
    • Secret Access Key

    These credentials are required to authenticate from my local machine.


    Configuring AWS CLI

    After installing the AWS CLI, I configured it using:

    bash
    aws configure

    AWS asks for four values:

    text
    AWS Access Key ID
    AWS Secret Access Key
    Default region name
    Default output format

    Example:

    text
    AWS Access Key ID: AKIAxxxxxxxxxxxxxxxx
    AWS Secret Access Key: xxxxxxxxxxxxxxxxxxxxxxxxx
    Default region name: us-east-1
    Default output format: json

    The credentials are stored locally.

    On Windows:

    text
    C:\Users\<username>\.aws\credentials

    After configuration, boto3 automatically reads these credentials.

    Connecting to DynamoDB becomes very simple.

    python
    import boto3
    
    dynamodb = boto3.resource(
        "dynamodb",
        region_name="us-east-1"
    )

    Creating the Users Table

    For this project, I created a simple Users table.

    The primary key is:

    text
    id

    I also created two Global Secondary Indexes:

    • EmailIndex
    • UsernameIndex

    These indexes allow users to be searched using either email or username.


    Understanding AttributeDefinitions

    When creating a DynamoDB table, AWS only needs to know the data type of attributes that are used as keys.

    Example:

    python
    AttributeDefinitions=[
        {
            "AttributeName": "id",
            "AttributeType": "S"
        },
        {
            "AttributeName": "email",
            "AttributeType": "S"
        },
        {
            "AttributeName": "username",
            "AttributeType": "S"
        }
    ]

    Notice that attributes such as first_name, last_name, and role are not included.

    That's because DynamoDB is schema-less. Only attributes used as the table's primary key or index keys must be defined when the table is created.

    Available attribute types are:

    TypeMeaning
    SString
    NNumber
    BBinary

    Understanding KeySchema

    Every DynamoDB table requires a primary key.

    A primary key can consist of:

    • Partition Key only
    • Partition Key and Sort Key

    AWS uses two names internally.

    text
    HASH

    represents the Partition Key.

    text
    RANGE

    represents the Sort Key.

    Example:

    python
    KeySchema=[
        {
            "AttributeName": "id",
            "KeyType": "HASH"
        }
    ]

    This means that id is the partition key.


    Understanding Global Secondary Indexes

    A table can have only one primary key, but applications often need to search data in multiple ways.

    For example:

    • Find user by ID
    • Find user by email
    • Find user by username

    To support these access patterns efficiently, DynamoDB provides Global Secondary Indexes (GSIs).

    Example:

    python
    GlobalSecondaryIndexes=[
        {
            "IndexName": "EmailIndex",
            "KeySchema": [
                {
                    "AttributeName": "email",
                    "KeyType": "HASH"
                }
            ],
            "Projection": {
                "ProjectionType": "ALL"
            }
        }
    ]

    Understanding Projection

    Projection determines which attributes are copied from the main table into the index.

    ProjectionType = ALL

    python
    Projection={
        "ProjectionType": "ALL"
    }

    Every attribute is copied into the index.

    This means querying the index returns the complete user document without needing another read.

    ProjectionType = KEYS_ONLY

    Only the primary key and index key are stored.

    ProjectionType = INCLUDE

    Only selected non-key attributes are copied into the index.


    Creating the Table

    python
    dynamodb.create_table(
        TableName="Users",
        ...
    )

    The complete source code is available in my GitHub Gist.


    Building CRUD Operations

    After creating the table, I built a simple FastAPI application.

    The API supports:

    text
    POST   /users
    GET    /users
    GET    /users/{id}
    PUT    /users/{id}
    DELETE /users/{id}

    Each endpoint maps directly to a DynamoDB operation.

    APIDynamoDB Method
    Createput_item()
    Readget_item()
    Updateupdate_item()
    Deletedelete_item()
    Listscan()

    Pagination with LastEvaluatedKey

    Unlike SQL databases, DynamoDB does not use OFFSET.

    Instead, it returns a LastEvaluatedKey.

    If more items are available, this value can be passed back using ExclusiveStartKey to continue reading from where the previous request stopped.

    Example:

    python
    response = table.scan(
        Limit=10
    )
    
    last_evaluated_key = response.get("LastEvaluatedKey")

    Things I Learned

    While building this project, I learned several important DynamoDB concepts.

    • DynamoDB does not automatically generate IDs.
    • UUIDs should be generated by the application.
    • Global Secondary Indexes improve query flexibility but do not enforce uniqueness.
    • Scan reads the entire table and should be used carefully.
    • Query is preferred whenever possible.
    • Reserved keywords such as role require ExpressionAttributeNames.
    • Pagination uses LastEvaluatedKey instead of SQL-style offsets.
    • DynamoDB tables are schema-less, so only key attributes are defined during table creation.

    Source Code

    The complete FastAPI CRUD project is available here:

    GitHub Gist

    https://gist.github.com/jobissjo/b5b98f485fc34c6b81c0e6e5664ad64b


    Conclusion

    Building this small project helped me understand the core concepts of DynamoDB far better than reading documentation alone. It also showed me how differently DynamoDB approaches data modeling compared to relational databases.

    In the next part of my learning journey, I plan to explore querying with Global Secondary Indexes, conditional expressions, transactions, sort keys, and single-table design.

    J
    Written by

    Jobi S S

    Portfolio

    admin

    Sharing technical insights, engineering concepts, and practical modern software development guides.

    Community Discussion

    Enjoyed this read? Show your support or share your thoughts.

    Comments (0)

    No comments yet. Be the first to comment!

    📬 Enjoyed this article?

    Get new posts on Django, FastAPI, and system design straight to your inbox. No spam — unsubscribe whenever you want.