Skip to content

DynamoDBClient

The DynamoDBClient is the connection between your code and DynamoDB. It handles authentication, network calls, retries, and timeouts.

Why use it?

pydynox Models need a client to talk to DynamoDB. You can either:

  1. Set a default client once at app startup (recommended)
  2. Pass a client to each model's config

The client wraps the AWS SDK and adds features like rate limiting. It's built in Rust for speed.

Key features

  • Multiple credential sources (env vars, profile, SSO, AssumeRole)
  • Timeout and retry configuration
  • Rate limiting built-in
  • Local development support

Basic usage

"""Basic client setup."""

from pydynox import DynamoDBClient

# Use default credentials (env vars, instance profile, etc.)
client = DynamoDBClient()

# Check connection
if client.ping():
    print("Connected!")

By default, the client uses the AWS credential chain: env vars, profile, instance profile, EKS IRSA, etc.

Credentials

pydynox supports multiple ways to authenticate. Pick the one that fits your environment.

Environment variables

Set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. The client picks them up automatically. Good for local dev and CI/CD.

Profile (including SSO)

Use a named profile from ~/.aws/credentials or ~/.aws/config. Works with SSO profiles too. Good for local dev with multiple AWS accounts.

"""Client with AWS profile."""

from pydynox import DynamoDBClient

# Use a named profile from ~/.aws/credentials
client = DynamoDBClient(profile="prod")

# Or specify region with profile
client = DynamoDBClient(
    profile="prod",
    region="eu-west-1",
)

For SSO profiles, run aws sso login --profile my-profile first.

AssumeRole

Assume an IAM role in another account. Good for cross-account access or when you need temporary elevated permissions.

from pydynox import DynamoDBClient

# AssumeRole for cross-account access
client = DynamoDBClient(
    role_arn="arn:aws:iam::123456789012:role/MyRole",
    role_session_name="my-session",  # optional, defaults to "pydynox-session"
)

# With external ID (for third-party access)
client = DynamoDBClient(
    role_arn="arn:aws:iam::123456789012:role/MyRole",
    external_id="my-external-id",
)

Explicit credentials

Pass credentials directly. Good for testing or when credentials come from a secrets manager. Avoid hardcoding in production.

"""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. Use env vars or profiles instead.

EKS IRSA / GitHub Actions OIDC

These work automatically via the default credential chain. The env vars are injected by EKS or GitHub Actions. Just use DynamoDBClient() with no config. Good for Kubernetes and CI/CD pipelines.

Environment variables

pydynox uses the AWS SDK for Rust, which supports standard AWS environment variables:

Variable Description
AWS_ACCESS_KEY_ID Access key for authentication
AWS_SECRET_ACCESS_KEY Secret key for authentication
AWS_SESSION_TOKEN Session token for temporary credentials
AWS_REGION / AWS_DEFAULT_REGION Default region
AWS_PROFILE Profile name from ~/.aws/credentials
AWS_ENDPOINT_URL Custom endpoint (for local dev)
AWS_MAX_ATTEMPTS Max retry attempts
AWS_RETRY_MODE Retry mode: standard or adaptive

These work automatically - no code changes needed. Set them in your shell, .env file, or CI/CD pipeline.

export AWS_REGION=us-east-1
export AWS_PROFILE=my-profile

For the full list, see the AWS SDK environment variables documentation.

Configuration

Timeouts and retries

from pydynox import DynamoDBClient

# Set connection and read timeouts (in seconds)
client = DynamoDBClient(
    connect_timeout=5.0,  # 5 seconds to establish connection
    read_timeout=30.0,  # 30 seconds to read response
)

# Short timeouts for Lambda (fail fast)
lambda_client = DynamoDBClient(
    connect_timeout=2.0,
    read_timeout=10.0,
)
from pydynox import DynamoDBClient

# Configure max retry attempts
client = DynamoDBClient(
    max_retries=5,  # Retry up to 5 times on transient errors
)

# Combined with timeouts
client = DynamoDBClient(
    connect_timeout=5.0,
    read_timeout=30.0,
    max_retries=3,
)

Local development

"""Client for local development."""

from pydynox import DynamoDBClient

# Connect to DynamoDB Local
client = DynamoDBClient(endpoint_url="http://localhost:8000")

# Connect to LocalStack
client = DynamoDBClient(endpoint_url="http://localhost:4566")

Proxy

from pydynox import DynamoDBClient

# Use an HTTP/HTTPS proxy
client = DynamoDBClient(
    proxy_url="http://proxy.example.com:8080",
)

# With authentication
client = DynamoDBClient(
    proxy_url="http://user:password@proxy.example.com:8080",
)

Default client

Set a default client once instead of passing it to each model:

"""Setting a default client for all models."""

import asyncio
import os

from pydynox import DynamoDBClient, Model, ModelConfig, set_default_client
from pydynox.attributes import StringAttribute

# Create and set default client once at app startup
# Uses environment variables or default credential chain
client = DynamoDBClient(
    endpoint_url=os.environ.get("AWS_ENDPOINT_URL"),
)
set_default_client(client)


# All models use the default client automatically
class User(Model):
    model_config = ModelConfig(table="users")
    pk = StringAttribute(partition_key=True)
    sk = StringAttribute(sort_key=True)
    name = StringAttribute()


class Order(Model):
    model_config = ModelConfig(table="orders")
    pk = StringAttribute(partition_key=True)
    sk = StringAttribute(sort_key=True)
    total = StringAttribute()


async def main():
    # No need to pass client to each model
    user = User(pk="USER#1", sk="PROFILE", name="John")
    await user.save()  # Uses the default client


if __name__ == "__main__":
    asyncio.run(main())

Override per model if needed:

set_default_client(prod_client)

# Different client for audit logs
class AuditLog(Model):
    model_config = ModelConfig(table="audit_logs", client=audit_client)
    pk = StringAttribute(partition_key=True)

Rate limiting

"""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 rate limiting for details.

