Skip to main content

Lance REST service

Overview​

The Lance REST service provides a RESTful interface for managing Lance datasets through HTTP endpoints. Introduced in Gravitino version 1.1.0, this service enables seamless interaction with Lance datasets for data operations and metadata management.

The service implements the Lance REST API specification. For detailed specification documentation, see the official Lance REST documentation.

About Lance​

Lance is a modern columnar data format designed for AI/ML workloads. It provides:

  • High-performance vector search: Native support for similarity search on high-dimensional embeddings
  • Columnar storage: Optimized for analytical queries and machine learning pipelines
  • Fast random access: Efficient row-level operations unlike traditional columnar formats
  • Version control: Built-in dataset versioning and time-travel capabilities
  • Incremental updates: Append and update data without full rewrites

Architecture​

The Lance REST service acts as a bridge between Lance datasets and applications:

Lance REST service architecture
┌─────────────────┐
│ Applications │
│ (Python/Java) │
└────────┬────────┘
│ HTTP/REST
▼
┌─────────────────┐
│ Lance REST │
│ Service │
└────────┬────────┘
│
▼ Gravitino internal API or HTTP client
┌─────────────────┐
│ Gravitino Server │
│(Metadata Backend)│
└────────┬────────┘
│ File System Operations
▼
┌─────────────────┐
│ Lance Datasets │
│ (S3/GCS/Local) │
└─────────────────┘

Key Features:

  • Full compliance with Lance REST API specification
  • Can run standalone or integrated with Gravitino server
  • Support for namespace and table management
  • Index creation and management capabilities (Index operations are not supported in version 1.1.0)
  • Metadata stored in Gravitino for unified governance

Supported operations​

The Lance REST service provides comprehensive support for namespace management, table management, and index operations. The table below lists all supported operations:

OperationDescriptionHTTP MethodEndpoint Pattern
CreateNamespaceCreate a new Lance namespacePOST/lance/v1/namespace/{id}/create
ListNamespacesList all namespaces under a parent namespaceGET/lance/v1/namespace/{parent}/list
DescribeNamespaceRetrieve detailed information about a specific namespacePOST/lance/v1/namespace/{id}/describe
DropNamespaceDelete a namespacePOST/lance/v1/namespace/{id}/drop
NamespaceExistsCheck whether a namespace existsPOST/lance/v1/namespace/{id}/exists
ListTablesList all tables in a namespaceGET/lance/v1/namespace/{id}/table/list
CreateTableCreate a new table in a namespacePOST/lance/v1/table/{id}/create
DescribeTableDescribe an existing Lance tablePOST/lance/v1/table/{id}/describe
DropTableDelete a table including both metadata and dataPOST/lance/v1/table/{id}/drop
TableExistsCheck whether a table existsPOST/lance/v1/table/{id}/exists
RegisterTableRegister an existing Lance table to a namespacePOST/lance/v1/table/{id}/register
DeregisterTableUnregister a table from a namespace (metadata only, data remains)POST/lance/v1/table/{id}/deregister
DeclareTableDeclare a table and store the metadata without touching lance table data.POST/lance/v1/table/{id}/declare

For more details, refer to the Lance REST API specification.

Operation details​

Some operations have specific behaviors and modes. Below are important details to consider:

Mode values are parsed case-insensitively. The examples below use lowercase values as the REST-style canonical form.

Namespace operations​

CreateNamespace supports three modes:

  • create: Fails if namespace already exists
  • exist_ok: Succeeds even if namespace exists
  • overwrite: Replaces existing namespace

DropNamespace behavior:

  • Recursively deletes all child namespaces and tables
  • Deletes both metadata and Lance data files
  • Operation is irreversible

Table operations​

RegisterTable vs CreateTable:

  • RegisterTable: Links existing Lance datasets into Gravitino catalog without data movement
  • CreateTable: Creates a new Lance table with a schema and writes metadata files

The version field of CreateTable response is always null, which stands for the latest version.

DropTable vs DeregisterTable:

  • DropTable: Permanently deletes metadata and data files from storage
  • DeregisterTable: Removes metadata from Gravitino but preserves Lance data files

Deployment​

Run with Gravitino server​

To enable the Lance REST service within Gravitino server, set the following properties through the chart values in my-values.yaml and re-run the helm upgrade --install command:

