Skip to main content

dynamoxy

A typed, async DynamoDB ORM for Python, with a Rust core. Declare models with type hints (or pydantic) and get validated, atomic DynamoDB access, plus an in-memory DynamoDB for your tests.

import asyncio
from datetime import datetime

import dynamoxy
from dynamoxy import Attr, field, partition_key


class User(dynamoxy.Model, table="users"):
    user_id: Attr[str] = partition_key()
    email: Attr[str] = field(unique=True)
    name: Attr[str] = field(min_length=1)
    visits: Attr[int] = field(default=0)
    created_at: Attr[datetime] = dynamoxy.created_at()
    version: Attr[int] = dynamoxy.version()

    by_email = dynamoxy.GlobalIndex(partition_key=email)


async def main() -> None:
    async with dynamoxy.Client(region="eu-west-1") as client:  # or dynamoxy.testing.memory_client()
        await client.ensure_tables(User)
        users = client.repository(User)

        ada = await users.create(User(user_id="u1", email="ada@example.com", name="Ada"))
        await ada.increment(User.visits)  # atomic; `ada` is refreshed in place
        ada.name = "Ada Lovelace"
        await ada.save()  # only if nobody changed it meanwhile (version)

        try:
            await users.create(User(user_id="u2", email="ada@example.com", name="Imposter"))
        except dynamoxy.UniqueConstraintError as error:
            print(f"{error.field} is taken")

        found = await users.query(index=User.by_email, email="ada@example.com").first()
        print(found)


asyncio.run(main())

Highlights

  • Typed end to end. Fields are values on instances and typed paths on the class (User.visits > 3). Your type checker catches User(visits="3") and User.visits > "3".

  • Errors that tell you what to fix. DynamoDB's rules are checked before a request is sent:

    ValidationError: the transaction has 120 operations (guard items of unique attributes included); DynamoDB allows 100
    

    A refused write raises ItemAlreadyExistsError, VersionConflictError or UniqueConstraintError, not a bare ConditionalCheckFailedException.

  • Writes that mean what they say. create() never overwrites, save() checks the version, update() is atomic without a read.

  • Unique values, timestamps and versions are maintained for you.

  • Retries built in, with backoff and jitter. Nothing fails silently.

  • An in-memory DynamoDB for tests. No Docker, no AWS account. It refuses what DynamoDB refuses, simulates faults and answers in microseconds:

    dynamoxy.testing.inject_fault(client, operation="GetItem", error="throttling", times=2)
    with dynamoxy.collect() as usage:
        user = await users.get("u1")  # throttled twice, retried
    assert usage.retries == 2
    
  • Observable. Structured logs and event hooks out of the box; OpenTelemetry spans and metrics when you configure it. Item contents are never logged.

  • Single-table design with key templates such as "CUSTOMER#{customer_id}".

  • Fast. 2.5 to 5 times less client CPU per call than boto3 (numbers).

  • No required dependencies. pydantic and OpenTelemetry are optional extras.

Also covered: indexes, cursors, batches, transactions, TTL, streams, backups, PartiQL and table management.

Already using pydantic?

Inherit from dynamoxy.PydanticModel instead of BaseModel and mark the key. Pydantic keeps validating, and the class stays a pydantic model, so the same Customer can be a FastAPI request or response model and a DynamoDB table (uv add 'dynamoxy[pydantic]'):

from typing import Annotated

from pydantic import BaseModel, Field

import dynamoxy


class Address(BaseModel):  # plain pydantic models nest as maps
    street: str
    city: str


class Customer(dynamoxy.PydanticModel, table="customers"):  # instead of BaseModel
    customer_id: Annotated[str, dynamoxy.PartitionKey()]
    email: Annotated[str, dynamoxy.Unique()]
    name: str = Field(min_length=1)
    address: Address | None = None


await client.ensure_tables(Customer)
customers = client.repository(Customer)
await customers.create(Customer(customer_id="c1", email="ada@example.com", name="Ada"))
customer = await customers.get("c1")  # a validated Customer

A model you would rather not touch can stay as it is: subclass it together with dynamoxy.PydanticModel and re-declare only the fields that need a marker, such as the key (see the pydantic guide).

Install

uv add dynamoxy               # or: pip install dynamoxy
uv add 'dynamoxy[pydantic]'   # pydantic models
uv add 'dynamoxy[otel]'       # OpenTelemetry

Documentation

Getting started First model, connecting, first queries
Usage guide The compact reference (dynamoxy guide)
Guides Modeling, reading, writing, transactions, single-table design, testing, ...
Examples Runnable programs
Reference Configuration, errors, events
Architecture How it works, invariants, decisions
Changelog Release notes

AI agents: run dynamoxy guide (or read AGENT_GUIDE.md) before writing code with dynamoxy; application repositories can copy the skill in skills/dynamoxy. Agents changing dynamoxy itself start with AGENTS.md.

How it works

A Rust core speaks DynamoDB: the AWS SDK for transport, plus dynamoxy's own retries, batching, events and the in-memory backend. Python owns what you touch: models, validation, repositories and hooks. A few choices worth knowing:

  • Values never go into expression strings, so reserved words and injection are non-issues.
  • Unique values are guard items written in the same transaction, since indexes are only eventually consistent.
  • Models hold no client, so one model works with several accounts, regions or test stores.
  • Stored formats are API: they stay readable across versions.

The architecture and the decision records have the details.

Performance

Round trips cost every client the same. What a library adds is CPU time per call, spent holding the GIL. dynamoxy does the protocol work in Rust.

Client CPU time per call against a local emulator (dynamoxy returns validated models; the others return DynamoDB JSON):

