When to use dynamodb.client, dynamodb.resource and dynamodb.Table?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Boto3 gives you multiple DynamoDB entry points, and each is intended for a different abstraction level. dynamodb.client is low-level and explicit, dynamodb.resource is higher-level and Pythonic, and Table is the focused object for table-centric app code. Choosing the right layer improves readability while preserving access to advanced features when needed.
dynamodb.client: Lowest-Level Control
Use client when you need full API surface and explicit request structure.
Why choose this layer:
- new DynamoDB API features appear here first
- request payload is explicit and predictable
- easier for advanced middleware and auditing pipelines
Tradeoff is verbosity, especially attribute typing with S, N, M, and L wrappers.
dynamodb.resource: Higher-Level Convenience
Use resource when you want cleaner application code and automatic type handling.
Benefits:
- less boilerplate for CRUD operations
- more readable business logic
- easier onboarding for teams new to DynamoDB
Tradeoff is less low-level control when you need service-specific edge behaviors.
Table: Daily Driver for One-Table Workflows
Table objects, created from resource, are ideal for app services that interact with one table repeatedly.
This layer maps naturally to repository-style application code.
Mixed Approach in Real Systems
Many production systems use both layers:
- default app CRUD with
Table - targeted advanced operations with
client
This keeps most code readable without losing access to full API depth.
Decision Rules
Use Table or resource when:
- standard CRUD is primary workload
- readability and maintainability are priorities
- you want automatic Python type conversion
Use client when:
- you need explicit request-level control
- you use features not exposed conveniently in resource wrappers
- you need strict parity with DynamoDB API documentation
Document this policy in team standards to avoid inconsistent styles across services.
Testing and Mocking Considerations
Higher-level table code is often easier to mock in unit tests because calls map closely to business operations. For integration tests, using the same abstraction as production code reduces drift. If you must mix layers, keep boundaries explicit in repository utilities.
Serialization and Decimal Handling
One practical reason teams drop to client is strict control over numeric serialization behavior. DynamoDB numeric values and Python decimal handling can create surprises if conversions are implicit in unexpected places. If your domain has strict formatting or audit requirements, centralize serialization in one utility layer and keep abstraction boundaries consistent. This prevents subtle mismatches between write and read paths.
Common Pitfalls
- Mixing abstraction layers randomly inside one function.
- Choosing
clienteverywhere and creating unnecessary serialization boilerplate. - Assuming
resourcealways exposes newest features immediately. - Hiding low-level request details in places where explicit control is required.
- Failing to define team conventions for which layer is default.
Summary
clientis low-level and explicit.resourceandTableare higher-level and better for most app code.Tableis ideal for table-centric CRUD workflows.- Use mixed strategy intentionally for advanced feature gaps.
- Pick one default abstraction and document when to drop lower.

