> For the complete documentation index, see [llms.txt](https://framework.aic.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://framework.aic.io/technical-guidelines-code-standards-and-tech-stack/tech-stack/data-access-stack.md).

# Data Access Stack

## AIC Standard

MongoDB is the default primary persistence layer for AIC applications and platforms.

AIC favours MongoDB because many of our products and customer systems deal with evolving operational records, documents, events, detections, intelligence objects, workflow state, audit records and tenant-specific metadata. These domains usually benefit from a document-first model where an aggregate can be stored, retrieved and versioned without forcing premature relational decomposition.

EF Core and relational databases remain approved, but they are secondary choices. Use them when the data model is strongly relational, when ACID transaction boundaries across multiple tables are genuinely required, when customer policy mandates a relational store, or when reporting and analytics are better served by a relational model.

Redis is the default caching layer. It must not be treated as the system of record.

## Default Persistence Decision

| Requirement                                  | Preferred approach                                                      |
| -------------------------------------------- | ----------------------------------------------------------------------- |
| Primary operational application data         | MongoDB                                                                 |
| Document-like aggregates                     | MongoDB                                                                 |
| Multi-tenant SaaS platform data              | MongoDB with explicit tenant isolation controls                         |
| Event, message, detection or ingest records  | MongoDB                                                                 |
| Audit trails                                 | MongoDB append-only collection or dedicated audit store                 |
| Search-heavy read models                     | MongoDB Atlas Search, dedicated search index, or approved projection    |
| Short-lived cache                            | Redis                                                                   |
| Distributed locks / short-lived coordination | Redis, with strict expiry and failure handling                          |
| Strong relational model                      | Relational database with EF Core                                        |
| Legacy SQL integration                       | EF Core, Dapper or raw SQL as appropriate                               |
| Reporting warehouse                          | Separate analytical model, not the operational MongoDB model by default |
| Offline mobile data                          | Local encrypted store plus sync strategy                                |
| Integration idempotency                      | MongoDB or Redis depending durability requirement                       |

## MongoDB Standards

* Model collections around aggregates, not around relational tables.
* Keep aggregate boundaries explicit.
* Store tenant identifiers on every tenant-owned document.
* Index all high-use query paths.
* Use compound indexes deliberately for tenant, status, date and correlation lookups.
* Avoid unbounded document growth.
* Avoid deeply nested structures that become difficult to update or query.
* Use optimistic concurrency where concurrent updates can collide.
* Use transactions only where necessary; prefer aggregate design that avoids cross-document transactions.
* Do not expose MongoDB document models directly through public APIs.
* Use repository or data access abstractions where they protect the domain from persistence details.
* Store dates in UTC.
* Use explicit serialization conventions.
* Keep collection naming consistent and documented.

## MongoDB Driver and Configuration

Projects should use the official MongoDB .NET driver unless a project-specific exception is approved.

Connection configuration must be handled through typed options and secure secret management.

Example options model:

```csharp
public sealed record MongoDatabaseOptions
{
    public required string ConnectionString { get; init; }

    public required string DatabaseName { get; init; }
}
```

Example registration:

```csharp
public static class MongoDatabaseServiceCollectionExtensions
{
    public static IServiceCollection AddMongoDatabase(
        this IServiceCollection serviceCollection,
        IConfiguration configuration)
    {
        serviceCollection.Configure<MongoDatabaseOptions>(
            configuration.GetRequiredSection(nameof(MongoDatabaseOptions)));

        serviceCollection.AddSingleton<IMongoClient>(serviceProvider =>
        {
            MongoDatabaseOptions mongoDatabaseOptions = serviceProvider
                .GetRequiredService<IOptions<MongoDatabaseOptions>>()
                .Value;

            return new MongoClient(mongoDatabaseOptions.ConnectionString);
        });

        serviceCollection.AddScoped(serviceProvider =>
        {
            MongoDatabaseOptions mongoDatabaseOptions = serviceProvider
                .GetRequiredService<IOptions<MongoDatabaseOptions>>()
                .Value;

            IMongoClient mongoClient = serviceProvider.GetRequiredService<IMongoClient>();

            return mongoClient.GetDatabase(mongoDatabaseOptions.DatabaseName);
        });

        return serviceCollection;
    }
}
```

## Repository Standard

Repositories should protect the domain from MongoDB-specific concerns while staying honest about MongoDB semantics.

Do not create generic repositories that hide important query behaviour, indexing needs, consistency limits or tenant filtering.

Preferred repository characteristics:

* aggregate-specific interface
* explicit query methods
* cancellation token support
* tenant-aware access rules
* optimistic concurrency support where required
* no hidden cross-collection magic
* no leaking `IMongoCollection<TDocument>` into application services

Example:

```csharp
public interface ICaseRepository
{
    Task<CaseRecord?> GetByIdAsync(
        OrganisationId organisationId,
        CaseId caseId,
        CancellationToken cancellationToken);

    Task<IReadOnlyList<CaseSummary>> SearchOpenCasesAsync(
        OrganisationId organisationId,
        CaseSearchRequest caseSearchRequest,
        CancellationToken cancellationToken);

    Task SaveAsync(
        CaseRecord caseRecord,
        CancellationToken cancellationToken);
}
```

## Redis Standards

Redis is used for speed, not truth.

Use Redis for:

* distributed cache
* short-lived session state
* rate limiting counters
* idempotency markers where loss is acceptable or backed by durable persistence
* short-lived coordination with explicit expiry
* frequently read reference data
* temporary API response caching

Do not use Redis for:

* permanent business records
* authoritative audit trails
* long-term workflow state
* data that cannot be rebuilt
* secrets
* uncontrolled personally identifiable information

## EF Core and Relational Use

EF Core is approved when relational persistence is the right answer.

Use EF Core when:

* the domain is naturally relational
* reporting requires relational modelling
* customer infrastructure mandates SQL
* transaction boundaries require relational consistency
* integration with existing relational systems is the core requirement

When EF Core is selected, the decision must be recorded in an ADR.

## Data Quality Gate

Before release:

* persistence choice recorded in an ADR
* MongoDB collections and indexes documented
* tenant filtering reviewed
* query performance checked for critical paths
* Redis cache keys, expiry and invalidation documented
* sensitive data handling reviewed
* connection string handling secure
* backup and restore assumptions recorded
* test database strategy defined
* migration or schema evolution approach documented
