Namespace Manifest Management#
Overview#
LanceDB supports two complementary modes for table discovery and metadata management in local/native connections:
- Directory-listing mode (default): Tables are discovered by listing
.lancedirectories under the connection root. Table names are derived from directory names. - Manifest-enabled mode: A namespace-backed manifest is the source of truth for table metadata. This enables richer operations (versioned declares, managed versioning, hierarchical namespaces) and automatic migration from directory listing.
The central control point is the manifest_enabled boolean on ConnectRequest.
Directory-Listing Mode (Default)#
ListingDatabase is the default database backend. It discovers tables with a read_dir call and filters for paths ending in .lance . Table URIs are constructed as <base_uri>/<table_name>.lance .
ListingDatabase always carries a backing LanceNamespaceDatabase instance (namespace_database) that handles operations involving an explicit namespace_path — table operations at the root namespace bypass it and use object-store directory listing directly .
Key option constants (listing.rs):
new_table_data_storage_version— storage format version for new tablesnew_table_enable_v2_manifest_paths— enable V2 manifest paths (more efficient, requires newer clients)new_table_enable_stable_row_ids— enables stable row IDs across compaction/delete operations
manifest_enabled Configuration#
Setting manifest_enabled: true on a connection causes ConnectBuilder::execute() to call connect_manifest_enabled_namespace_database() instead of the standard connect_with_options() path . The returned connection is a LanceNamespaceDatabase directly — not a ListingDatabase.
Manifest-enabled properties injected automatically :
manifest_enabled = "true"dir_listing_to_manifest_migration_enabled = "true"— existing directory-listed tables are migrated into the manifest on access.
Restrictions for manifest-enabled connections : URI schemes with + (e.g., s3+ddb://), engine query parameters, and mirroredStore query parameters are rejected — these commit strategies are incompatible with manifest-based metadata.
Python API#
import lancedb
db = lancedb.connect("/path/to/db", manifest_enabled=True)
The Python connect() function exposes manifest_enabled: bool = False . When True, it forwards to LanceDBConnection with the flag set .
Rust API#
lancedb::connect("/path/to/db")
.manifest_enabled(true)
.execute()
.await?;
ConnectBuilder::manifest_enabled() sets the flag on ConnectRequest.
LanceNamespaceDatabase and Manifest-Based Table Management#
LanceNamespaceDatabase is the implementation used when manifest-enabled (and also when connecting via connect_namespace). It delegates all table operations to a LanceNamespace trait object.
Table lifecycle in manifest mode:
- Create: Calls
declare_table()on the namespace to reserve a location, then writes data to that location . ADeclareTableRequestconflict is resolved by inspecting whether the table is fully realized (hasversion+schema) before surfacingTableAlreadyExists. - Open: Delegates to
NativeTable::open_from_namespace(). - List: Calls
namespace.list_tables()instead ofread_dir. - Drop: Calls
namespace.drop_table().
ExternalManifestStore and Managed Versioning#
When a namespace response includes managed_versioning: Some(true), table creation installs an ExternalManifestCommitHandler as the Lance commit handler :
let external_store = LanceNamespaceExternalManifestStore::for_table_uri(
self.namespace.clone(), table_id, &location
)?;
params.commit_handler = Some(Arc::new(ExternalManifestCommitHandler {
external_manifest_store: Arc::new(external_store),
}));
LanceNamespaceExternalManifestStore— fromlance::io::commit::namespace_manifest; stores manifest version metadata in the namespace server rather than in object storage files .ExternalManifestCommitHandler— fromlance_table::io::commit::external_manifest; implementsCommitHandlerto route commits through the external store .
This enables the namespace server to serve as the version-of-record, which allows features like atomic cross-table version coordination and server-side table discovery without object-store listing.
The managed_versioning flag is activated on the namespace side. For example, setting the table_version_tracking_enabled namespace client property via namespace_client_property("table_version_tracking_enabled", "true") causes the namespace to return managed_versioning: Some(true) in describe_table responses .
Choosing a Mode#
| Scenario | Recommended mode |
|---|---|
| Simple local or cloud storage, single process | Directory listing (default) |
| Need hierarchical namespaces, atomic declares, or server-managed versioning | manifest_enabled=True or connect_namespace |
| Existing directory-listed database, want to migrate | manifest_enabled=True (migration runs automatically) |
| Custom REST/catalog namespace server | connect_namespace("rest", {...}) |
Key Source Files#
| File | Purpose |
|---|---|
rust/lancedb/src/connection.rs | ConnectRequest, ConnectBuilder, manifest_enabled entry point |
rust/lancedb/src/database/listing.rs | ListingDatabase, connect_manifest_enabled_namespace_database() |
rust/lancedb/src/database/namespace.rs | LanceNamespaceDatabase, ExternalManifestCommitHandler wiring |
python/python/lancedb/__init__.py | Python connect() with manifest_enabled param |
python/python/lancedb/namespace.py | Python connect_namespace / AsyncLanceNamespaceDBConnection |