# How ai-memory Prevents Circular Dependencies Between Its Crates

> Learn how ai-memory prevents circular dependencies with a strict hierarchical architecture and automatic `cargo check` validation. Ensure robust crate relationships.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: internals
- Published: 2026-08-28

---

**ai-memory enforces acyclic crate dependencies through a strict hierarchical architecture where lower-level crates define core types and higher-level crates depend only downward, with `cargo check` automatically rejecting any cycle-inducing configuration.**

Circular dependencies between crates break Rust builds, obscure module boundaries, and create maintenance nightmares. The `ai-memory` project, authored by Fabio Akita (`akitaonrails/ai-memory`), solves this with a layered workspace design that makes crate relationships explicit, unidirectional, and automatically verifiable.

## Core-First Design: The Foundation of Acyclic Dependencies

The `ai-memory-core` crate sits at the bottom of the dependency hierarchy. It contains domain types, entity IDs, and pure logic data structures that every other crate consumes.

In [`crates/ai-memory-core/Cargo.toml`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/Cargo.toml):

```toml
[package]
name = "ai-memory-core"

```

This crate has **no workspace dependencies**. It exports primitives that upper layers import but never modify. This isolation prevents any upward dependency edge that could form a cycle.

## One-Directional Dependency Flow

Higher-level crates depend strictly on lower-level ones. The hierarchy flows: **Core → Store/LLM → Web**.

Examine [`crates/ai-memory-store/Cargo.toml`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-store/Cargo.toml):

```toml
[package]
name = "ai-memory-store"

[dependencies]
ai-memory-core = { path = "../ai-memory-core" }   # Store depends on Core

```

The store crate consumes core types but does not expose itself to core. This pattern continues upward. In [`crates/ai-memory-web/Cargo.toml`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-web/Cargo.toml):

```toml
[package]
name = "ai-memory-web"

[dependencies]
ai-memory-store = { path = "../ai-memory-store" }   # Web depends on Store

ai-memory-llm   = { path = "../ai-memory-llm" }     # Web also depends on LLM

```

Notice that `ai-memory-web` accesses `ai-memory-core` types **indirectly** through `ai-memory-store` and `ai-memory-llm`. It does not declare a direct dependency on core, preserving the strict layering.

## Workspace Enforcement via Cargo.toml

The root [`Cargo.toml`](https://github.com/akitaonrails/ai-memory/blob/main/Cargo.toml) declares all workspace members. Cargo's build system validates the dependency graph at resolution time—any cycle causes immediate failure with a clear error message.

This mechanical enforcement means:

- Developers cannot accidentally introduce cycles through configuration
- CI pipelines block cyclic dependency PRs automatically
- Refactoring remains safe because `cargo check` validates the graph continuously

## Documented Architectural Invariant

The "no circular deps" rule is codified in documentation, not just code. According to [`docs/ARCHITECTURE.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/ARCHITECTURE.md) at line 349:

> "No circular deps. Inter‑crate boundaries enforce the cross‑cutting invariants."

The same statement appears in [`AGENTS.md`](https://github.com/akitaonrails/ai-memory/blob/main/AGENTS.md) at line 194, ensuring all contributors understand this constraint before modifying crate relationships.

## Why This Pattern Matters for Rust Workspaces

Rust's module system and Cargo's workspace design make circular dependencies particularly destructive:

- **Compilation order ambiguity** — cycles prevent `cargo` from determining build phases
- **Incremental build invalidation** — cyclic edges poison the dependency cache
- **Test isolation breakdown** — integration tests cannot run against partial graphs

By contrast, `ai-memory`'s DAG structure enables:

- Parallel compilation of independent crate subtrees
- Clean unit testing at each layer without mocking upstream crates
- Predictable refactoring where changes to core propagate safely downward

## Summary

- **Core-first layering**: `ai-memory-core` defines primitives with zero workspace dependencies
- **Downward-only edges**: Crates depend strictly on lower-level crates, never siblings or ancestors
- **Mechanical enforcement**: Cargo's dependency resolver rejects non-DAG configurations automatically
- **Explicit documentation**: [`docs/ARCHITECTURE.md`](https://github.com/akitaonrails/ai-memory/blob/main/docs/ARCHITECTURE.md) and [`AGENTS.md`](https://github.com/akitaonrails/ai-memory/blob/main/AGENTS.md) state the invariant for contributors

## Frequently Asked Questions

### What happens if a developer tries to add a circular dependency?

`cargo check` or `cargo build` fails immediately with a resolution error. The workspace dependency graph must remain a directed acyclic graph, and Cargo's resolver enforces this at configuration time—no code compilation even begins.

### Can crates at the same layer depend on each other?

No. The `ai-memory` architecture avoids sibling dependencies entirely. `ai-memory-store` and `ai-memory-llm` both depend on core but not on each other. This prevents diamond dependency problems and keeps the graph shallow.

### Why not use a single crate instead of managing boundaries?

Multiple crates enforce **physical module boundaries** that single-crate codebases cannot guarantee. Teams can work in parallel without merge conflicts, compilation units stay small, and the dependency graph documents architectural intent explicitly.

### How does this pattern scale as the workspace grows?

New crates insert at appropriate layers. A `ai-memory-index` crate would depend on `ai-memory-core` and be consumed by `ai-memory-store`. The existing hierarchy guides placement, and Cargo's validation ensures the graph stays acyclic regardless of workspace size.