DynamoDBClient
The DynamoDBClient is your connection to AWS. Configure it once, use it everywhere.
Key features
- Multiple credential sources (profile, env vars, explicit)
- Rate limiting built-in
- Local development support (DynamoDB Local, LocalStack)
- Set a default client for all models
Getting started
Basic setup
By default, the client uses the standard AWS credential chain:
- Environment variables (
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - Shared credentials file (
~/.aws/credentials) - Instance profile (EC2, ECS, Lambda)
Using a profile
Explicit credentials
"""Client with explicit credentials."""
from pydynox import DynamoDBClient
# Hardcoded credentials (not recommended for production)
client = DynamoDBClient(
access_key="AKIAIOSFODNN7EXAMPLE",
secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
region="us-east-1",
)
# With session token (for temporary credentials)
client = DynamoDBClient(
access_key="AKIAIOSFODNN7EXAMPLE",
secret_key="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
session_token="FwoGZXIvYXdzEBY...",
region="us-east-1",
)
Warning
Don't hardcode credentials in your code. Use environment variables or profiles instead.
Local development
Default client
Instead of passing a client to each model, set a default client once:
"""Setting a default client for all models."""
from pydynox import DynamoDBClient, Model, ModelConfig, set_default_client
from pydynox.attributes import StringAttribute
# Create and set default client once at app startup
client = DynamoDBClient(region="us-east-1", profile="prod")
set_default_client(client)
# All models use the default client automatically
class User(Model):
model_config = ModelConfig(table="users")
pk = StringAttribute(hash_key=True)
name = StringAttribute()
class Order(Model):
model_config = ModelConfig(table="orders")
pk = StringAttribute(hash_key=True)
total = StringAttribute()
# No need to pass client to each model
user = User(pk="USER#1", name="John")
user.save() # Uses the default client
How it works
When a model needs a client, it looks in this order:
model_config.client- if you passed one explicitly- Default client - set via
set_default_client() - Error - if neither is set
Override per model
You can still use a different client for specific models:
# Default for most models
set_default_client(prod_client)
# Different client for audit logs
audit_client = DynamoDBClient(region="eu-west-1")
class AuditLog(Model):
model_config = ModelConfig(
table="audit_logs",
client=audit_client, # Uses this instead of default
)
pk = StringAttribute(hash_key=True)
Rate limiting
Control how fast you hit DynamoDB. Useful to avoid throttling or stay within budget.
"""Client with rate limiting."""
from pydynox import DynamoDBClient
from pydynox.rate_limit import AdaptiveRate, FixedRate
# Fixed rate: constant throughput
client = DynamoDBClient(
rate_limit=FixedRate(rcu=50, wcu=25),
)
# Adaptive rate: adjusts based on throttling
client = DynamoDBClient(
rate_limit=AdaptiveRate(max_rcu=100, max_wcu=50),
)
See the rate limiting guide for more details.
Constructor options
| Parameter | Type | Default | Description |
|---|---|---|---|
region |
str | None | AWS region (e.g., "us-east-1") |
profile |
str | None | AWS profile name from ~/.aws/credentials |
access_key |
str | None | AWS access key ID |
secret_key |
str | None | AWS secret access key |
session_token |
str | None | AWS session token (for temporary credentials) |
endpoint_url |
str | None | Custom endpoint (for local development) |
rate_limit |
FixedRate or AdaptiveRate | None | Rate limiter |
Methods
ping()
Check if the client can connect to DynamoDB.
get_region()
Get the configured region.
Low-level operations
The client has methods for direct DynamoDB operations. Each sync method has an async version with async_ prefix:
| Sync | Async | Description |
|---|---|---|
put_item(table, item) |
async_put_item(table, item) |
Save an item |
get_item(table, key) |
async_get_item(table, key) |
Get an item by key |
delete_item(table, key) |
async_delete_item(table, key) |
Delete an item |
update_item(table, key, updates) |
async_update_item(table, key, updates) |
Update an item |
query(table, key_condition, ...) |
async_query(table, key_condition, ...) |
Query items |
batch_write(table, put_items, delete_keys) |
- | Batch write |
batch_get(table, keys) |
- | Batch get |
transact_write(operations) |
- | Transaction |
All operations return metrics (duration, RCU/WCU consumed). See observability for details.
Consistent reads
get_item and query support strongly consistent reads:
"""Consistent read with low-level client."""
from pydynox import DynamoDBClient
client = DynamoDBClient(region="us-east-1")
# get_item with consistent read
item = client.get_item(
"users",
{"pk": "USER#123", "sk": "PROFILE"},
consistent_read=True,
)
# query with consistent read
for item in client.query(
"users",
key_condition_expression="#pk = :pk",
expression_attribute_names={"#pk": "pk"},
expression_attribute_values={":pk": "USER#123"},
consistent_read=True,
):
print(item)
By default, reads are eventually consistent. Pass consistent_read=True when you need the latest data.
See async support for more details on async operations.
Most of the time you'll use the Model ORM instead of these methods directly.
Credential priority
When multiple credential sources are available, the client uses this order:
- Explicit credentials (
access_key,secret_key) - Profile (
profile) - Environment variables
- Default credential chain (instance profile, etc.)
Tips
- Set
set_default_client()once at app startup - Use profiles for local development
- Use instance profiles in production (no credentials in code)
- Add rate limiting if you're doing bulk operations
boto3 vs pydynox
What we support today
| Feature | boto3 | pydynox |
|---|---|---|
| Environment variables | ✅ | ✅ |
| AWS profiles | ✅ | ✅ |
| Explicit credentials | ✅ | ✅ |
| Session token | ✅ | ✅ |
| Custom endpoint | ✅ | ✅ |
| Region config | ✅ | ✅ |
| Rate limiting | ❌ | ✅ |
What's coming
| Feature | boto3 | pydynox | Coming soon |
|---|---|---|---|
| Session object | ✅ | ❌ | 🚧 |
| Assume role | ✅ | ❌ | 🚧 |
| STS credentials | ✅ | ❌ | 🚧 |
| Custom retry config | ✅ | ❌ | 🚧 |
| Request/response hooks | ✅ | ❌ | 🚧 |
Workaround for now
If you need assume role or STS, get temporary credentials outside pydynox and pass them directly:
# Get credentials from STS (using boto3 or AWS CLI)
# Then pass them to pydynox
client = DynamoDBClient(
access_key=temp_credentials["AccessKeyId"],
secret_key=temp_credentials["SecretAccessKey"],
session_token=temp_credentials["SessionToken"],
)
Missing something?
Open a feature request on GitHub. We prioritize based on community feedback.