serviceType for Nessie. Use the generic spec-compliant adapter, catalogType=iceberg-rest, serviceType=rest, and address a specific branch/ref with catalog.iceberg-rest.prefix (Nessie’s version of a multi-catalog prefix). Data files must be Parquet.
Using AWS Glue, Amazon S3 Tables, or Unity Catalog instead? See their respective onboarding pages linked above.
How it works
Onboarding is four calls. Each one feeds the next:All paths are relative to your data-plane base URL. Set
export BASE_URL=https://dp.<data-plane-id>.cp.<region>.startree.cloud/api/pinot — the StarTree Cloud data-plane proxy that fronts the controller.If your controller requires authentication, add an Authorization header to every request — e.g. -H "Authorization: Bearer <token>". The examples below omit it for brevity.Prerequisites
- StarTree 0.16.0 or later with the External Table Beta feature enabled, and tiered storage configured on the cluster. Contact StarTree support if unsure.
- Network access to the controller REST endpoint, plus an
Authorizationtoken if your cluster requires auth. - A running Nessie server (self-hosted or managed) with its Iceberg REST API reachable — this is enabled by default on the official Nessie server/Docker image, served under
<nessie-base-url>/iceberg. - The branch/ref to query (defaults to Nessie’s server-side default, usually
main, if you don’t set one explicitly) and the namespace/table to onboard. - If your Nessie deployment sits behind auth (an OAuth2/OIDC proxy, or a static bearer token), have the credentials ready — see Authentication.
- Read access to the underlying object storage. This connector supports S3-compatible storage for the data files.
Limitations
- No dedicated
serviceTypefor Nessie — it’s reached through the generic spec-compliantrestadapter, so there’s no Nessie-specific request validation; a misconfigured branch/refprefixsurfaces as a generic REST error, not a Nessie-specific one. - No credential vending. Unlike Unity Catalog, Nessie doesn’t automatically vend short-lived storage credentials — configure static keys, an assumed role, or the cluster’s node role explicitly.
Authentication
An External Table authenticates in two places, configured independently:- Catalog (REST) — keys under
catalog.iceberg-rest.auth.rest.*. Choose one of three methods. - Storage (S3 data files) — keys under
catalog.iceberg-rest.auth.storage.*. Choose one of three methods — same mechanism used for Glue and S3 Tables.
Catalog (REST) authentication: choose one
No authentication (default for self-hosted Nessie)
Most self-hosted Nessie deployments (e.g. the quickstart Docker image) run without REST auth. Omitauth.rest.* entirely.
Bearer token
authType doesn’t need to be set explicitly — it’s auto-detected as token auth when .token is present.
OAuth2 client-credentials
Use this if your Nessie deployment sits behind an OAuth2/OIDC proxy (e.g. Keycloak) that requires a client-credentials grant.authType is optional; it’s auto-detected as oauth2 once the three required keys below are all present.
Storage authentication: choose one
Assumed IAM role (recommended for production)
No static secrets in the table config — every S3 read assumesroleArn via STS. Three things to know: auth.storage.region is required whenever a roleArn is set (the sync fails fast without it); any static auth.storage access keys are ignored once a roleArn is present; and the AssumeRole call itself authenticates with the cluster’s ambient AWS identity (node role / IRSA), so the target role’s trust policy must trust that identity (plus the externalId, if you set one).
Cluster node role
Omit everyauth.storage.* credential key — only region is required. Credential resolution falls back to the AWS SDK default chain (the node’s instance profile / IRSA role), which must already have S3 access.
Static access keys
Quick tests, or when role-based access isn’t available. Use the canonicalaccessKeyId / secretAccessKey spellings (an optional sessionToken is also accepted). Avoid the shorter accessKey/secretKey aliases: only part of the pipeline honors them (segment generation does, Iceberg manifest and data-file reads do not), so a short-alias config falls back to the cluster’s ambient credentials for catalog file reads and can fail in confusing ways.
Selecting a branch or ref
catalog.iceberg-rest.prefix pins every request to a specific Nessie branch, tag, or ref (e.g. main, a feature branch, or a commit hash) — this is the same operator-supplied “prefix” mechanism generic multi-catalog Iceberg REST servers use, applied to Nessie’s branch model. Leave it unset to use the server’s default branch.
Step 1: Validate and browse the connection
POST /connections/browse
There is no separate “validate” endpoint. Browsing the catalog is the validation step: a 200 with an items list (even an empty one) confirms your credentials and connectivity.
- Set
pathto""to browse the root — this both validates the connection and lists namespaces. - Set
pathto a namespace name to list the tables inside it.
Request
Response
Step 2: Preview the schema
POST /tables/preview
Samples the source, infers a Pinot schema, and returns an enriched table config (S3 tier, raw field configs, time column) plus sample rows. Review it, tweak if needed, then carry the schema and config forward to steps 3 and 4.
The request and response share the same JSON shape. You send a
tableConfig describing the source; the response fills in schema, the enriched tableConfigs.offline, sampled rows, and a summary.Request
Top-level fields:config.inference — how the schema is derived:
Resolution order: explicit
schema → embedded schema → inferred schema.
config.sampling — how rows are sampled:
Setting the namespace and table. Take them from the browse response — set
catalog.iceberg-rest.table.namespace / .tableName to the NAMESPACE and TABLE you selected.Use executor: controller — it’s required for the controller-watcher flow and the observability endpoints. The input tableConfig is intentionally minimal; /tables/preview returns the complete tableConfigs.offline you persist in Step 4.Response
Adjust the schema (time column, column names, null handling) before moving on.
Step 3: Create the schema
POST /schemas
Send the schema object from the preview response. Rename its schemaName to match your table.
Step 4: Create the table
POST /tables
Send the enriched tableConfigs.offline object from the preview response. Its ExternalTableSyncTask block is what marks the table as external.
schedule (cron) interval. There is no separate start call.
Quickstart: onboard a table end-to-end
The whole flow as one script. Fill in the variables at the top, run the script, and the first sync starts automatically.catalog.iceberg-rest.auth.rest.* keys from Authentication to both requests above.
Once step 6 exits 0, verify it’s queryable.
Monitor onboarding
Three read-only endpoints report ingestion progress — run status, ingestion checkpoint, and source file count — and requireexecutor=controller (set automatically). See Observability for full request and response details.
Verify it’s queryable
WhenfileOnboardingRun.status is COMPLETED and segmentsUploaded matches filesDiscovered, run a query against the broker (or the Data Portal query console) to confirm the data is live:
summary.nSourceRows (preview only samples up to ~100 rows) — confirm it’s non-zero and plausible for your dataset. If the run status is COMPLETED but the count is 0, give segments a moment to load on the servers, then recheck; if it persists, see Troubleshooting.
What’s next
Now that the table is created and data is loading, these are the highest-impact follow-up steps:- Add indexes for your query patterns. Without indexes, every query scans all remote Parquet data. Add a range index on time/numeric columns, an inverted index on low-cardinality filter columns, and a bloom filter on high-cardinality ID columns. → Indexes
-
Enable caching and preload. Set
enable.prefetch.page.cache=trueandpreload.enable=trueon the S3 tier so index data is served from local disk on repeated queries instead of re-fetched from S3. → Data and Index Caching - Protect large-scan queries from OOM. For tables that receive heavy aggregations or wide scans, enable the query OOM killer so a runaway query is killed instead of crashing the server. → Best Practices & Configs — Query OOM protection
- Monitor ongoing syncs. Use the observability endpoints to check run status, ingestion checkpoint, and source file count after each scheduled sync. → Observability
For common questions and failures, see the FAQ and Troubleshooting.

