<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw" -->

---
title: Two Iceberg Clients, One Protocol: Where the Time Goes
description: A detailed benchmark compares the Rust client (iceberg-catalog-rest 0.10.1) and Python client (pyiceberg 0.12.0) for Apache Iceberg REST catalogs, testing...
canonical: https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw
twitter:card: summary_large_image
twitter:site: @dailydotdev
og:type: website
og:site_name: daily.dev
og:title: Two Iceberg Clients, One Protocol: Where the Time Goes | daily.dev
og:description: A detailed benchmark compares the Rust client (iceberg-catalog-rest 0.10.1) and Python client (pyiceberg 0.12.0) for Apache Iceberg REST catalogs, testing...
og:url: https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw
og:image: https://api.daily.dev/og/posts/WrxhDEMfw.png
og:image:alt: Two Iceberg Clients, One Protocol: Where the Time Goes
og:image:width: 1200
og:image:height: 630
og:locale: en
---

> ## Documentation Index
> Fetch the complete documentation index at: https://daily.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Two Iceberg Clients, One Protocol: Where the Time Goes

**[Medium](https://daily.dev/sources/medium_js)** · 9 min read · 0 upvotes · 0 comments

## Summary

A detailed benchmark compares the Rust client (iceberg-catalog-rest 0.10.1) and Python client (pyiceberg 0.12.0) for Apache Iceberg REST catalogs, testing against Apache Polaris, Google BigLake, and Microsoft OneLake. Locally, Rust is 1.90x to 4.29x faster on small calls, with 85-90% of that gap traced to the HTTP library (reqwest vs requests). Over the internet, per-call differences disappear (0.90x-1.04x), but Python's startup remains 507-776 ms slower, dominated by library import time (~340-366 ms). A notable finding: pyiceberg's load_table is 4x slower on OneLake because it requests a vended storage credential by default via an X-Iceberg-Access-Delegation header, which the Rust client never sends. Recommendation: pick by features for long-running services, but choose Rust for CLIs, Lambda functions, or short-lived agents where startup time matters.

## Full article

daily.dev links to this article rather than hosting it. Read it at the original source: <https://xbill999.medium.com/two-iceberg-clients-one-protocol-where-the-time-goes-1fcc454a93b4>

## Questions this post answers

### Why is pyiceberg's load_table so much slower than the Rust Iceberg client on Microsoft OneLake?

pyiceberg sends the X-Iceberg-Access-Delegation: vended-credentials header by default, asking the catalog to include a temporary storage credential with the table response. On OneLake this adds roughly 108.5 to 111.9 milliseconds, making load_table 4.12x to 4.62x slower than the Rust client, which sends no such header and never requests a credential. Removing the header brings pyiceberg's time to 36.6 ms, inside the Rust client's 36.3-39.0 ms range.

_When comparing Iceberg catalog clients for a real workload, track findings like this vended-credentials overhead on daily.dev._

### How much of the speed difference between Rust and Python Iceberg clients comes from the HTTP library itself?

Roughly 85% to 90% of the local call-time gap between the Rust client (iceberg-catalog-rest 0.10.1) and pyiceberg 0.12.0 comes down to the HTTP library. Rust's reqwest completes the same raw HTTP request in 269.8 to 479.7 microseconds versus 864.3 to 1286.4 microseconds for Python's requests library, while pyiceberg's own post-processing (JSON parsing, object building) adds only 57.3 to 134.7 microseconds.

_Developers weighing Rust versus Python for latency-sensitive clients can follow benchmarks like this on daily.dev._

### How much slower does a Python Iceberg client start up compared to a Rust one, and why does it matter?

A pyiceberg 0.12.0 process starts 507.2 to 776.2 milliseconds slower than the Rust iceberg-catalog-rest client on every catalog tested, mostly from importing the library (337.9 to 366.3 milliseconds locally). This startup cost is negligible for a long-running service but matters for a CLI, a Lambda function, or a short-lived agent, where it's paid on every invocation.

_Teams picking a client for short-lived functions can weigh startup overhead data like this via daily.dev._

## Similar posts on daily.dev

- [Apache Iceberg 1.12 and Rust 0.11: What's New](https://daily.dev/posts/apache-iceberg-1-12-and-rust-0-11-what-s-new-zfzjpbdok) · Dremio Blog · 14 upvotes · 1 comments
- [Apache Polaris with PyIceberg: A Guide](https://daily.dev/posts/apache-polaris-with-pyiceberg-a-guide-ykkijp45z) · Dremio Blog · 0 upvotes · 0 comments
- [Google Cloud Introduces Cross-Engine Iceberg Support in BigQuery](https://daily.dev/posts/google-cloud-introduces-cross-engine-iceberg-support-in-bigquery-iuk5rijpt) · InfoQ · 0 upvotes · 1 comments
- [Explore public datasets with Apache Iceberg & BigLake](https://daily.dev/posts/explore-public-datasets-with-apache-iceberg-biglake-tn371fitl) · Google Open Source Blog · 1 upvotes · 0 comments

---

Tags: [#python](https://daily.dev/tags/python), [#performance](https://daily.dev/tags/performance), [#rust](https://daily.dev/tags/rust), [#data-engineering](https://daily.dev/tags/data-engineering), [#apache-iceberg](https://daily.dev/tags/apache-iceberg)

[View this post on daily.dev](https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw)

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180},"sameAs":["https://twitter.com/dailydotdev","https://github.com/dailydotdev","https://www.linkedin.com/company/daily-dev-ltd"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}}]}
{"@context":"https://schema.org","@type":"TechArticle","headline":"Two Iceberg Clients, One Protocol: Where the Time Goes","url":"https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw","mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw"},"datePublished":"2026-10-02T21:01:48.138Z","dateModified":"2026-10-02T21:09:58.007Z","description":"A detailed benchmark compares the Rust client (iceberg-catalog-rest 0.10.1) and Python client (pyiceberg 0.12.0) for Apache Iceberg REST catalogs, testing...","image":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/05ce7177b07e45d51bddcd8bc13c7109?_a=AQAEuop","thumbnailUrl":"https://media.daily.dev/image/upload/f_auto,q_auto/v1/posts/05ce7177b07e45d51bddcd8bc13c7109?_a=AQAEuop","isAccessibleForFree":true,"articleSection":"Medium","inLanguage":"en","publisher":{"@type":"Organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/apple-touch-icon.png","width":180,"height":180}},"author":{"@type":"Organization","name":"Medium","logo":"https://media.daily.dev/image/upload/t_logo,f_auto/v1/logos/medium","url":"https://daily.dev/sources/medium_js"},"commentCount":0,"discussionUrl":"https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw","interactionStatistic":[{"@type":"InteractionCounter","interactionType":{"@type":"LikeAction"},"userInteractionCount":0},{"@type":"InteractionCounter","interactionType":{"@type":"CommentAction"},"userInteractionCount":0}],"keywords":"python,performance,rust,data-engineering,apache-iceberg","timeRequired":"PT9M"}
{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev"},{"@type":"ListItem","position":2,"name":"Medium","item":"https://daily.dev/sources/medium_js"},{"@type":"ListItem","position":3,"name":"Two Iceberg Clients, One Protocol: Where the Time Goes"}]}
{"@context":"https://schema.org","@type":"FAQPage","@id":"https://daily.dev/posts/two-iceberg-clients-one-protocol-where-the-time-goes-wrxhdemfw#faq","mainEntity":[{"@type":"Question","name":"Why is pyiceberg's load_table so much slower than the Rust Iceberg client on Microsoft OneLake?","acceptedAnswer":{"@type":"Answer","text":"pyiceberg sends the X-Iceberg-Access-Delegation: vended-credentials header by default, asking the catalog to include a temporary storage credential with the table response. On OneLake this adds roughly 108.5 to 111.9 milliseconds, making load_table 4.12x to 4.62x slower than the Rust client, which sends no such header and never requests a credential. Removing the header brings pyiceberg's time to 36.6 ms, inside the Rust client's 36.3-39.0 ms range. When comparing Iceberg catalog clients for a real workload, track findings like this vended-credentials overhead on daily.dev."}},{"@type":"Question","name":"How much of the speed difference between Rust and Python Iceberg clients comes from the HTTP library itself?","acceptedAnswer":{"@type":"Answer","text":"Roughly 85% to 90% of the local call-time gap between the Rust client (iceberg-catalog-rest 0.10.1) and pyiceberg 0.12.0 comes down to the HTTP library. Rust's reqwest completes the same raw HTTP request in 269.8 to 479.7 microseconds versus 864.3 to 1286.4 microseconds for Python's requests library, while pyiceberg's own post-processing (JSON parsing, object building) adds only 57.3 to 134.7 microseconds. Developers weighing Rust versus Python for latency-sensitive clients can follow benchmarks like this on daily.dev."}},{"@type":"Question","name":"How much slower does a Python Iceberg client start up compared to a Rust one, and why does it matter?","acceptedAnswer":{"@type":"Answer","text":"A pyiceberg 0.12.0 process starts 507.2 to 776.2 milliseconds slower than the Rust iceberg-catalog-rest client on every catalog tested, mostly from importing the library (337.9 to 366.3 milliseconds locally). This startup cost is negligible for a long-running service but matters for a CLI, a Lambda function, or a short-lived agent, where it's paid on every invocation. Teams picking a client for short-lived functions can weigh startup overhead data like this via daily.dev."}}]}
```

