Introduction
dbzero is a state management system designed to unify your application's business logic, data persistence, and caching into a single, efficient layer.
The core philosophy is inspired by a thought experiment from Architecture Patterns with Python by Harry Percival and Bob Gregory:
“If we had infinite memory in our laptop, we’d have no need for clumsy databases. Instead, we could just use our objects whenever we liked.”
While we don't have infinite memory, dbzero provides an abstraction that lets you code as if you do. It handles the complexities of data management in the background, offering a robust set of features out of the box.
dbzero implements the DISTIC memory model:
- Durable - Data persists across application restarts
- Infinite - Work with data as if memory constraints don't exist
- Shared - Multiple processes can access and share the same data
- Transactions - Transaction support for data integrity
- Isolated - Operations are isolated and thread-safe
- Composable - A single process can integrate multiple memory partitions (prefixes) to suit its specific requirements
The result is a simplified application stack that eliminate the need for separate databases, ORMs and caching layers. This reduces architectural complexity and development time, while offering significant performance benefits, due to reduced serialization overhead and cache locality.
Express start
Installation
pip install dbzeroSimple example
The guiding philosophy behind dbzero is invisibility—it stays out of your way as much as possible. In most cases, unless you're using advanced features, you won’t even notice it’s there. No schema definitions, no explicit save calls, no ORM configuration. You just write regular Python code, as you always have. See the complete working example below:
import dbzero as db0
@db0.memo(singleton=True)
class GreeterAppRoot:
def __init__(self, greeting, persons):
self.greeting = greeting
self.persons = persons
self.counter = 0
def greet(self):
print(f"{self.greeting}{''.join(f', {person}' for person in self.persons)}!")
self.counter += 1
if __name__ == "__main__":
# Initialize dbzero
db0.init("./app-data", prefix="main")
# Initialize the application's root object
root = GreeterAppRoot("Hello", ["Michael", "Jennifer"])
root.greet() # Output: Hello, Michael, Jennifer!
print(f"Greeted {root.counter} times.")What’s happening here:
- The
@db0.memo(singleton=True)decorator tells dbzero to manage theGreeterAppRootclass as a singleton—meaning only one instance will exist per prefix. - dbzero data root is initialized inside "app-data", relative to current working directory and "main" is set as the current prefix.
- Singleton is initialized only once with its
__init__args. - When the process exits, the application state is persisted automatically. The same data will be available the next time the app starts.
If you run this script several times you will notice the count increses each time. You can try to access and modify the same data from a different script:
import dbzero as db0
from greeter import GreeterAppRoot
if __name__ == "__main__":
# Initialize dbzero
db0.init("./app-data", prefix="main")
# Access the root
root = GreeterAppRoot()
root.greeting = "Bonjour"
root.persons.append("Susan")
root.greet() # Output: Bonjour, Michael, Jennifer, Susan!
Why dbzero?
As we observed in our cases, dbzero can reduce development time by up to 80%. This is mostly thanks to reduced complexity, which leads to a significantly smaller and more maintainable codebase. It also works exceptionally well with AI coding agents, enabling them to generate accurate code with fewer bugs.
Applications built with dbzero are not only easier to develop—they're also more performant and naturally scalable in distributed environments.
But the true innovation lies in flexible data modeling. Unlike traditional architectures that constrain you to tables, graphs, or documents, dbzero lets you design custom data models that match your application's needs exactly—and reuse them across projects.
Key platform features:
dbzero provides the reliability of a traditional database system with modern capabilities and extra features on top:
- Persistence: Application objects (classes and common structures like
list,dict,set, etc.) are automatically persisted to the underlying storage medium (e.g. a local file). - Efficient caching: Only the data actually accessed is retrieved and cached. For example, if a list has 1 million elements but only 10 are accessed, only those 10 are loaded.
- Constrained memory usage: You can define memory limits for the process to control RAM consumption.
- Serializable consistency: Data changes are immediately visible to readers, maintaining a consistent view.
- Transactions: Make atomic changes using the
with dbzero.atomic():context manager. - Snapshots & Time Travel: Query data as it existed at a specific point in the past. This enables tracking of data changes and simplify auditing.
- Tags: Tag objects and use tags to filter or retrieve data.
- Indexing: Define imperative indexes that can be dynamically created and updated.
- Data composability: Combine data from different apps, processes, or servers and access it through a unified interface.
- UUID support: All objects are automatically assigned a universally unique identifier, allowing to always reference them directly.
- Custom data models - Unlike traditional databases, dbzero allows you to define custom data structures to match your domain's needs.
All these features are condensed into a single layer. This results in simplified application stack that eliminates the need for separate databases, ORMs, and caching layers.
General Architecture
Internally, dbzero stores all managed data in files called "prefixes". A prefix is a single .db0 file that holds the state of an application - i.e. all of its data assets such as: objects, collections, binary data, metadata and more.
- Only one process can open a specific prefix in read-write mode.
- However, multiple processes can open the same prefix in read-only mode simultaneously.
The .db0 file format is platform-independent and can even serve as a data-exchange format—an alternative to tools like Python’s pickle. Prefix files can be easily backed up while the application is running, with the use of copy_prefix functionality.
Below is an example deployment architecture where three processes share access to five prefixes:
Prefix Characteristics
dbzero prefixes are central to how data is managed and shared across processes. Each prefix follows these core principles:
- Can be identified by a relative path (name) or a UUID.
- Can be opened in read-write mode by only one process at a time.
- Can be opened in read-only mode by multiple processes simultaneously, with automatic and consistent synchronization.
- Stores both current data and the entire change history, enabling features like time travel and snapshots.
- Each process typically operates on a single "current" prefix, unless configured otherwise.
- Contains only metadata (e.g., class and enum definitions) for binding with Python code—no actual code is stored.
- Consumes only a small, bounded amount of operating memory, no matter how much data the prefix contains.
- Data updates are stored incrementally, which helps to save storage space.
Get started
Key Concepts
Get falimiar with key concepts of dbzero:
Tutorials
Learn dbzero with tutorials:
API Reference
For more details about specific funcions, check out our API reference:
Contributing
Want to contribute? Check out our Contributing Guide to learn how you can help improve dbzero.
Support and Feedback
Here's how to get help or provide feedback:
- For bug reports and feature requests related to the dbzero platform, SDKs, or documentation (open source), please create a GitHub issue (opens in a new tab)
- For discussions or Q&A about the dbzero plaform, use the dbzero discussions (opens in a new tab)
- For discussions or Q&A about other dbzero open source components, use the organization discussions (opens in a new tab)