How to create DynamoDB table using Python Boto3

This post explains how to create a DynamoDB table using both DynamoDB.Client and DynamoDB.ServiceResource and explains difference between these two approaches.

Topics

What is DynamoDB ?

Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability. With DynamoDB, you can create database tables that can store and retrieve any amount of data and serve any level of request traffic. You can scale up or scale down your tables' throughput capacity without downtime or performance degradation.

Prerequisite

  • If you are using your computer to execute this code than make sure you have proper credentials set up, follow boto3 credentials to set up boto3 credentials.
  • If you are using Lambda function to execute this code than make sure role assigned to lambda function is having proper permissions.

Create DynamoDB table using Python Boto3

In this section we will use Python Boto3 SDK to create table in DynamoDB for storing movies data.

Each movie is having its distinct attributes like "title", "year" etc. Below is the sample item from the JSON file that will be stored in DynamoDB. You can download the sample file from here.

   
{
  "year": 2000,
  "title": "28 Days",
  "info": {
      "directors": ["Betty Thomas"],
      "release_date": "2000-02-08T00:00:00Z",
      "rating": 5.8,
      "genres": [
          "Comedy",
          "Drama"
      ],
      "image_url": "http://ia.media-imdb.com/images/M/MV5BMTYwMDA1NjAxMF5BMl5BanBnXkFtZTYwODc3MTU3._V1_SX400_.jpg",
      "plot": "A big-city newspaper columnist is forced to enter a drug and alcohol rehab center after ruining her sister's wedding and crashing a stolen limousine.",
      "rank": 3350,
      "running_time_secs": 6180,
      "actors": [
          "Sandra Bullock",
          "Viggo Mortensen",
          "Dominic West"
      ]
}  
   

Create DynamoDB table using DynamoDB.Client

Let's select year as partition key (HASH Key) and title as a sort key (RANGE key) and create the table as shown in below code snippet.

   
import boto3

client = boto3.client("dynamodb")

table_name = "sample-movie-table-client"

attribute_definitions = [
    {"AttributeName": "year", "AttributeType": "N"},
    {"AttributeName": "title", "AttributeType": "S"},
]

key_schema = [
    {"AttributeName": "year", "KeyType": "HASH"},
    {"AttributeName": "title", "KeyType": "RANGE"},
]

response = client.create_table(
    AttributeDefinitions=attribute_definitions,
    TableName=table_name,
    KeySchema=key_schema,
    BillingMode='PAY_PER_REQUEST'
    )

print(type(response))
print(dir(response))
  
 
Output
   
<class 'dict'>

['__class__', '__class_getitem__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__ior__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__or__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__ror__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
 

Create DynamoDB table using DynamoDB.ServiceResource

Now let's create the same table using DynamoDB.ServiceResource and notice the difference in returned response.

   
import boto3

dynamodb_resource = boto3.resource("dynamodb")

table_name = "sample-movie-table-resource"

attribute_definitions = [
    {"AttributeName": "year", "AttributeType": "N"},
    {"AttributeName": "title", "AttributeType": "S"},
]

key_schema = [
    {"AttributeName": "year", "KeyType": "HASH"},
    {"AttributeName": "title", "KeyType": "RANGE"},
]

response = dynamodb_resource.create_table(
    AttributeDefinitions=attribute_definitions,
    TableName=table_name,
    KeySchema=key_schema,
    BillingMode='PAY_PER_REQUEST'
    )

print(type(response))
print(dir(response))
 
Output
   
<class 'boto3.resources.factory.dynamodb.Table'>

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_injector', '_name', 'archival_summary', 'attribute_definitions', 'batch_writer', 'billing_mode_summary', 'creation_date_time', 'delete', 'delete_item', 'get_available_subresources', 'get_item', 'global_secondary_indexes', 'global_table_version', 'item_count', 'key_schema', 'latest_stream_arn', 'latest_stream_label', 'load', 'local_secondary_indexes', 'meta', 'name', 'provisioned_throughput', 'put_item', 'query', 'reload', 'replicas', 'restore_summary', 'scan', 'sse_description', 'stream_specification', 'table_arn', 'table_class_summary', 'table_id', 'table_name', 'table_size_bytes', 'table_status', 'update', 'update_item', 'wait_until_exists', 'wait_until_not_exists']
 

Difference between using DynamoDB.Client and DynamoDB.ServiceResource

So if you noticed the type of response returned by DynamoDB.Client is dictionary, while type of response returned by DynamoDB.ServiceResource is boto3.resources.factory.dynamodb.Table, which provides other useful methods like table_status , wait_until_exists etc. to interact with the created table.

Create DynamoDB table with PROVISIONED mode

In the above snippet tables were created in On-Demand Mode, where we passed BillingMode as PAY_PER_REQUEST. Now lets create the table for PROVISIONED mode. Change the ReadCapacityUnits and WriteCapacityUnits as per the requirements.

   
import boto3

dynamodb_resource = boto3.resource("dynamodb")

table_name = "sample-movie-table-resource"

attribute_definitions = [
    {"AttributeName": "year", "AttributeType": "N"},
    {"AttributeName": "title", "AttributeType": "S"},
]

key_schema = [
    {"AttributeName": "year", "KeyType": "HASH"},
    {"AttributeName": "title", "KeyType": "RANGE"},
]

response = dynamodb_resource.create_table(
    AttributeDefinitions=attribute_definitions,
    TableName=table_name,
    KeySchema=key_schema,
    BillingMode="PROVISIONED",
    ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
)

print(type(response))
print(dir(response))
 

Create DynamoDB table encrypted with AWS KMS Key

In the previous examples while creating the DynamoDB tables, SSESpecification parameter was not provided. Whenever this parameter is missing or disabled than server-side encryption is set to AWS owned key. Follow below code snippet to create table that is encrypted using AWS KMS.

   
import boto3

dynamodb_resource = boto3.resource("dynamodb")

table_name = "sample-movie-table-resource"

attribute_definitions = [
    {"AttributeName": "year", "AttributeType": "N"},
    {"AttributeName": "title", "AttributeType": "S"},
]

key_schema = [
    {"AttributeName": "year", "KeyType": "HASH"},
    {"AttributeName": "title", "KeyType": "RANGE"},
]

response = dynamodb_resource.create_table(
    AttributeDefinitions=attribute_definitions,
    TableName=table_name,
    KeySchema=key_schema,
    BillingMode="PROVISIONED",
    ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
      SSESpecification={
        'Enabled': True,
        'SSEType': 'KMS'
    },
)

print(type(response))
print(dir(response))
  
 

Category: Python