diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 3b61d565..3d0c7356 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+### Hardening
+
+- **Auto engine selection no longer lands on PageBased (production hardening)** - with default
+ configuration (`StorageEngineType.Auto` + `WorkloadHint.General`) `GetOptimalStorageEngine`
+ returned PageBased, which is not yet OLTP-ready (measured UPDATE ~26K ops/s vs ~245K ops/s on the
+ fixed-width Columnar path). Auto selection now routes General / WriteHeavy / unknown hints to
+ AppendOnly/Columnar; PageBased remains reachable only through an explicit
+ `StorageEngineType.PageBased` until its UPDATE/DELETE fast paths reach parity. Regression tests
+ assert the mapping AND that a default database creates Columnar fixed-width PK tables that engage
+ the single-pass contiguous DELETE path (no `.pages` artifacts). Full suite 1768 tests, 0 failed.
+
### Performance
- **Fixed-width record layout is now the default for new columnar PK tables (B7)** ÔÇö
diff --git a/src/SharpCoreDB/DatabaseConfig.cs b/src/SharpCoreDB/DatabaseConfig.cs
index 34babc4d..d189fe44 100644
--- a/src/SharpCoreDB/DatabaseConfig.cs
+++ b/src/SharpCoreDB/DatabaseConfig.cs
@@ -563,9 +563,15 @@ public class DatabaseConfig
/// ✅ NEW: Smart storage selection based on workload characteristics!
/// - ReadHeavy: Optimized for SELECT queries → COLUMNAR storage
/// - Analytics: Optimized for aggregates/scans → COLUMNAR storage
- /// - WriteHeavy: Optimized for INSERT/UPDATE → PAGE_BASED storage
- /// - General: Balanced for mixed workloads → PAGE_BASED storage
- ///
+ /// - WriteHeavy: Optimized for INSERT/UPDATE → currently APPEND_ONLY/COLUMNAR too (PageBased is
+ /// opt-in only via an explicit ; see the note below)
+ /// - General: Balanced for mixed workloads → APPEND_ONLY/COLUMNAR storage (the fast, hardened path)
+ ///
+ /// NOTE (production hardening): the PageBased engine is NOT yet OLTP-ready — measured UPDATE is
+ /// ~26K ops/s vs ~245K ops/s on the fixed-width Columnar (AppendOnly) path. Auto selection
+ /// therefore routes the default General workload (and the unknown-hint fallback) to
+ /// AppendOnly/Columnar until PageBased reaches UPDATE/DELETE parity.
+ ///
/// When StorageEngineType = Auto, the engine is selected based on this hint.
///
public WorkloadHint WorkloadHint { get; init; } = WorkloadHint.General;
@@ -583,14 +589,15 @@ public Interfaces.StorageEngineType GetOptimalStorageEngine()
return StorageEngineType;
}
- // Auto-select based on workload hint
+ // Auto-select based on workload hint. PageBased is deliberately not selected for General /
+ // unknown hints (and should be treated as opt-in only) until its UPDATE/DELETE fast paths
+ // reach the fixed-width Columnar engine's parity (see class-level note).
return WorkloadHint switch
{
WorkloadHint.ReadHeavy => Interfaces.StorageEngineType.Columnar,
WorkloadHint.Analytics => Interfaces.StorageEngineType.Columnar,
- WorkloadHint.WriteHeavy => Interfaces.StorageEngineType.PageBased,
- WorkloadHint.General => Interfaces.StorageEngineType.PageBased,
- _ => Interfaces.StorageEngineType.PageBased // Default to PAGE_BASED (safest choice)
+ WorkloadHint.General => Interfaces.StorageEngineType.AppendOnly,
+ _ => Interfaces.StorageEngineType.AppendOnly
};
}
diff --git a/tests/SharpCoreDB.Tests/DefaultEngineSelectionTests.cs b/tests/SharpCoreDB.Tests/DefaultEngineSelectionTests.cs
new file mode 100644
index 00000000..855ccdc2
--- /dev/null
+++ b/tests/SharpCoreDB.Tests/DefaultEngineSelectionTests.cs
@@ -0,0 +1,96 @@
+//
+// Copyright (c) 2026 MPCoreDeveloper. All rights reserved.
+// Licensed under the MIT License. See LICENSE file in the project root for full license information.
+//
+namespace SharpCoreDB.Tests;
+
+using Microsoft.Extensions.DependencyInjection;
+using SharpCoreDB.DataStructures;
+using SharpCoreDB.Interfaces;
+using SharpCoreDB.Storage.Hybrid;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Xunit;
+
+///
+/// Production-hardening regression: a database created with DEFAULT configuration must stay on the
+/// fast, hardened path — Columnar (AppendOnly) tables with the fixed-width record layout for PK
+/// tables and the single-pass contiguous DELETE fast path — and must never silently land on the
+/// not-yet-OLTP-ready PageBased engine through the Auto/WorkloadHint selection.
+///
+public sealed class DefaultEngineSelectionTests : IDisposable
+{
+ private readonly DatabaseFactory _factory;
+ private readonly string _dirPath;
+
+ public DefaultEngineSelectionTests()
+ {
+ var services = new ServiceCollection();
+ services.AddSharpCoreDB();
+ _factory = services.BuildServiceProvider().GetRequiredService();
+ _dirPath = Path.Combine(Path.GetTempPath(), $"SCDB_DefaultEng_{Guid.NewGuid():N}");
+ }
+
+ public void Dispose()
+ {
+ try { if (Directory.Exists(_dirPath)) Directory.Delete(_dirPath, true); } catch { }
+ }
+
+ [Fact]
+ public void DefaultConfig_AutoSelection_PrefersAppendOnlyOverPageBased()
+ {
+ // Regression: WorkloadHint.General (the default) and unknown hints used to resolve Auto to
+ // PageBased, which is not OLTP-ready (measured UPDATE ~26K ops/s vs ~245K on the
+ // fixed-width Columnar path). Explicit PageBased opt-in must remain possible.
+ var config = new DatabaseConfig();
+
+ Assert.Equal(StorageEngineType.Auto, config.StorageEngineType);
+ Assert.Equal(StorageEngineType.AppendOnly, config.GetOptimalStorageEngine());
+
+ var explicitPageBased = new DatabaseConfig { StorageEngineType = StorageEngineType.PageBased };
+ Assert.Equal(StorageEngineType.PageBased, explicitPageBased.GetOptimalStorageEngine());
+ }
+
+ [Fact]
+ public void DefaultDatabase_NewPkTable_UsesColumnarFixedWidthAndContiguousDelete()
+ {
+ var db = _factory.Create(_dirPath, "pw", isReadOnly: false, config: new DatabaseConfig());
+ try
+ {
+ db.ExecuteSQL("CREATE TABLE docs (id INTEGER PRIMARY KEY, name TEXT, score REAL)");
+ Assert.True(db.TryGetTable("docs", out var t));
+ var table = Assert.IsType(t);
+
+ Assert.Equal(StorageMode.Columnar, table.StorageMode);
+ Assert.True(table.IsFixedWidthRecords, "default new PK table must use the fixed-width record layout");
+ Assert.Equal(StorageEngineType.AppendOnly, table.GetStorageEngineType());
+
+ var stmts = new List(1000);
+ for (int i = 1; i <= 1000; i++)
+ {
+ stmts.Add($"INSERT INTO docs VALUES ({i}, 'user{i}', {i * 0.5})");
+ }
+
+ db.ExecuteBatchSQL(stmts);
+ db.Flush();
+
+ var dels = new List(500);
+ for (int i = 1; i <= 500; i++)
+ {
+ dels.Add($"DELETE FROM docs WHERE id = {i}");
+ }
+
+ db.ExecuteBatchSQL(dels);
+ db.Flush();
+
+ Assert.Equal(1, table.BulkContiguousDeleteBatches); // fast path engaged on default config
+ Assert.Equal(500, db.ExecuteQuery("SELECT id FROM docs").Count);
+
+ // No PageBased .pages artifact may appear for a default Columnar table.
+ Assert.False(Directory.EnumerateFiles(_dirPath, "*.pages").Any());
+ }
+ finally { (db as IDisposable)?.Dispose(); }
+ }
+}