Configuration Reference
CSharpDB is configured through a hierarchy of options objects passed to Database.OpenAsync.
All options use sensible defaults — you only need to override what you want to change.
Opening a Database
// Defaults — zero configuration
await using var db = await Database.OpenAsync("mydata.db");
// With options
await using var db = await Database.OpenAsync("mydata.db", new DatabaseOptions
{
StorageEngineOptions = new StorageEngineOptions
{
DurabilityMode = DurabilityMode.Buffered,
PagerOptions = new PagerOptions
{
MaxCachedPages = 5000,
CheckpointPolicy = new FrameCountCheckpointPolicy(2000),
}
}
});
// In-memory
await using var db = await Database.OpenInMemoryAsync();
// Hybrid (lazy-resident with on-disk persistence)
await using var db = await Database.OpenHybridAsync("mydata.db",
new DatabaseOptions(),
new HybridDatabaseOptions
{
PersistenceMode = HybridPersistenceMode.IncrementalDurable,
HotTableNames = ["users", "sessions"],
});
Options Hierarchy
DatabaseOptions
├── ImplicitInsertExecutionMode
├── Functions
├── WindowExecution
│ ├── MaxPartitionRows
│ └── MaxBufferedRows
├── StorageEngineOptions
│ ├── DurabilityMode
│ ├── DurableGroupCommit
│ ├── DurableCommitBatchWindow (compatibility alias)
│ ├── AdvisoryStatisticsPersistenceMode
│ ├── WalPreallocationChunkBytes
│ └── PagerOptions
│ ├── WriterLockTimeout
│ ├── CheckpointPolicy
│ ├── AutoCheckpointExecutionMode
│ ├── AutoCheckpointMaxPagesPerStep
│ ├── MaxCachedPages
│ ├── MaxCachedWalReadPages
│ ├── PageCacheFactory
│ ├── MaxWalBytesWhenReadersActive
│ ├── UseMemoryMappedReads
│ ├── EnableSequentialLeafReadAhead
│ └── PreserveOwnedPagesOnCheckpoint
└── StorageEngineFactory
HybridDatabaseOptions (separate, for OpenHybridAsync)
├── PersistenceMode
├── PersistenceTriggers
├── HotTableNames
└── HotCollectionNames
FullTextIndexOptions (per-index, for EnsureFullTextIndexAsync)
├── Normalization
├── LowercaseInvariant
└── StorePositions
DatabaseOptions
Top-level database composition and execution-shape configuration.
| Option | Type | Default | Description |
|---|---|---|---|
ImplicitInsertExecutionMode |
ImplicitInsertExecutionMode |
Serialized |
Controls whether shared auto-commit INSERT statements stay behind the legacy database write gate or run as isolated WriteTransaction commits. This does not disable the explicit multi-writer WriteTransaction APIs. |
Functions |
DbFunctionRegistry |
DbFunctionRegistry.Empty |
Trusted in-process scalar functions available to SQL and embedded expression surfaces. See Trusted C# Scalar Functions. |
WindowExecution |
WindowExecutionOptions |
default instance | Finite row limits for bounded in-memory SQL window execution |
StorageEngineOptions |
StorageEngineOptions |
default instance | Storage engine durability, pager, WAL, and checkpoint settings |
StorageEngineFactory |
IStorageEngineFactory |
DefaultStorageEngineFactory |
Factory used to compose the backing storage engine |
WindowExecution
Window functions buffer and order rows in memory. The owning embedded or direct host sets these limits on the DatabaseOptions instance used to open the database; they are not per-query SQL settings and cannot be overridden by a remote client statement.
| Option | Type | Default | Description |
|---|---|---|---|
MaxPartitionRows |
int |
65536 |
Maximum number of rows allowed in one logical window partition |
MaxBufferedRows |
int |
262144 |
Maximum number of input rows one in-memory window stage may buffer |
Both values must be greater than zero, and MaxBufferedRows cannot be smaller than MaxPartitionRows. Exceeding either runtime limit stops the query with ResourceLimitExceeded rather than allowing uncontrolled memory growth.
await using var db = await Database.OpenAsync("mydata.db", new DatabaseOptions
{
WindowExecution = new WindowExecutionOptions
{
MaxPartitionRows = 20_000,
MaxBufferedRows = 80_000,
},
});
StorageEngineOptions
Top-level storage engine configuration.
| Option | Type | Default | Description |
|---|---|---|---|
DurabilityMode |
DurabilityMode |
Durable |
WAL commit flushing strategy |
DurableGroupCommit |
DurableGroupCommitOptions |
Disabled |
Opt-in durable group-commit settings |
DurableCommitBatchWindow |
TimeSpan |
TimeSpan.Zero |
Compatibility alias for DurableGroupCommit.BatchWindow |
AdvisoryStatisticsPersistenceMode |
AdvisoryStatisticsPersistenceMode |
Immediate |
When to persist query planner statistics |
WalPreallocationChunkBytes |
long |
0 (disabled) |
Pre-reserve WAL file space in chunks of this size |
PagerOptions |
PagerOptions |
new() |
Page cache, locking, and checkpoint settings |
DurabilityMode
Controls how WAL commits are flushed to disk.
| Value | Description |
|---|---|
Durable |
Forces an OS-level flush on every commit. Maximum safety, analogous to SQLite synchronous=FULL. This is the default. |
Buffered |
Flushes managed buffers to the OS but does not force an OS flush per commit. Higher throughput at the cost of potential data loss of recent commits on power failure. Analogous to SQLite synchronous=NORMAL. |
DurableGroupCommit
When using Durable mode, setting DurableGroupCommit.BatchWindow to a non-zero TimeSpan (for example, TimeSpan.FromMilliseconds(0.25)) allows the engine to batch concurrent commits into a single OS flush. This amortizes the cost of fsync across multiple writers without reducing durability guarantees for any individual commit.
DurableCommitBatchWindow remains available as a compatibility alias for the same BatchWindow value.
AdvisoryStatisticsPersistenceMode
| Value | Description |
|---|---|
Immediate |
Statistics updated during ordinary commit flows. Default — keeps stats fresh with minimal lag. |
Deferred |
Statistics kept current in memory but only persisted on ANALYZE, clean close, or export. Reduces write amplification for write-heavy workloads. |
PagerOptions
Controls the page cache, writer locking, and automatic checkpointing.
Cache
| Option | Type | Default | Description |
|---|---|---|---|
MaxCachedPages |
int? |
null (unbounded) |
Maximum pages in the shared cache. When set, uses an LRU eviction policy. When null, all pages are retained. |
MaxCachedWalReadPages |
int |
0 |
Dedicated cache for immutable WAL frame reads. 0 disables caching (always reads from WAL). |
PageCacheFactory |
Func<IPageCache>? |
null |
Custom cache implementation. Overrides MaxCachedPages when set. |
OnCachePageEvicted |
Action<uint, byte[]>? |
null |
Diagnostic callback invoked when a page is evicted from cache. |
PreserveOwnedPagesOnCheckpoint |
bool |
true |
Keep materialized main-file pages in cache after checkpoint. Only transient WAL and memory-mapped views are invalidated. |
Read Path
| Option | Type | Default | Description |
|---|---|---|---|
UseMemoryMappedReads |
bool |
false |
Enable memory-mapped I/O for clean main-file page reads. |
EnableSequentialLeafReadAhead |
bool |
true |
Speculative read-ahead of next B-tree leaf during sequential scans. |
Writer Lock
| Option | Type | Default | Description |
|---|---|---|---|
WriterLockTimeout |
TimeSpan |
5 seconds |
Maximum wait time to acquire the single-writer lock. |
Checkpoint Policy
| Option | Type | Default | Description |
|---|---|---|---|
CheckpointPolicy |
ICheckpointPolicy |
FrameCountCheckpointPolicy(1000) |
When to trigger automatic checkpoints. |
AutoCheckpointExecutionMode |
AutoCheckpointExecutionMode |
Foreground |
Run checkpoints inline or in the background. |
AutoCheckpointMaxPagesPerStep |
int |
64 |
Max pages per background checkpoint step (ignored for foreground). |
MaxWalBytesWhenReadersActive |
long? |
null |
Optional WAL growth cap while snapshot readers are active. Commits fail with ErrorCode.Busy if exceeded. |
Snapshot readers now block checkpoint finalization only when they still reference retained WAL frames. Readers whose snapshot was taken after the WAL had already been drained can coexist with auto-checkpoint finalization without forcing WAL growth.
Built-in Checkpoint Policies
FrameCountCheckpointPolicy(int threshold)
Triggers when committed frame count reaches the threshold and no active snapshot currently requires retained WAL frames. Default threshold is 1000 frames.
new FrameCountCheckpointPolicy(2000)
TimeIntervalCheckpointPolicy(TimeSpan interval)
Triggers at fixed wall-clock intervals when no readers are active.
new TimeIntervalCheckpointPolicy(TimeSpan.FromMinutes(5))
WalSizeCheckpointPolicy(long thresholdBytes)
Triggers when estimated WAL size in bytes reaches the threshold and no readers are active.
new WalSizeCheckpointPolicy(50 * 1024 * 1024) // 50 MB
AnyCheckpointPolicy(params ICheckpointPolicy[] policies)
Composite policy — triggers when any of the inner policies fires.
new AnyCheckpointPolicy(
new FrameCountCheckpointPolicy(1000),
new WalSizeCheckpointPolicy(100 * 1024 * 1024)
)
AutoCheckpointExecutionMode
| Value | Description |
|---|---|
Foreground |
Checkpoint runs inline with the triggering commit. The commit does not return until the checkpoint completes. Simplest model. |
Background |
Checkpoint is scheduled asynchronously after commit returns. Copies at most AutoCheckpointMaxPagesPerStep pages per step to avoid blocking subsequent writes. |
HybridDatabaseOptions
Configuration for hybrid databases opened with Database.OpenHybridAsync. Hybrid databases
keep frequently accessed pages resident in memory while persisting committed state to a
backing file.
| Option | Type | Default | Description |
|---|---|---|---|
PersistenceMode |
HybridPersistenceMode |
IncrementalDurable |
Persistence strategy. |
PersistenceTriggers |
HybridPersistenceTriggers |
Commit \| Dispose |
Lifecycle points that trigger persistence (snapshot mode only). |
HotTableNames |
IReadOnlyList<string> |
[] |
SQL tables to preload into cache at open time. |
HotCollectionNames |
IReadOnlyList<string> |
[] |
Collections to preload into cache at open time. |
HybridPersistenceMode
| Value | Description |
|---|---|
IncrementalDurable |
Uses on-disk WAL and page-level checkpoints. Touched pages remain resident by cache policy. Default and recommended. |
Snapshot |
Full-image export to backing file. Simpler but higher write amplification. |
HybridPersistenceTriggers (Flags)
Only applies when PersistenceMode is Snapshot.
| Flag | Description |
|---|---|
None |
Manual persistence only |
Commit |
Persist after each commit |
Checkpoint |
Persist on checkpoint |
Dispose |
Persist on database close |
FullTextIndexOptions
Per-index configuration passed to Database.EnsureFullTextIndexAsync.
| Option | Type | Default | Description |
|---|---|---|---|
Normalization |
NormalizationForm |
FormKC |
Unicode normalization form applied during indexing. |
LowercaseInvariant |
bool |
true |
Apply case-insensitive indexing. |
StorePositions |
bool |
true |
Store token positions for proximity/phrase searches. |
Observability
Embedded databases, the standalone API, the daemon, and Admin share one
validated CSharpDbObservabilityOptions model. API and daemon hosts
bind it from CSharpDB:Observability before database warmup. For an
embedded database, pass the same options instance through
DatabaseOptions.ObservabilityOptions.
| Key | Default | Description and validation |
|---|---|---|
Enabled | false | Master switch for configured runtime diagnostics, logging, tracing, and metrics. OpenTelemetry and Prometheus cannot be enabled while this is false. Health is configured independently. |
DatabaseAlias | default | Stable low-cardinality label: 1-64 ASCII letters, digits, ., -, or _. Never use a path, connection string, or unbounded tenant value. |
Logging:Enabled | true | Bridges typed events to the host logging pipeline when master observability is enabled. |
Logging:Queries | false | Enables ordinary query terminal logging. |
Logging:SlowQueries | true | Enables slow-query events. |
Logging:SlowQueryThreshold | 00:00:00.500 | Positive duration up to one day. SlowQueryThresholdOverrides can set a positive threshold for each defined operation class. |
Logging:SqlText | None | None, Normalized, or sensitive Raw. Raw mode emits startup warning event 1003. |
History:Enabled | true | Retains bounded active/recent query and maintenance history. Set false for metrics- or tracing-only operation; those signals remain independently enabled. |
History:ActiveQueryCapacity | 1000 | Bounded active-query registry capacity, 1-10,000. |
History:RecentQueryCapacity | 500 | Bounded recent-query history capacity, 1-10,000. |
History:RecentOperationCapacity | 100 | Bounded maintenance/operation history capacity, 1-10,000. |
History:Retention | 00:15:00 | Positive in-memory retention up to seven days. |
LongRunningQueryThreshold | 00:00:05 | Positive duration up to one day before the in-flight long-running event. |
SessionAbandonmentThreshold | 00:30:00 | Positive idle duration up to seven days used to classify open non-expiring sessions. |
OpenTelemetry:Enabled | false | API/daemon host adapter registers the CSharpDB activity source and meter. |
OpenTelemetry:SamplingRatio | 1 | Parent-based trace-id sampling ratio from 0 through 1. |
OpenTelemetry:Resource:* | host defaults | Optional service name, namespace, version, instance id, and deployment environment. Values are at most 128 non-control characters and cannot contain paths. |
OpenTelemetry:Otlp:Enabled | false | Enables OTLP trace and metric export. Endpoint, protocol, headers, and timeout use standard OTEL_EXPORTER_OTLP_* environment variables. |
OpenTelemetry:Console:Enabled | false | Enables console trace and metric export independently of OTLP. |
Prometheus:Enabled | false | Maps the protected exact scrape route and registers metrics even when tracing is disabled. |
Prometheus:Path | /metrics | Canonical absolute application path; it must not collide with REST, gRPC, OpenAPI, Scalar, or health routes. |
Prometheus:AllowInsecureRemoteAccess | false | Explicitly permits unauthenticated non-loopback scraping in security mode None and emits a warning. Prefer API-key mode, TLS, and private networking. |
Health:Enabled | true | Maps cached minimal liveness/readiness routes; daemon also maps standard gRPC Health. |
Health:LivenessPath | /health/live | Canonical exact process-liveness path. |
Health:ReadinessPath | /health/ready | Distinct canonical exact cached database-readiness path. |
Health:ReadinessTimeout | 00:00:02 | Positive bounded database verification attempt, up to one minute. |
Representative hosted configuration:
{
"CSharpDB": {
"Observability": {
"Enabled": true,
"DatabaseAlias": "primary",
"Logging": {
"Enabled": true,
"Queries": true,
"SlowQueries": true,
"SlowQueryThreshold": "00:00:00.500",
"SqlText": "None"
},
"History": {
"Enabled": true,
"ActiveQueryCapacity": 1000,
"RecentQueryCapacity": 500,
"RecentOperationCapacity": 100,
"Retention": "00:15:00"
},
"LongRunningQueryThreshold": "00:00:05",
"SessionAbandonmentThreshold": "00:30:00",
"OpenTelemetry": {
"Enabled": true,
"SamplingRatio": 0.1,
"Resource": {
"ServiceName": "orders-api",
"ServiceNamespace": "CSharpDB",
"DeploymentEnvironment": "production"
},
"Otlp": { "Enabled": true },
"Console": { "Enabled": false }
},
"Prometheus": {
"Enabled": true,
"Path": "/metrics",
"AllowInsecureRemoteAccess": false
},
"Health": {
"Enabled": true,
"LivenessPath": "/health/live",
"ReadinessPath": "/health/ready",
"ReadinessTimeout": "00:00:02"
}
}
}
}
Environment variables use the normal double-underscore form:
$env:CSharpDB__Observability__Enabled = "true"
$env:CSharpDB__Observability__DatabaseAlias = "primary"
$env:CSharpDB__Observability__OpenTelemetry__Otlp__Enabled = "true"
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "https://collector.example.internal:4317"
$env:CSharpDB__Observability__Prometheus__Enabled = "true"
See Observability and Diagnostics for the complete logging, span, metric, health, access-control, privacy, and troubleshooting contract.
Runtime Settings
These properties can be changed on an open Database instance:
| Property | Type | Default | Description |
|---|---|---|---|
ImplicitInsertExecutionMode |
ImplicitInsertExecutionMode |
Serialized |
Shared auto-commit INSERT statements use the legacy serialized path by default; set ConcurrentWriteTransactions to route them through isolated write transactions for better low-conflict insert fan-in. This setting only changes the shared implicit INSERT path. |
PreferSyncPointLookups |
bool |
true |
Simple primary-key equality lookups use a synchronous cache-only fast path instead of the async pipeline. |
Daemon Host Configuration
CSharpDB.Daemon has a daemon-only host database section layered on top of the
normal ConnectionStrings:CSharpDB input. The daemon still uses the same
database locator, but it now builds its direct host client explicitly and
applies daemon defaults for a long-lived shared process.
Relevant keys:
| Key | Default | Description |
|---|---|---|
ConnectionStrings:CSharpDB |
Data Source=csharpdb.db |
Backing database connection string used by the daemon host |
CSharpDB:HostDatabase:OpenMode |
HybridIncrementalDurable |
HybridIncrementalDurable keeps the daemon in lazy-resident hybrid mode; Direct opens the file directly without the hybrid resident cache |
CSharpDB:HostDatabase:ImplicitInsertExecutionMode |
ConcurrentWriteTransactions |
Enables concurrent host-side implicit insert execution by default |
CSharpDB:HostDatabase:UseWriteOptimizedPreset |
true |
Applies UseWriteOptimizedPreset() to the daemon's direct host database options |
CSharpDB:HostDatabase:HotTableNames |
[] |
Optional hybrid hot-table preload hints |
CSharpDB:HostDatabase:HotCollectionNames |
[] |
Optional hybrid hot-collection preload hints |
Default daemon appsettings.json shape:
{
"ConnectionStrings": {
"CSharpDB": "Data Source=csharpdb.db"
},
"CSharpDB": {
"HostDatabase": {
"OpenMode": "HybridIncrementalDurable",
"ImplicitInsertExecutionMode": "ConcurrentWriteTransactions",
"UseWriteOptimizedPreset": true,
"HotTableNames": [],
"HotCollectionNames": []
}
}
}
Environment variable example:
$env:ConnectionStrings__CSharpDB = "Data Source=C:\\data\\app.db"
$env:CSharpDB__HostDatabase__OpenMode = "Direct"
$env:CSharpDB__HostDatabase__ImplicitInsertExecutionMode = "Serialized"
$env:CSharpDB__HostDatabase__HotTableNames__0 = "users"
Use the daemon defaults when you want a warm long-lived gRPC host. Override them only when your deployment has a measured reason to prefer direct open mode or the legacy serialized implicit-insert path.
Key Defaults Summary
| Setting | Default |
|---|---|
| Page size | 4096 bytes (fixed) |
| Durability | Durable (fsync on every commit) |
| Page cache | Unbounded (all pages retained) |
| Checkpoint threshold | 1000 committed WAL frames |
| Checkpoint execution | Foreground (inline) |
| Writer lock timeout | 5 seconds |
| Sequential read-ahead | Enabled |
| Statistics persistence | Immediate |