Configuration PropertyDescriptionDefault ValueRequired
gravitino.auxService.namesAuxiliary services to run. Include lance-rest to enable Lance REST serviceiceberg-rest,lance-restYes
gravitino.lance-rest.classpathClasspath for Lance REST service, relative to Gravitino home directorylance-rest-server/libsYes
gravitino.lance-rest.httpPortPort number for Lance REST service9101No
gravitino.lance-rest.hostHostname for Lance REST service0.0.0.0No
gravitino.lance-rest.namespace-backendNamespace metadata backend (currently only gravitino is supported)gravitinoYes
gravitino.lance-rest.gravitino-uriGravitino server URI. Not required in auxiliary mode.http://localhost:8090No
gravitino.lance-rest.gravitino-metalakeGravitino metalake name (required when namespace-backend is gravitino)(none)Yes

The chart sets gravitino.auxService.names from the value of the same name, and each gravitino.lance-rest.* property above from the matching value under gravitino.lanceRest: classpath, host, httpPort, namespaceBackend, gravitinoUri and gravitinoMetalake. The chart's defaults match the table and already include lance-rest in gravitino.auxService.names, so the metalake is usually the only value to set:

my-values.yaml
gravitino:
lanceRest:
gravitinoMetalake: "{metalake}"

In auxiliary mode, gravitino.lance-rest.gravitino-uri is not required because the Lance REST service uses Gravitino's internal API.

Authentication to the Gravitino Server

The Lance REST service makes its own requests to the Gravitino server. Those requests must carry credentials, otherwise the Gravitino server rejects them and every Lance operation fails. The service reaches Gravitino with oauth2 or simple, of which Datastrato Enterprise accepts only oauth2. Configure it to match the Gravitino server:

Configuration PropertyDescriptionDefault ValueRequired
gravitino.lance-rest.gravitino-auth-typeAuth type used to reach the Gravitino server. Supported values: simple, oauth2simpleNo
gravitino.lance-rest.gravitino-oauth2.server-uriOAuth server URI(none)Yes, for oauth2
gravitino.lance-rest.gravitino-oauth2.credentialCredential used to request the OAuth token(none)Yes, for oauth2
gravitino.lance-rest.gravitino-oauth2.token-pathPath on the OAuth server used to request the token(none)Yes, for oauth2
gravitino.lance-rest.gravitino-oauth2.scopeScope of the requested OAuth token(none)Yes, for oauth2

These properties have no dedicated chart value. Set them under gravitino.additionalConfigItems as quoted strings; see Set Other Server Properties.

my-values.yaml
gravitino:
additionalConfigItems:
gravitino.lance-rest.gravitino-auth-type: "oauth2"
gravitino.lance-rest.gravitino-oauth2.server-uri: "{oauth_server_uri}"
gravitino.lance-rest.gravitino-oauth2.credential: "{client_id}:{client_secret}"
gravitino.lance-rest.gravitino-oauth2.token-path: "{token_path}"
gravitino.lance-rest.gravitino-oauth2.scope: "{scope}"

These properties control how the service authenticates to the Gravitino server. They do not change how callers authenticate to the Lance REST service itself.

Run standalone​

To run the Lance REST service independently of the Gravitino server (the Gravitino server must already be running):

Start the standalone service
{GRAVITINO_HOME}/bin/gravitino-lance-rest-server.sh start

Configure the service by editing {GRAVITINO_HOME}/conf/gravitino-lance-rest-server.conf or passing command-line arguments:

Configuration PropertyDescriptionDefault ValueRequired
gravitino.lance-rest.namespace-backendNamespace metadata backendgravitinoYes
gravitino.lance-rest.gravitino-uriGravitino server URIhttp://localhost:8090Yes
gravitino.lance-rest.gravitino-metalakeGravitino metalake name(none)Yes
gravitino.lance-rest.httpPortService port number9101No
gravitino.lance-rest.hostService hostname0.0.0.0No

In standalone deployments, you only need to configure gravitino.lance-rest.gravitino-metalake, gravitino.lance-rest.gravitino-uri, and other properties can use their default values.

Run with Docker​

Launch the Lance REST service using Docker (the Gravitino server must already be running):

Run the service in Docker
docker run -d --name lance-rest-service -p 9101:9101 \
-e LANCE_REST_GRAVITINO_METALAKE_NAME={metalake_name} \
-e LANCE_REST_GRAVITINO_URI=http://{gravitino_host}:{gravitino_port} \
apache/gravitino-lance-rest:latest

Access the service at http://localhost:9101.

Environment Variables:

