Namespace Layer Architecture#
LanceDB's namespace layer is the subsystem responsible for managing table metadata, discovery, and location resolution. It sits between the Connection API and the physical Lance datasets, and can operate in two modes: directory-listing (default) or manifest-enabled. Both ultimately delegate to LanceNamespaceDatabase, which wraps a LanceNamespace trait object from the external lance_namespace_impls crate.
Connection Routing#
The routing decision happens in ConnectBuilder::execute():
db://URIs → remote (RemoteDatabase)manifest_enabled: true→ callsListingDatabase::connect_manifest_enabled_namespace_database(), returns aLanceNamespaceDatabasedirectly- default → calls
ListingDatabase::connect_with_options(), returns aListingDatabase(which still embeds aLanceNamespaceDatabasefor child-namespace operations)
The manifest_enabled flag lives on ConnectRequest and is set via ConnectBuilder::manifest_enabled().
ConnectBuilder::execute()
├── db:// URI → RemoteDatabase
├── manifest_enabled=true → connect_manifest_enabled_namespace_database()
│ └── LanceNamespaceDatabase ("dir" impl)
└── default → connect_with_options()
└── ListingDatabase
└── [embedded] LanceNamespaceDatabase (for child namespaces)
For direct namespace connections (bypassing the URI-based path entirely), use connect_namespace(ns_impl, properties), which produces a ConnectNamespaceBuilder that calls LanceNamespaceDatabase::connect() directly.
Initialization Path#
Standard mode#
ListingDatabase::connect_namespace_database() is called during ListingDatabase construction to create the embedded namespace database. It:
- Builds namespace client properties via
build_namespace_client_properties(), settingrootto the URI and prefixing storage options withstorage. - Calls
LanceNamespaceDatabase::connect("dir", ...), which instantiates aConnectBuilderfromlance_namespace_impls
Manifest-enabled mode#
connect_manifest_enabled_namespace_database() additionally injects two properties before connecting :
manifest_enabled = "true"— makes the namespace the source of truth for table metadatadir_listing_to_manifest_migration_enabled = "true"— automatically migrates existing directory-listed tables into the manifest on first access
URI restrictions apply: schemes containing + (e.g. s3+ddb://), engine query parameters, and mirroredStore are rejected because they conflict with manifest-based commit management .
Delegation to lance_namespace_impls::ConnectBuilder#
Inside LanceNamespaceDatabase::connect_with_new_table_config() :
- Creates
lance_namespace_impls::ConnectBuilder::new(ns_impl) - Iterates over
ns_propertiesand calls.property(key, value)for each - Optionally installs a
Sessionvia.session() - Installs a
ReadFreshnessContextProviderfor read consistency - Calls
.connect().awaitto obtain theArc<dyn LanceNamespace>trait object
The resulting LanceNamespaceDatabase stores the namespace client alongside storage options, read consistency interval, pushdown operation set, and new-table config .
LanceNamespaceDatabase – Core Structure#
LanceNamespaceDatabase implements the Database trait. Its fields:
| Field | Purpose |
|---|---|
namespace: Arc<dyn LanceNamespace> | Delegate for all metadata operations |
storage_options | Inherited by all tables |
read_consistency_interval | Controls read freshness |
session | Object-store registry / cache sharing |
pushdown_operations | Operations routed to the namespace server (e.g. QueryTable, CreateTable) |
ns_impl / ns_properties | Impl type (e.g. "dir", "rest") and properties for client reconstruction |
new_table_config | Storage version, V2 manifest paths, stable row IDs defaults |
freshness_baselines | Shared baseline map for read-freshness keying |
delimiter | Separator for table ID key construction (default "$") |
Table operation dispatch:
- List:
namespace.list_tables() - Create:
namespace.declare_table()→ write data →NativeTable::create_from_namespace() - Open:
NativeTable::open_from_namespace() - Drop:
namespace.drop_table() - Rename:
namespace.rename_table()
clone_table is explicitly not supported on namespace connections.
Managed Versioning#
When describe_table or declare_table returns managed_versioning: Some(true), table creation installs ExternalManifestCommitHandler as the Lance commit handler . This routes all version writes through LanceNamespaceExternalManifestStore (from lance::io::commit::namespace_manifest), making the namespace server — not the object store — the version-of-record.
Activated by setting namespace_client_property("table_version_tracking_enabled", "true") on the connection .
Python API#
Python exposes two entry points in namespace.py:
connect_namespace(ns_impl, properties, ...)→ syncLanceNamespaceDBConnectionconnect_namespace_async(ns_impl, properties, ...)→AsyncLanceNamespaceDBConnection
For "dir" and "rest" impls, these call the Rust-native _connect_namespace binding; other impls fall back to constructing a Python LanceNamespace client and passing it to the Rust layer via _connect_namespace_client .
Key Source Files#
| File | Role |
|---|---|
rust/lancedb/src/connection.rs | ConnectRequest, ConnectBuilder, connect_namespace(), ConnectNamespaceBuilder |
rust/lancedb/src/database/namespace.rs | LanceNamespaceDatabase, ExternalManifestCommitHandler wiring |
rust/lancedb/src/database/listing.rs | ListingDatabase, connect_namespace_database(), connect_manifest_enabled_namespace_database() |
python/python/lancedb/namespace.py | Python connect_namespace, LanceNamespaceDBConnection, AsyncLanceNamespaceDBConnection |