Attribute types and boto3

Amazon DynamoDB · Essentials · 10 min

Type mismatches, especially floats and Decimals, are the first errors every Python developer hits.

DynamoDB attribute values have one of these types:

  • scalars: S (string), N (number), B (binary), BOOL, NULL
  • documents: M (map, a nested object) and L (list, any mix of types)
  • sets: SS, NS, BS (unique strings, numbers or binaries; never empty)

Key attributes must be S, N or B. Numbers are sent as strings and stored with up to 38 digits of precision, so they are exact decimals rather than floats.

boto3 has two interfaces. The low-level client speaks the wire format, where every value is wrapped with its type: {"total": {"N": "35"}}. The higher-level resource (boto3.resource("dynamodb").Table(...)) converts automatically between Python and DynamoDB types:

  • str to S, bool to BOOL, None to NULL, dict to M, list to L, set to a set type, bytes to B
  • numbers come back as decimal.Decimal, and you must send int or Decimal, not `float`

Passing a float raises TypeError: Float types are not supported. Convert with Decimal(str(x)), or keep money in integer cents. When returning items as JSON from an API, convert Decimals back (e.g. a custom default= in json.dumps).

The resource interface is the most readable for scripts; the client offers every API and is required for some newer features.

Example

from decimal import Decimal
import boto3

table = boto3.resource("dynamodb").Table("Orders")

table.put_item(Item={
    "customer_id": "c1", "order_id": "2025-03-01#A17",
    "total": Decimal("35.90"),          # not 35.90 (float raises TypeError)
    "paid": True,
    "items": [{"sku": "pen", "qty": 2}],  # list of maps
    "tags": {"gift", "express"},          # string set
})
item = table.get_item(Key={"customer_id": "c1", "order_id": "2025-03-01#A17"})["Item"]
print(item["total"], type(item["total"]).__name__)   # 35.90 Decimal
print(item["items"][0]["qty"])                       # 2  (also a Decimal)

Remember

  • Types: S, N, B, BOOL, NULL, M, L and the sets SS/NS/BS
  • Key attributes must be string, number or binary
  • The boto3 resource maps Python types automatically; numbers come back as Decimal
  • Never send floats: use Decimal or integers

Watch out for

  • Passing a Python float to put_item and getting 'Float types are not supported'.

Check yourself

  1. Why does boto3's Table.put_item reject the value 9.99 (a float)?

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

Official docs: docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html