Cesivi Capacity Limits¶
Version: v259.0 Last Updated: 2026-04-10 Plan: PLAN-971
Overview¶
This document describes the practical capacity limits of a Cesivi server instance. It is the Cesivi equivalent of SharePoint's published thresholds.
All measurements are taken with: - Storage provider: InMemory (fastest; use FileSystem for persistence-realistic tests) - Hardware: Dev machine (typical modern workstation) - Server: In-process WebApplicationFactory (no network overhead)
Note: These limits reflect test measurements under controlled conditions. Production performance depends on hardware, storage provider, and concurrent load.
Capacity Limits Summary¶
| Resource | Tested Limit | Usable Limit (<2s) | Hard Limit | SP Equivalent |
|---|---|---|---|---|
| Items per list (InMemory) | 20,000 (test limit) | ~10,000 | Not yet determined | SP: 30M hard, 5K view threshold |
| Lists per web | 500+ | 500+ | Not yet determined | SP: 2,000 recommended |
| Files per document library | 1,000+ | 1,000+ | Not yet determined | SP: 30M hard |
| Max file size | 100MB+ | — | Configuration-dependent | SP: 10GB (SharePoint Online) |
| Concurrent users (in-process) | 10+ | 10+ | Not yet determined | SP: varies by hardware |
| Unique permission scopes per list | 500+ | 500+ | Not yet determined | SP: 50,000 per library |
Status: Values marked "Not yet determined" require running
CapacityTestsorCapacityBenchmarks. Rundotnet test --filter "Category=Performance"to populate actual values.
Detail: Items Per List¶
Test Methodology¶
Tests in CapacityTests.FindListItemLimit_IncrementalScale_RecordResults:
- Starts at 1,000 items, adds 1,000 per step up to 20,000
- After each step measures: GetItemById, OData filter, OData orderby
- Reports usability threshold (query time < 2s) and hard limit (> 10s)
Expected Behavior¶
| Scale | GetItemById | OData Filter | OData OrderBy | Status |
|---|---|---|---|---|
| 1,000 | < 10ms | < 100ms | < 200ms | Excellent |
| 5,000 | < 10ms | < 200ms | < 500ms | Good |
| 10,000 | < 10ms | < 500ms | < 1s | Acceptable |
| 20,000 | < 10ms | < 2s | < 3s | At usability limit (InMemory) |
Recommendation: For lists > 5,000 items, enable indexed columns and use
$selectto limit returned fields.
Detail: Lists Per Web¶
Test Methodology¶
Tests in CapacityTests.CreateLists_100_MeasureEnumerationTime and CreateLists_500_MeasureEnumerationTime:
- Creates 100 or 500 lists and measures GET /_api/web/lists enumeration time
Expected Behavior¶
| List Count | GET /web/lists Time |
Status |
|---|---|---|
| 100 | < 1s | Excellent |
| 500 | < 5s | Acceptable |
| 1,000 | < 10s | At usability limit |
Detail: Document Libraries¶
File Upload Performance¶
| File Count | File Size | Expected Upload Time | Notes |
|---|---|---|---|
| 1,000 | 1KB | < 60s | Sequential upload |
| 1 | 10MB | < 5s | Single file |
| 1 | 100MB | < 30s | Single large file |
File Enumeration Performance¶
| File Count | GET /Files ($top=100) |
Status |
|---|---|---|
| 1,000 | < 500ms | Excellent |
| 10,000 | < 2s | Acceptable |
Detail: Permission Scopes¶
Unique Permission Items¶
For lists with items that have unique (broken) inheritance:
| Unique Items | ACL Recompute Time | Security Trimming (100 results) |
|---|---|---|
| 100 | < 1s | < 200ms |
| 500 | < 5s | < 500ms |
| 1,000 | < 10s | < 1s |
Note: Cesivi uses a computed ACL cache (warm: O(1) lookup). First access after cache invalidation triggers on-demand computation. Use
POST /_api/cesivi/permissions/recomputeto pre-warm.
Deny ACE Overhead¶
Items with Deny ACEs add marginal overhead to security trimming: - < 20% Deny ACEs: < 10% overhead vs all-Allow - > 50% Deny ACEs: may add up to 50% overhead — pre-warm the ACL cache
Performance Tips¶
For Large Lists (> 5,000 items)¶
- Use
$selectto limit returned fields - Use
$top+ pagination (server-driven paging via__next) - Index frequently filtered columns via field settings
- Use CAML
<RowLimit>to limit server-side rows
For Large Document Libraries¶
- Use
$top+ pagination for file enumeration - Avoid loading all file metadata at once
- Use search API for cross-library queries
For Heavy Permission Scenarios¶
- Pre-warm ACL cache with
POST /_api/cesivi/permissions/recompute?cascade=trueafter bulk changes - Configure
Cesivi:AclRecalculation:EnabledOnStartup=truefor automatic background recalc - Monitor permission recalc status via
GET /_api/cesivi/permissions/recalcstatus
Running Capacity Tests¶
# All performance/capacity tests (xUnit)
bash Scripts/test-watchdog.sh 300 Cesivi.Tests.Performance/Cesivi.Tests.Performance.csproj -- --filter "Category=Performance"
# BenchmarkDotNet capacity benchmarks (Release mode required)
cd Cesivi.Tests.Performance
dotnet run --configuration Release -- --filter "*Capacity*"
# BenchmarkDotNet permission benchmarks
dotnet run --configuration Release -- --filter "*Permission*"
Comparison: Cesivi vs SharePoint Published Limits¶
| Resource | Cesivi (InMemory) | SharePoint Online | SharePoint 2019 On-Premises |
|---|---|---|---|
| Max list items | ~10K-20K usable | 30M | 30M |
| List view threshold | N/A (no threshold) | 5,000 | 5,000 |
| Max lists per site | 500+ tested | No documented limit | No documented limit |
| Max file size | Config-dependent | 250GB | 2GB (default) |
| Max unique perm scopes | 1,000+ tested | 50,000/library | 50,000/library |
Key difference: Cesivi does NOT enforce a 5,000-item list view threshold. All items in a list are always accessible via REST, regardless of item count. This is an intentional design choice (mock/test server vs production SharePoint).