← Files Azure Cosmos DBARCHIVED FILE
skills/cosmosdb-best-practices/rules/model-nesting-depth.md
3.44 KB · Sep 30, 2026 · 23:01 UTC
---
title: Stay Within 128-Level Nesting Depth Limit
impact: MEDIUM
impactDescription: prevents document rejection on deeply nested structures
tags: model, nesting, limits, design, json
---
## Stay Within 128-Level Nesting Depth Limit
Azure Cosmos DB allows a maximum of **128 levels** of nesting for embedded objects and arrays. While 128 is generous, recursive or auto-generated structures can exceed this limit unexpectedly.
**Incorrect (risk of exceeding nesting limit):**
```csharp
// Anti-pattern 1: Recursive tree stored as deeply nested JSON
public class TreeNode
{
public string Id { get; set; }
public string Name { get; set; }
// Recursive children - each level adds nesting depth
public List<TreeNode> Children { get; set; }
}
// A category hierarchy with 130+ levels will fail on write
var root = BuildDeepTree(depth: 150); // Exceeds 128 levels!
await container.CreateItemAsync(root);
// Microsoft.Azure.Cosmos.CosmosException: Document nesting depth exceeds limit
// Anti-pattern 2: Deeply nested auto-generated JSON from ORMs
// Serializing complex object graphs without cycle detection
var entity = LoadEntityWithAllRelations(); // Lazy-loaded relations
var json = JsonSerializer.Serialize(entity); // May create deep nesting
```
**Correct (bounded nesting depth):**
```csharp
// Solution 1: Flatten deep hierarchies using path-based approach
public class CategoryNode
{
public string Id { get; set; }
public string Name { get; set; }
public string ParentId { get; set; }
// Materialized path captures hierarchy without nesting
public string Path { get; set; } // e.g., "/root/electronics/phones/android"
public int Depth { get; set; }
// Only store immediate children IDs, not nested objects
public List<string> ChildIds { get; set; }
}
// Each node is a flat document, hierarchy expressed via Path and ParentId
var node = new CategoryNode
{
Id = "cat-android",
Name = "Android",
ParentId = "cat-phones",
Path = "/root/electronics/phones/android",
Depth = 3,
ChildIds = new List<string> { "cat-samsung", "cat-pixel" }
};
```
```csharp
// Solution 2: Cap nesting depth when building recursive structures
public class TreeNode
{
public string Id { get; set; }
public string Name { get; set; }
public List<TreeNode> Children { get; set; }
}
// Limit nesting at serialization time
public static TreeNode TruncateTree(TreeNode node, int maxDepth, int currentDepth = 0)
{
if (currentDepth >= maxDepth || node.Children == null)
{
node.Children = null; // Stop nesting here
return node;
}
node.Children = node.Children
.Select(c => TruncateTree(c, maxDepth, currentDepth + 1))
.ToList();
return node;
}
// Keep well under 128 - aim for practical limits like 10-20
var safeTree = TruncateTree(root, maxDepth: 20);
await container.CreateItemAsync(safeTree);
```
Key points:
- Maximum nesting depth is **128 levels** for embedded objects/arrays
- Recursive data structures (trees, graphs) are the most common cause of violations
- Prefer flat representations with references (parent IDs, materialized paths) for deep hierarchies
- If nesting is required, enforce a practical depth cap well under 128
Reference: [Azure Cosmos DB service quotas - Per-item limits](https://learn.microsoft.com/azure/cosmos-db/concepts-limits#per-item-limits)
SHA-256: 3818fe7dbc1431be163b74f49e62ec7c04c8d7b59182554849faebe2497cc1c3