Skip to main content
Version: 1.1.0

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.

What is 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:

┌─────────────────┐
│ Applications │
│ (Python/Java) │
└────────┬────────┘
│ HTTP/REST

┌─────────────────┐
│ Lance REST │
│ Service │
└────────┬────────┘

▼ Gravitino Client API
┌─────────────────┐
│ 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 PatternSince Version
CreateNamespaceCreate a new Lance namespacePOST/lance/v1/namespace/{id}/create1.1.0
ListNamespacesList all namespaces under a parent namespaceGET/lance/v1/namespace/{parent}/list1.1.0
DescribeNamespaceRetrieve detailed information about a specific namespacePOST/lance/v1/namespace/{id}/describe1.1.0
DropNamespaceDelete a namespacePOST/lance/v1/namespace/{id}/drop1.1.0
NamespaceExistsCheck whether a namespace existsPOST/lance/v1/namespace/{id}/exists1.1.0
ListTablesList all tables in a namespaceGET/lance/v1/namespace/{id}/table/list1.1.0
CreateTableCreate a new table in a namespacePOST/lance/v1/table/{id}/create1.1.0
DropTableDelete a table including both metadata and dataPOST/lance/v1/table/{id}/drop1.1.0
TableExistsCheck whether a table existsPOST/lance/v1/table/{id}/exists1.1.0
RegisterTableRegister an existing Lance table to a namespacePOST/lance/v1/table/{id}/register1.1.0
DeregisterTableUnregister a table from a namespace (metadata only, data remains)POST/lance/v1/table/{id}/deregister1.1.0

More details, please refer to the Lance REST API specification

Operation Details

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

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 new Lance table with schema and write metadata files
note

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

Running with Gravitino Server

To enable the Lance REST service within Gravitino server, configure the following properties in your Gravitino configuration file ${GRAVITINO_HOME}/conf/gravitino.conf:

Configuration PropertyDescriptionDefault ValueRequiredSince Version
gravitino.auxService.namesAuxiliary services to run. Include lance-rest to enable Lance REST serviceiceberg-rest,lance-restYes0.2.0
gravitino.lance-rest.classpathClasspath for Lance REST service, relative to Gravitino home directorylance-rest-server/libsYes1.1.0
gravitino.lance-rest.httpPortPort number for Lance REST service9101No1.1.0
gravitino.lance-rest.hostHostname for Lance REST service0.0.0.0No1.1.0
gravitino.lance-rest.namespace-backendNamespace metadata backend (currently only gravitino is supported)gravitinoYes1.1.0
gravitino.lance-rest.gravitino-uriGravitino server URI (required when namespace-backend is gravitino)http://localhost:8090Yes1.1.0
gravitino.lance-rest.gravitino-metalakeGravitino metalake name (required when namespace-backend is gravitino)(none)Yes1.1.0

Example Configuration:

gravitino.auxService.names = lance-rest
gravitino.lance-rest.httpPort = 9101
gravitino.lance-rest.host = 0.0.0.0
gravitino.lance-rest.namespace-backend = gravitino
gravitino.lance-rest.gravitino-uri = http://localhost:8090
gravitino.lance-rest.gravitino-metalake = my_metalake

Running Standalone

To run Lance REST service independently without Gravitino server (You need to start Gravitino server first):

{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 ValueRequiredSince Version
gravitino.lance-rest.namespace-backendNamespace metadata backendgravitinoYes1.1.0
gravitino.lance-rest.gravitino-uriGravitino server URIhttp://localhost:8090Yes1.1.0
gravitino.lance-rest.gravitino-metalakeGravitino metalake name(none)Yes1.1.0
gravitino.lance-rest.httpPortService port number9101No1.1.0
gravitino.lance-rest.hostService hostname0.0.0.0No1.1.0
tip

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

Running with Docker

Launch Lance REST service using Docker(You need to start Gravitino server first):

docker run -d --name lance-rest-service -p 9101:9101 \
-e LANCE_REST_GRAVITINO_URI=http://gravitino-host:8090 \
-e LANCE_REST_GRAVITINO_METALAKE_NAME=your_metalake_name \
-e LANCE_REST_GRAVITINO_URI=http://gravitino-host:port \
apache/gravitino-lance-rest:latest

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

Environment Variables:

Environment VariableConfiguration PropertyRequiredDefault ValueSince Version
LANCE_REST_NAMESPACE_BACKENDgravitino.lance-rest.namespace-backendYesgravitino1.1.0
LANCE_REST_GRAVITINO_METALAKE_NAMEgravitino.lance-rest.gravitino-metalakeYes(none)1.1.0
LANCE_REST_GRAVITINO_URIgravitino.lance-rest.gravitino-uriYeshttp://localhost:80901.1.0
LANCE_REST_HOSTgravitino.lance-rest.hostNo0.0.0.01.1.0
LANCE_REST_PORTgravitino.lance-rest.httpPortNo91011.1.0
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 created 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: You can 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 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

Common Delimiters:

Namespace path:     lance_catalog.schema.table01
URI representation: lance_catalog$schema$table01
URL encoded: lance_catalog%24schema%24table01
Important Limitations
  • Currently 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
  • Metadata operations require Gravitino server to be available
  • 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 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"
}'

# Create a new empty table
curl -X POST http://localhost:9101/lance/v1/table/lance_catalog%24schema%24table02/create-empty \
-H 'Content-Type: application/json' \
-d '{
"id": ["lance_catalog", "schema", "table02"],
"location": "/tmp/lance_catalog/schema/table02",
"properties": { "description": "This is table02" }
}'

# 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}"