Environment VariableConfiguration PropertyRequiredDefault Value
LANCE_REST_NAMESPACE_BACKENDgravitino.lance-rest.namespace-backendYesgravitino
LANCE_REST_GRAVITINO_METALAKE_NAMEgravitino.lance-rest.gravitino-metalakeYes(none)
LANCE_REST_GRAVITINO_URIgravitino.lance-rest.gravitino-uriYeshttp://localhost:8090
LANCE_REST_HOSTgravitino.lance-rest.hostNo0.0.0.0
LANCE_REST_PORTgravitino.lance-rest.httpPortNo9101

Configuration tips.

  • Required: Set LANCE_REST_GRAVITINO_METALAKE_NAME to your Gravitino metalake name
  • Conditional: Update LANCE_REST_GRAVITINO_URI if Gravitino server is not on localhost in the Docker instance.
  • Optional: Other variables can use default values unless you have specific requirements

Usage guidelines​

When using Lance REST service with Gravitino backend, keep the following considerations in mind:

Prerequisites​

  • A running Gravitino server with a metalake

Namespace hierarchy​

Gravitino follows a three-level hierarchy: catalog → schema → table. When creating namespaces or tables:

  1. Parent must exist: Before creating lance_catalog/schema, ensure lance_catalog catalog exists in Gravitino metalake.
  2. Two-level limit: Create namespace lance_catalog/schema, but not lance_catalog/schema/sub_schema.
  3. Table placement: Tables can only be created under lance_catalog/schema, not at catalog level.
Example namespace hierarchy
metalake
└── lance_catalog (catalog - create via REST)
└── schema (namespace - create via REST)
└── table01 (table - create via REST)

Delimiter convention​

The Lance REST API uses $ as the default delimiter to separate namespace levels in URIs. When making HTTP requests:

  • URL Encoding Required: $ must be URL-encoded as %24
  • Example: lance_catalog$schema$table01 becomes lance_catalog%24schema%24table01 in URLs
Delimiter representations
Namespace path:     lance_catalog.schema.table01
URI representation: lance_catalog$schema$table01
URL encoded: lance_catalog%24schema%24table01

Important limitations.

  • Supports only two levels of namespaces before tables
  • Tables cannot be nested deeper than schema level
  • Parent catalog must be created in Gravitino before using Lance REST API
  • Namespace deletion is recursive and irreversible

Examples​

The following examples demonstrate how to interact with Lance REST service using different programming languages and tools.

Prerequisites:

  • Gravitino server is running with Lance REST service enabled.
  • A metalake has been created in Gravitino.
Create namespaces and tables
# Create a catalog-level namespace
# mode: "create" | "exist_ok" | "overwrite" for create namespace/table; mode: "create" | "overwrite" for register table
curl -X POST http://localhost:9101/lance/v1/namespace/lance_catalog/create \
-H 'Content-Type: application/json' \
-d '{
"id": ["lance_catalog"],
"mode": "create"
}'

# Create a schema namespace
# Note: %24 is URL-encoded '$' character used as delimiter
curl -X POST http://localhost:9101/lance/v1/namespace/lance_catalog%24schema/create \
-H 'Content-Type: application/json' \
-d '{
"id": ["lance_catalog", "schema"],
"mode": "create"
}'

# Register an existing table
curl -X POST http://localhost:9101/lance/v1/table/lance_catalog%24schema%24table01/register \
-H 'Content-Type: application/json' \
-d '{
"id": ["lance_catalog", "schema", "table01"],
"location": "/tmp/lance_catalog/schema/table01",
"mode": "create"
}'

# Declare a table
curl -X POST http://localhost:9101/lance/v1/table/lance_catalog%24schema%24table04/declare \
-H 'Content-Type: application/json' \
-d '{
"id": ["lance_catalog", "schema", "table04"],
"location": "/tmp/lance_catalog/schema/table04"
}'

# Create a table with schema, the schema is inferred from the Arrow IPC file
curl -X POST \
"http://localhost:9101/lance/v1/table/lance_catalog%24schema%24table03/create" \
-H 'Content-Type: application/vnd.apache.arrow.stream' \
-H "x-lance-table-location: /tmp/lance_catalog/schema/table03" \
-H "x-lance-table-properties: {}" \
--data-binary "@${ARROW_FILE}"

Integration with Lance REST​

To use the Lance REST service with Apache Spark, Ray and other engines, refer to lance-rest-integration for more details.