Constructor reference

Parameter Type Description
region str AWS region
profile str AWS profile name (supports SSO)
access_key str AWS access key ID
secret_key str AWS secret access key
session_token str Session token for temporary credentials
endpoint_url str Custom endpoint for local dev
role_arn str IAM role ARN for AssumeRole
role_session_name str Session name for AssumeRole
external_id str External ID for AssumeRole
connect_timeout float Connection timeout (seconds)
read_timeout float Read timeout (seconds)
max_retries int Max retry attempts
proxy_url str HTTP/HTTPS proxy URL
rate_limit FixedRate/AdaptiveRate Rate limiter

Methods

Most of the time you'll use Models instead of these methods directly. But they're useful for quick operations or when you need more control.

Table operations

Table operations follow the async-first pattern. Async methods have no prefix, sync methods have sync_ prefix.

Async (default) Sync Description
create_table(...) sync_create_table(...) Create a new table
table_exists(table) sync_table_exists(table) Check if table exists
delete_table(table) sync_delete_table(table) Delete a table
wait_for_table_active(table) sync_wait_for_table_active(table) Wait for table to be ready

See table operations for details.

Item operations

Item operations also follow async-first. Async methods have no prefix, sync methods have sync_ prefix.

Async (default) Sync Description
put_item(table, item, ...) sync_put_item(...) Save an item. Overwrites if key exists.
get_item(table, key) sync_get_item(...) Get item by primary key.
delete_item(table, key, ...) sync_delete_item(...) Delete item by primary key.
update_item(table, key, updates, ...) sync_update_item(...) Update specific attributes.
query(table, key_condition, ...) sync_query(...) Find items by partition key.
batch_write(table, put_items, delete_keys) sync_batch_write(...) Write up to 25 items at once.
batch_get(table, keys) sync_batch_get(...) Get up to 100 items at once.
transact_write(operations) sync_transact_write(...) Atomic multi-item write.
transact_get(gets) sync_transact_get(...) Atomic multi-item read.

Write methods (put_item, update_item, delete_item) support these optional parameters:

Parameter Description
condition_expression Condition that must be true for the write to succeed
expression_attribute_names Placeholders for reserved words
expression_attribute_values Placeholders for values
return_values_on_condition_check_failure If True, get the existing item on ConditionalCheckFailedException

Utility methods

Method Description
ping() Check if the client can connect to DynamoDB. Returns True or False.
get_region() Get the AWS region this client is configured for.

See async operations for examples and best practices.

Next steps