# Persistence

Responsibility: persist entities to a database/storage and retrieve them later. Often called a repository.

A few important rules apply to the persistence layer:

* they contain zero business logic
* their input is one or multiple domain entity or a domain-specific change description
* their output is one or multiple domain entity or a command feedback

Persistence modules do not create entities, that is the role of [Services](/best-practices/the-big-picture/architecture/services.md). There should be no "create" method in them. Persistence only stores things.

&#x20;The API interface of persistence modules talks the language of the domain and never mention storage-specific information.

It is fine to use a framework, library or 3rd party service as a repository. But they have to remain hidden behind a bespoke, domain-driven API. Looking at the interface should reveal nothing about the technology behind the storage layer.

Add an explicit API interface type to your codebase. This way, different implementations can exist at the same time. A "real" one can save to the database of choice, another to memory for [testing](/best-practices/testing/purpose/integration.md).

Keep in mind that the [domain services](/best-practices/the-big-picture/architecture/services.md) define the API contract for repository modules. There is an obvious shortcut: import the definitions from the services into persistence.

No business logic exists in the persistence layer. These modules are storage boxes. They can store an entity and later return it in a pristine state, but they will never mutate it. The way they achieve this goal is an implementation detail.

There is no validation implemented in the repository - that is business logic. The incoming payload is validated by the [services](/best-practices/the-big-picture/architecture/services.md).

Suggestion: use an ID generated by the domain services instead of an auto-generated one from the DB. Your IDs decouple you from database-specific ID formats. The entity shapes will be more straightforward (they always have an ID). There will be no need to change the ID field names either (from `_id` to `id` etc.).

The Persistence API is not public and will import only from the domain or service modules.

The general rules about API and separation of concerns apply to any other IO modules we need to inject into the services: email or SMS sending, logging, and so on.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thekarel.gitbook.io/best-practices/the-big-picture/architecture/persistence.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
