Clients vs resources

boto3 · Essentials · 10 min

Choosing the right interface determines how you read the AWS docs and how future-proof your code is.

boto3 offers two interfaces.

A client (boto3.client("s3")) maps one-to-one onto the service API: every AWS operation is a method in snake_case (ListBuckets becomes list_buckets), parameters are keyword arguments with the API's exact names (Bucket=, Key=), and responses are plain dicts mirroring the API's JSON, plus a ResponseMetadata entry with the HTTP status and request id. Every service and every operation is available, as soon as AWS releases it.

A resource (boto3.resource("s3")) is an object-oriented layer: s3.Bucket("name").objects.all() yields ObjectSummary objects with attributes, and collections paginate automatically. It's pleasant, but only some services have resources (S3, DynamoDB, EC2, SQS, IAM and a few others), and AWS has stated that no new features will be added to resources. New code should generally use clients; the resource API remains fine where it's already used, notably DynamoDB's Table object.

You can reach the client behind a resource with resource.meta.client.

Reading the docs: each service's client reference lists every method with request syntax and response structure. Tools like boto3-stubs (mypy-boto3) add type hints and editor autocompletion for those dicts.

Create clients once and reuse them: creating one loads the service model and costs real time.

Example

import boto3

s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="demo-reports-2026")
s3.put_object(Bucket="demo-reports-2026", Key="a.txt", Body=b"hello")

# Client: API operations, dict responses
resp = s3.list_objects_v2(Bucket="demo-reports-2026")
print(resp["ResponseMetadata"]["HTTPStatusCode"])          # 200
print([o["Key"] for o in resp.get("Contents", [])])         # ['a.txt']

# Resource: objects and collections (feature-frozen interface)
bucket = boto3.resource("s3", region_name="us-east-1").Bucket("demo-reports-2026")
for obj in bucket.objects.all():
    print(obj.key, obj.size)                                 # a.txt 5

print(bucket.meta.client.meta.service_model.service_name)   # s3

Remember

  • Clients: one method per API operation, dict in and dict out
  • Resources: object-oriented, but limited to some services and feature-frozen
  • Prefer clients for new code; DynamoDB's Table resource is still common
  • Create clients once and reuse them

Watch out for

  • Calling boto3.client(...) inside a hot loop for every request.

Check yourself

  1. Which is true of the boto3 resource interface today?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: boto3.amazonaws.com/v1/documentation/api/latest/guide/clients.html