ArrowFEBE
v0.3.8Linux · Windows (x64)PostgreSQL-compatible services
A pure-native ADBC driver for PostgreSQL that speaks the Frontend/Backend
(FEBE) wire protocol v3 directly over TCP/TLS and delivers Apache Arrow
RecordBatches end to end. OpenSSL is the only runtime dependency beyond libc —
it does not use libpq.
note
Reading these docs. The badge above is the version this documentation describes. Options and features added recently are flagged inline with a Since vX.Y.Z note; the What's new page is the release-by-release view. See Versioning.
Highlights
- Native FEBE v3 over TCP/TLS — PostgreSQL 12–17, no libpq.
- NUMERIC without a string detour — Postgres
NUMERICmaps straight to Arrowdecimal128/decimal256, a headline speed and fidelity win. - Full auth surface — SCRAM-SHA-256 (with channel binding), MD5, cleartext,
GSSAPI/Kerberos, SSPI, plus
gssencmodeGSS transport encryption. - Arrow straight from the wire — results decode into Arrow column buffers with no intermediate row objects.
Connect in seconds
Load the driver by name (arrowfebe) from any ADBC client:
- Python
- C / C++
- C#
- Go
- Java
- R
- Rust
import adbc_driver_manager.dbapi as dbapi
with dbapi.connect(driver="arrowfebe",
db_kwargs={"uri": "postgresql://user:<pw>@host:5432/mydb?sslmode=require"}) as conn:
cur = conn.cursor()
cur.execute("SELECT * FROM public.orders")
table = cur.fetch_arrow_table()
#include <arrow-adbc/adbc.h>
// (error checks elided for brevity)
AdbcError e = {}; AdbcDatabase db = {}; AdbcConnection conn = {}; AdbcStatement st = {};
AdbcDatabaseNew(&db, &e);
AdbcDatabaseSetOption(&db, "driver", "arrowfebe", &e);
AdbcDatabaseSetOption(&db, "uri", "postgresql://user:<pw>@host:5432/mydb?sslmode=require", &e);
AdbcDatabaseInit(&db, &e);
AdbcConnectionNew(&conn, &e); AdbcConnectionInit(&conn, &db, &e);
AdbcStatementNew(&conn, &st, &e);
AdbcStatementSetSqlQuery(&st, "SELECT * FROM public.orders", &e);
ArrowArrayStream stream = {}; int64_t n = -1;
AdbcStatementExecuteQuery(&st, &stream, &n, &e); // consume `stream`
using Apache.Arrow.Adbc;
using Apache.Arrow.Adbc.DriverManager;
using var driver = AdbcDriverManager.FindLoadDriver("arrowfebe", loadOptions: AdbcLoadFlags.Default);
using var database = driver.Open(new Dictionary<string, string> {
["uri"] = "postgresql://user:<pw>@host:5432/mydb?sslmode=require" });
using var connection = database.Connect(null);
using var statement = connection.CreateStatement();
statement.SqlQuery = "SELECT * FROM public.orders";
using var stream = statement.ExecuteQuery().Stream!; // IArrowArrayStream
var drv drivermgr.Driver
db, _ := drv.NewDatabase(map[string]string{
"driver": "arrowfebe",
adbc.OptionKeyURI: "postgresql://user:<pw>@host:5432/mydb?sslmode=require",
})
conn, _ := db.Open(ctx)
stmt, _ := conn.NewStatement()
_ = stmt.SetSqlQuery("SELECT * FROM public.orders")
reader, _, _ := stmt.ExecuteQuery(ctx) // array.RecordReader
defer reader.Release()
Map<String, Object> params = new HashMap<>();
JniDriver.PARAM_DRIVER.set(params, "arrowfebe");
AdbcDriver.PARAM_URI.set(params, "postgresql://user:<pw>@host:5432/mydb?sslmode=require");
try (BufferAllocator a = new RootAllocator();
AdbcDatabase db = new JniDriver(a).open(params);
AdbcConnection conn = db.connect();
AdbcStatement st = conn.createStatement()) {
st.setSqlQuery("SELECT * FROM public.orders");
try (AdbcStatement.QueryResult r = st.executeQuery()) {
ArrowReader reader = r.getReader();
}
}
library(adbcdrivermanager)
db <- adbc_database_init(adbc_driver("arrowfebe"),
uri = "postgresql://user:<pw>@host:5432/mydb?sslmode=require")
con <- adbc_connection_init(db)
table <- read_adbc(con, "SELECT * FROM public.orders") |> arrow::as_arrow_table()
use adbc_core::{Connection, Database, Driver, Statement, LOAD_FLAG_DEFAULT};
use adbc_core::options::{AdbcVersion, OptionDatabase, OptionValue};
use adbc_driver_manager::ManagedDriver;
let mut driver = ManagedDriver::load_from_name("arrowfebe", None, AdbcVersion::default(), LOAD_FLAG_DEFAULT, None)?;
let mut db = driver.new_database_with_opts([(OptionDatabase::Uri,
OptionValue::String("postgresql://user:<pw>@host:5432/mydb?sslmode=require".into()))])?;
let mut conn = db.new_connection()?;
let mut stmt = conn.new_statement()?;
stmt.set_sql_query("SELECT * FROM public.orders")?;
let reader = stmt.execute()?; // impl RecordBatchReader
New here? Install ArrowFEBE first, then see the Connection guide.
All ArrowFEBE pages
ConnectionOptions, connection strings, URIs,
sslmode, channel binding, Kerberos.AuthenticationSCRAM, MD5, cleartext, GSSAPI/Kerberos, SSPI, gssencmode.Data typesPostgreSQL ↔ Arrow, NUMERIC → decimal, interval, PostGIS EWKB.CompatibilitySupported versions, compatible forks, platforms, conformance.ExamplesCopy-paste recipes: query to Arrow/pandas/Polars/DuckDB, bind, ingest.Environment variablesDriver-specific ARROWFEBE_* knobs and build-time overrides.LicensingSupplying and checking your Arpeio licence.TroubleshootingConnect, TLS, auth, licence and ingest failures and fixes.What's newReader-facing release highlights.