Pangolin is an MIT-licensed lakehouse catalog written in Rust. It implements the core of the Apache Iceberg REST specification and adds multi-tenancy, Git-style branching and merging, catalog federation, credential vending and a business metadata layer.
Pangolin is alpha software. 0.6.0 is a security and correctness hardening release, and it closes a lot of real ground — but there are limitations we name plainly rather than bury. Read the production readiness status before you point anything important at it.
Passion project by Alex Merced. Contributions welcome.
If you are running 0.5.x or earlier, upgrade and rotate your credentials. 0.6.0 fixes issues that were exploitable in earlier builds:
state parameter, with no allowlist. An authorize link could deliver a valid token for the victim straight to an attacker's access log. state is now HMAC-SHA256 signed with an expiry, redirect targets are allowlisted by exact match, and the token is no longer placed in a URL at all — the callback returns a single-use code redeemed at POST /api/v1/oauth/exchange.state nonce was generated and never stored or verified. Nonces are now registered server-side, consumed exactly once, and bound to the issuing provider.PANGOLIN_JWT_SECRET fell back to a value published in the repository, so anyone could forge a Root token. The Helm chart shipped working placeholder passwords. All are gone; the server refuses to start without a strong secret./config, so a namespace or table named config was reachable unauthenticated — including its DELETE route. Matching is now structural per route segment.bcrypt::verify against every service user in every tenant. Keys now carry a public key ID (pgl_<key-id>_<secret>), making authentication one lookup plus at most one verification.Read the full advisory and hardening checklist in SECURITY.md →
assert-current-schema-id and assert-table-uuid were implemented; the rest were discarded. The important one is assert-ref-snapshot-id — without it, a writer that lost a compare-and-swap would retry against the winner's metadata and blindly re-apply its own snapshot, producing forked snapshot lineage and orphaned data files with no error ever surfaced.200 OK. All are implemented; an unrecognised update now returns 501.last_sequence_number is a monotonic counter again (A-3). It was being assigned the snapshot ID, a random 64-bit value — which can produce incorrect query results on merge-on-read tables.GET /v1/{prefix}/config returns per-warehouse configuration (A-4) instead of process-wide environment defaults, and no longer exposes credential-bearing warehouse properties./v1/* use the Iceberg error envelope (A-6), so engines can tell NoSuchTableException from CommitFailedException and retry correctly.PANGOLIN_JWT_SECRET is required. Generate one with openssl rand -base64 48. Setting it ends every existing session, which is intended.PANGOLIN_OAUTH_REDIRECT_URIS.PANGOLIN_ALLOW_LEGACY_API_KEYS=true.PANGOLIN_ADMIN_PASSWORD; there is no default. POST /api/v1/users/login no longer has default root credentials./health/live and /health/ready.501 where they previously returned 200 OK and did nothing — a client that appeared to work may now surface a real error.Implements the core of the Iceberg REST spec — namespace and table CRUD, commits with full requirement enforcement, and credential vending. Not the whole spec yet; see the coverage list.
A single static binary with a low resource footprint and no runtime to install. unsafe_code = "forbid" across the workspace. No published benchmark figures yet.
Tenant scope is a required parameter throughout. Isolation is verified by tests running against the production auth middleware, not a test-only wrapper.
Branch, tag and merge catalogs for safe experimentation, with 3-way merge and conflict detection. Merge direction and branch-asset tracking were fixed in 0.6.0.
Native support for AWS S3, Azure Blob Storage and Google Cloud Storage, configured per warehouse rather than per process.
Vends scoped, temporary credentials to compute engines — AWS STS, Azure SAS and GCP downscoped tokens — so engines never hold long-lived keys.
PostgreSQL (recommended), SQLite, MongoDB (beta) or in-memory. Feature parity varies by backend.
Role- and tag-based access control, plus API-key service users for CI/CD and ETL. Keys carry a key ID, so authentication is a single bcrypt verification.
40+ actions across 19 resource types, plus authentication events from 0.6.0. Writes are best-effort and records are not yet tamper-evident.
New in 0.6.0 Prometheus metrics at /metrics, request correlation IDs, a working RUST_LOG, JSON logs, and real liveness/readiness endpoints.
Connect external Iceberg REST catalogs and proxy them transparently, so one endpoint fronts several sources.
A SvelteKit management UI, pangolin-admin and pangolin-user CLIs, and the PyPangolin client on PyPI — all versioned together at 0.6.0.
The honest version. Pangolin is pre-1.0 software under active hardening — a capable catalog that we would not yet tell you to put in front of a production data lake without reading this.
assert-ref-snapshot-id. This is the one path that is genuinely safe under concurrent writers.cargo test --workspace previously executed zero.id_token validation, no JWKS, no discovery, no email_verified check.loadNamespaceMetadata, namespaceExists, registerTable, commitTransaction and most of the view API.Silent, 36–40 second explainers covering what Pangolin is, how it is built, what changed in 0.6.0, and how ready it really is.
These videos have no audio track. Play them muted, on loop, or with the controls — whichever you prefer.
A SvelteKit interface for administrators and data explorers, versioned alongside the server at 0.6.0.
A Python library for Pangolin with PyIceberg integration, multi-format support and secure database connection management.
Available on PyPI: pip install pypangolin
PyPangolin provides a Python interface to Pangolin's catalog, governance and Git-style operations, plus support for common table formats and database connections.
View on PyPI → Documentation →PyIceberg integration with read/write operations
✅ TestedRead/write Delta tables with automatic registration
✅ TestedRegister and manage Hudi tables
SupportedRegister and track Paimon tables
SupportedRead/write Parquet files with metadata
✅ TestedRead/write structured files
✅ TestedRead/write vector database format
✅ TestedHigh-performance columnar format
SupportedStore and manage database credentials with Fernet encryption
Encrypted credential storage
✅ TestedSecure connection sharing
✅ TestedNoSQL database connections
✅ TestedCloud data warehouse
⚠️ UntestedAWS data warehouse
⚠️ UntestedGoogle Cloud analytics
⚠️ UntestedMicrosoft analytics service
⚠️ UntestedArrow Flight connections
✅ TestedRBAC, permissions, service users, and business metadata
Audit logging, search, token management, and system config
Connect to remote Iceberg catalogs and create SQL views
Branching, merging, tagging with conflict resolution
Pangolin is alpha, and being honest about that means pointing you elsewhere when that is the right answer. If you need a catalog you can put in front of a production lakehouse right now, start with these.
The production-grade, community-run lakehouse catalog. Best for large-scale open source deployments.
Visit Polaris →A managed version of Polaris with a built-in semantic layer, federated queries, and AI-powered autonomous optimization.
Try Dremio Cloud →Discuss Pangolin, Iceframe, and Dremioframe in the #pangolin-catalog channel on the Data Lakehouse Hub Slack.
Join Slack