dynamoxy boto3 aiobotocore
GetItem, one item 0.14 ms 0.66 ms 0.60 ms
PutItem, one item 0.19 ms 0.67 ms 0.61 ms
Query, 100 items 0.65 ms 1.68 ms 1.71 ms
  • Cold start (import and first read): 51 ms, against 115 ms for boto3.
  • In memory, a get() takes about 13 µs, so large test suites run in seconds.

Why it is fast: signing, HTTP, JSON and retries run in Rust outside the GIL; each model plans its encoding once, when the class is created; and features you do not use cost nothing.

Measured with dynamoxy 0.2.0 on Python 3.14, aarch64 Linux, October 2026. Your hardware will differ: scripts/benchmark.py measures it on yours.

Contributing

See CONTRIBUTING.md. The project is young (0.x): breaking changes are possible in minor versions and are called out in the changelog.

License

MIT

Metadata

Release files for dynamoxy 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dynamoxy 0.3.0
File Size Uploaded
dynamoxy-0.3.0.tar.gz 323.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for dynamoxy 0.3.0
File
dynamoxy-0.3.0-cp312-abi3-win_arm64.whl CPython 3.12 abi3 Windows ARM64 Details
dynamoxy-0.3.0-cp312-abi3-win_amd64.whl CPython 3.12 abi3 Windows x86-64 Details
dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_x86_64.whl CPython 3.12 abi3 Linux musl 1.2+ x86-64 Details
dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_aarch64.whl CPython 3.12 abi3 Linux musl 1.2+ ARM64 Details
dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 abi3 Linux glibc 2.17+ x86-64 Details
dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.12 abi3 Linux glibc 2.17+ ARM64 Details
dynamoxy-0.3.0-cp312-abi3-macosx_11_0_x86_64.whl CPython 3.12 abi3 macOS 11.0+ x86-64 Details
dynamoxy-0.3.0-cp312-abi3-macosx_11_0_arm64.whl CPython 3.12 abi3 macOS 11.0+ ARM64 Details

Total release size: 52.5 MB

Release files / dynamoxy-0.3.0.tar.gz

Download URL dynamoxy-0.3.0.tar.gz
Size 323.5 kB
Tags Source
SHA-256 checksum
How to use checksums
50aafabeca922f3e84cb929686968469fef9ab45e7e8ff993d83972a42accd40
BLAKE2b-256 checksum
How to use checksums
c322372afdd823d1d0b813fb8dc4b280ed95d80541c01324b49fddc645923246
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-win_arm64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-win_arm64.whl
Size 6.5 MB
Tags CPython 3.12 Windows ARM64 abi3
SHA-256 checksum
How to use checksums
764eee3a5034f06666138f4318f10257995446964d9e241bc3101339a250a5ae
BLAKE2b-256 checksum
How to use checksums
9b6c16f9a5af9017194555050f019d78dd9009f9cb8b11612cf412f7b9b1ea7d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-win_amd64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-win_amd64.whl
Size 6.8 MB
Tags CPython 3.12 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
32dc2a025e401108d2a1069b4524e27c49395cf6aff227b661be77ccc14a2cd0
BLAKE2b-256 checksum
How to use checksums
949673931a4a87273672c3ab7e71a270c32a723ca2c1107fea85362cc49a8396
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_x86_64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_x86_64.whl
Size 6.7 MB
Tags CPython 3.12 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
6cfaed89764d173cf782aa220df399ed093c374825b51168b9772fe6dadeefc2
BLAKE2b-256 checksum
How to use checksums
e0d261d6757f4d03ed41f03aa685231d170698d6662b9a07e617adbf523bf092
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_aarch64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-musllinux_1_2_aarch64.whl
Size 6.3 MB
Tags CPython 3.12 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
f3d96933cf329ba318e1c7a820112f0614b727f93b4d4e0bf96c2c923a6f2d12
BLAKE2b-256 checksum
How to use checksums
0bd147eeb23a8b46bea13eb89ed7b8770678508eab34cecfd216bb3c87c206a3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 6.7 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
441dd31de8bc0c20a44f9174d0e3f42c4ec49a5ca56d27b2213f7e92e33cca82
BLAKE2b-256 checksum
How to use checksums
378d8e8a17599626b8faa4f78328e06e69983939bd3050cac81e359470420d40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 6.3 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
a2d0c55e16d54717356f99687b476299fcd913d91e4a471c1031a88920cda843
BLAKE2b-256 checksum
How to use checksums
df8be7ac3dce6d5f509797d7a608c1e805514be4b69e9ed86840116aa6f035ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-macosx_11_0_x86_64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-macosx_11_0_x86_64.whl
Size 6.6 MB
Tags CPython 3.12 abi3 macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
ab1ad2850eab10da119ecd082592020e77ecd1d3877501666652cf97d3b80cde
BLAKE2b-256 checksum
How to use checksums
aca33a4a0cd7d838e39fdf406be19704c274ca3d63ebe5910d47eb4f73f10bfd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / dynamoxy-0.3.0-cp312-abi3-macosx_11_0_arm64.whl

Download URL dynamoxy-0.3.0-cp312-abi3-macosx_11_0_arm64.whl
Size 6.1 MB
Tags CPython 3.12 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a8a9b3a8573a7364491f37199f22aa4b4432a21e9c6dcbf33ceab112a6a5d8cf
BLAKE2b-256 checksum
How to use checksums
4d821913105fa96b52b299783f2bb702d48e0e7b0cfeb0558511173d305d7229
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.3.0 This release

9 release files

0.2.0

9 release files

0.1.0

9 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page