AWS Boto3: Clients vs Resources - DynamoDB
Tags: aws, python, dynamodb
Published: 2024-01-21 09:44:48

Recently, my colleague brought up the difficulty of using the [AWS SDK for Python (Boto3)](https://aws.amazon.com/sdk-for-python/) while working with DynamoDB, especially the cumbersome mapping of [`AttributeValue`](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_AttributeValue.html) objects on the `Table` operations. One of the easiest ways to get around this difficulty is to switch from the [clients](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html) interface to the [resources](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/resources.html) interface.


It is important to know the key difference between clients and resources. From the definition of the Boto3 documentation:

> Clients provide a low-level interface to AWS whose methods map close to 1:1 with service APIs.

#

> Resources represent an object-oriented interface to Amazon Web Services (AWS). They provide a higher-level abstraction than the raw, low-level calls made by service clients.


Let's quickly write a script to demonstrate the difference in the responses:

```python
import boto3
import simplejson

def print_items(desc, response):
    items = response.get('Items')
    items_json = simplejson.dumps(items, indent=4)
    print(f'{desc}:', items_json, sep='\n')

ddb_table_name = 'test'

# DynamoDB client
ddb_client = boto3.client('dynamodb')

# Scan the table
response = ddb_client.scan(TableName=ddb_table_name)
print_items('client', response)

print('\n')

# DynamoDB resource
ddb_resource = boto3.resource('dynamodb')

# Scan the table
response = ddb_resource.Table(ddb_table_name).scan()
print_items('resource', response)
```

The output:
```json
client:
[
    {
        "datetime": {
            "S": "2024-01-20T00:01:02"
        },
        "id": {
            "N": "1"
        },
        "data": {
            "L": [
                {
                    "M": {
                        "amount": {
                            "N": "40"
                        }
                    }
                },
                {
                    "M": {
                        "amount": {
                            "N": "56"
                        }
                    }
                }
            ]
        }
    }
]


resource:
[
    {
        "datetime": "2024-01-20T00:01:02",
        "id": 1,
        "data": [
            {
                "amount": 40
            },
            {
                "amount": 56
            }
        ]
    }
]
```

Notice the simplicity of the second output. The abstraction of the resources interface deserialized the low-level raw response of the AWS service API.

In most cases, the resources interface can be used over the low-level clients for the abstraction benefits. However, as stated at the top of the resources interface documentation: 

> The AWS Python SDK team does not intend to add new features to the resources interface in boto3". 

**Therefore, it is essential to compare both interfaces to determine whether the resources interface is sufficient for your use case.**

In a future post, I will explore another method to work with the AttributeValue maps in Boto3.

---
### Further reading
 - [DynamoDB - Boto3 1.34.23 documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html)
 -  [More info about resource deprecation? · boto/boto3 · Discussion #3563](https://github.com/boto/boto3/discussions/3563)
 - [simplejson · PyPI](https://pypi.org/project/simplejson/)