--- warning: DO NOT CHANGE THIS MANUALLY, THIS IS GENERATED BY https://github.com/duckdb/community-extensions repository, check README there title: quackapi excerpt: | DuckDB Community Extensions FastAPI-class HTTP framework inside DuckDB — CREATE ROUTE turns SQL into typed, validated endpoints; one process is DB + HTTP (+ PDF/renderer via companion extensions). # Community-extensions submission descriptor for the `quackapi` extension. # Keep the root and packaging/description.yml copies identical. # Release candidate descriptor; editing this file does not publish the CDN package. # # Submit: # 1. Fork https://github.com/duckdb/community-extensions # 2. Copy this file to extensions/quackapi/description.yml # 3. Set repo.ref to the exact git SHA of the release commit (no merge markers) # 4. Open a pull request against duckdb/community-extensions # # Schema: https://duckdb.org/community_extensions/documentation.html extension: name: quackapi description: >- FastAPI-class HTTP framework inside DuckDB — CREATE ROUTE turns SQL into typed, validated endpoints; one process is DB + HTTP (+ PDF/renderer via companion extensions). version: 0.2.0 language: C++ build: cmake license: MIT maintainers: - asubbarao # HTTP server uses DuckDB's bundled httplib — no server sockets on wasm. # windows_amd64 enabled (MSVC / extension-ci-tools). MinGW/rtools/arm64 # still excluded. Target signed arches: linux_*, osx_*, windows_amd64. excluded_platforms: wasm_mvp;wasm_eh;wasm_threads;windows_amd64_mingw;windows_amd64_rtools;windows_arm64 repo: github: asubbarao/quackapi # Pin to the packaging commit SHA (set by release engineer; never a branch). ref: d5c0e6784fda79930f952052302be89c16d6739c # Preserve the community registry's pre-2.0 compatibility build. variegata: 9da900bcaa1da48b64dbcab5cc3470c849b851a0 docs: hello_world: | LOAD quackapi; -- JSON endpoint: the SELECT is the handler CREATE ROUTE hello GET '/hello' AS SELECT 'world' AS msg; -- Path params bind as $id; cast failure → FastAPI-shaped 422 CREATE ROUTE item GET '/items/:id' AS SELECT $id::INTEGER AS id; -- HTML when the single output column is named html CREATE ROUTE home GET '/' AS SELECT '

quackapi

' AS html; -- Typed optional query param with constraint CREATE ROUTE search GET '/search' PARAM limit INTEGER DEFAULT 10 LE 100 AS SELECT $q::VARCHAR AS q, $limit::INTEGER AS limit; -- POST mutation (JSON body fields bind as $name / $age) CREATE ROUTE create_user POST '/users' STATUS 201 AS SELECT $name::VARCHAR AS name, $age::INTEGER AS age; -- Serve (background threads; shell stays usable) -- Optional: static_dir for unrouted GETs; cors_origins for browser CORS SELECT * FROM quackapi_serve(8000); -- curl http://127.0.0.1:8000/hello → [{"msg":"world"}] -- curl http://127.0.0.1:8000/items/42 → [{"id":42}] -- curl http://127.0.0.1:8000/items/abc → 422 detail[loc=path,id] -- curl -X POST …/users -H 'Content-Type: application/json' -d '{"name":"a","age":3}' SELECT * FROM quackapi_routes(); SELECT * FROM quackapi_stop(8000); extended_description: | # quackapi **A FastAPI-class HTTP framework that lives inside DuckDB.** Routes are DDL, handlers are SQL, and request validation is the database type system. ## Thesis: the backend IS the database A conventional stack serializes at every hop (app server → workers → DB → PDF microservice). quackapi collapses that into **one DuckDB process**: browser → DuckDB [ quackapi(HTTP) · pdf · tera · fakeit · webbed · … ] Companion community extensions (`pdf`, `tera`, `fakeit`, `crawler`/`webbed`, `cronjob`, `curl_httpfs`, …) load into the same address space. A handler that redacts a PDF is literally `SELECT pdf_redact(...)` — no RPC between tiers. **Showcase:** the Closure redaction-review app (DB + HTML UI + PDF word boxes + POST decisions + static assets) runs as a single DuckDB process via `CREATE ROUTE` + `quackapi_serve`. ## CREATE ROUTE CREATE [OR REPLACE] ROUTE '' [STATUS ] [REQUIRE ] [GROUP ] [BODY SCHEMA '' | BODY TYPE ''] [PARAM [] [HEADER|COOKIE|QUERY …] [DEFAULT …] [GE|LE|…] …] AS ` polls SQL as SSE. `CREATE STREAM … WS` supports WebSocket push or replies per `$message`; WebSockets do not apply REST auth/middleware. - **Policies:** `CREATE ROW ACCESS POLICY` / `CREATE MASKING POLICY` + `ALTER TABLE` bind; `quackapi_policies()`. - **Inspect:** `quackapi_routes()` (including schedule and route upload limit), `quackapi_servers()`, `quackapi_requests()`, `quackapi_http_pool()`. - **POST / local SQL:** scalar and table `quackapi_post` / `quackapi_selfdispatch` return receipts. POST preserves exact `body_blob` bytes; text `body` is NULL for invalid UTF-8. Optional `timeout_ms` never extends the outer deadline. `response_format := 'arrow'|'parquet'` decodes HTTP bytes directly into `rows LIST` and `columns LIST`. Local self-dispatch captures these fields before JSON serialization. Empty results preserve their native column types; no curl pipe is needed. - **Framework metadata:** `quack_from_routes(framework, path)` and `quack_from_models(framework, path)` support fastapi, rails, express and gin. They return AST-derived rows, not executable handler translations. - **Composition:** native readers handle remote files; `http_request` handles arbitrary GET responses; DuckDB `postgres` ATTACH handles PostgreSQL. Legacy GET helpers, custom pg_dsn execution and Quack auth adapters are removed. ## Platforms & build Targets **DuckDB v2.0.0**. C++17; uses DuckDB-bundled **httplib** and **mbedtls**, plus vendored **nanoarrow IPC** (no vcpkg, no libcurl, no separately installed Arrow extension). CI builds linux/macOS/windows_amd64; excludes wasm and Windows MinGW/rtools/arm64. ## Limits (honest) - DuckDB single-writer / file concurrency — not high-write multi-tenant OLTP. - Serve leaves DuckDB's memory limit unchanged unless `memory_limit` or `quackapi_memory_limit` is supplied. - Uploads default to 8 MiB. Server `max_request_bytes` sets the hard ceiling (maximum 1 GiB); route `WITH (max_request_bytes = …)` opts into a larger upload within it. Raising only the server ceiling leaves routes at 8 MiB. - JWT is **HS256 only** (no RS256/OIDC); table API is read-only list/get with validated pagination and key ordering. - `cancel_on_disconnect := true` opts into route-query/plain-HTTP POST cancellation. HTTPS remains backend-limited; remote jobs need their own cancellation APIs. POST waits for a complete upstream response. - Route registry is instance-scoped (re-run DDL after reopen); queue jobs persist in `quackapi_jobs`. Full reference: https://github.com/asubbarao/quackapi Migration notes: https://github.com/asubbarao/quackapi/blob/main/docs/MIGRATION.md Community page source: https://github.com/asubbarao/quackapi/blob/main/docs/community-page.md extension_star_count: 8 extension_star_count_pretty: 8 extension_download_count: 13898 extension_download_count_pretty: 13.9k image: '/images/community_extensions/social_preview/preview_community_extension_quackapi.png' layout: community_extension_doc --- ### Compatibility Matrix This table covers all DuckDB releases that have not reached [end-of-life](https://duckdb.org/release_calendar), including LTS releases, and shows the 2 most recent patch releases of each. Older patch releases are not listed, but the extension may be available for them as well.
| Platform | 1.4.4 | 1.4.5 | 1.5.5 | 1.5.6 | 2.0.0 | | :--- | :---: | :---: | :---: | :---: | :---: | | Linux AMD64 | ❌ | ❌ | ✅ | ✅ | ✅ | | Linux ARM64 | ❌ | ❌ | ✅ | ✅ | ✅ | | macOS AMD64 | ❌ | ❌ | ✅ | ✅ | ✅ | | macOS ARM64 | ❌ | ❌ | ✅ | ✅ | ✅ | | Windows AMD64 | ❌ | ❌ | ✅ | ✅ | ✅ | | Windows ARM64 | ❌ | ❌ | ❌ | ❌ | ❌ | | WebAssembly | ❌ | ❌ | ❌ | ❌ | ❌ | ### Installing and Loading ```sql INSTALL {{ page.extension.name }} FROM community; LOAD {{ page.extension.name }}; ``` {% if page.docs.hello_world %} ### Example ```sql {{ page.docs.hello_world }}``` {% endif %} {% if page.docs.extended_description %} ### About {{ page.extension.name }} {{ page.docs.extended_description }} {% endif %} ### Added Functions
| function_name | function_type | description | comment | examples | |---------------------------------|---------------|-------------|---------|----------| | quack_from_express | table | NULL | NULL | | | quack_from_express_models | table | NULL | NULL | | | quack_from_fastapi | table | NULL | NULL | | | quack_from_fastapi_models | table | NULL | NULL | | | quack_from_gin | table | NULL | NULL | | | quack_from_gin_models | table | NULL | NULL | | | quack_from_rails | table | NULL | NULL | | | quack_from_rails_models | table | NULL | NULL | | | quack_from_x_sql | scalar | NULL | NULL | | | quack_from_x_sql_relpath | scalar | NULL | NULL | | | quackapi_ack | scalar | NULL | NULL | | | quackapi_add_api_key | table | NULL | NULL | | | quackapi_apply_middleware | table | NULL | NULL | | | quackapi_authentication | scalar | NULL | NULL | | | quackapi_authorization | scalar | NULL | NULL | | | quackapi_auths | table | NULL | NULL | | | quackapi_dequeue | table | NULL | NULL | | | quackapi_enqueue | scalar | NULL | NULL | | | quackapi_fetch | scalar | NULL | NULL | | | quackapi_fetch | table | NULL | NULL | | | quackapi_graphql_routes | table | NULL | NULL | | | quackapi_graphql_tables | table | NULL | NULL | | | quackapi_groups | table | NULL | NULL | | | quackapi_http_pool | table | NULL | NULL | | | quackapi_http_util_name | scalar | NULL | NULL | | | quackapi_last_write_timeout_sec | scalar | NULL | NULL | | | quackapi_middlewares | table | NULL | NULL | | | quackapi_nack | scalar | NULL | NULL | | | quackapi_parallel_fetch | table | NULL | NULL | | | quackapi_policies | table | NULL | NULL | | | quackapi_post | scalar | NULL | NULL | | | quackapi_queues | table | NULL | NULL | | | quackapi_renew | scalar | NULL | NULL | | | quackapi_request | table | NULL | NULL | | | quackapi_requests | table | NULL | NULL | | | quackapi_routes | table | NULL | NULL | | | quackapi_serve | table | NULL | NULL | | | quackapi_servers | table | NULL | NULL | | | quackapi_stop | table | NULL | NULL | | | quackapi_streams | table | NULL | NULL | | | quackapi_telemetry_flush | table | NULL | NULL | | | quackapi_telemetry_status | table | NULL | NULL | | | quackapi_verify_auth | scalar | NULL | NULL | | | quackapi_wait | table | NULL | NULL | | ### Overloaded Functions
This extension does not add any function overloads. ### Added Types
This extension does not add any types. ### Added Settings
| name | description | input_type | scope | aliases | typed_value | |--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------|--------|---------|-------------| | quackapi_compression | Response compression mode on quackapi_serve: auto, gzip, zstd or off. Default auto (zstd preferred, then gzip). Overridden by compression named parameter. | VARCHAR | GLOBAL | [] | auto | | quackapi_compression_min_bytes | Minimum response body size (bytes) before compression. Default 1024. Overridden by compression_min_bytes named parameter. | BIGINT | GLOBAL | [] | 1024 | | quackapi_cors_origins | CORS allowed origins for quackapi_serve (* or comma-separated list). Empty (default) disables CORS. Overridden by cors_origins named parameter. | VARCHAR | GLOBAL | [] | | | quackapi_graphql_allow_all | Explicit legacy opt-in to public GraphQL catalog exposure | BOOLEAN | GLOBAL | [] | false | | quackapi_http_client | Outbound HTTP client for httpfs/route fetches: auto\|curl\|httplib. Default auto prefers curl_httpfs (pool, HTTP/2, async) and falls back to httplib with http_client_reason on /healthz when unavailable. curl fails serve if curl_httpfs cannot INSTALL/LOAD. Overridden by http_client named parameter. Does not change the inbound HTTP server. | VARCHAR | GLOBAL | [] | auto | | quackapi_http_timeout_ms | Maximum time for one outbound quackapi_fetch / quackapi_post call in milliseconds | BIGINT | GLOBAL | [] | 600000 | | quackapi_log_headers | Comma-separated request-header allowlist for access-log maps; empty (default) avoids retaining headers. Overridden by log_headers named parameter. | VARCHAR | GLOBAL | [] | | | quackapi_log_level | Log verbosity for quackapi_serve: silent\|error\|warn\|info\|debug. Default info. Overridden by log_level named parameter. | VARCHAR | GLOBAL | [] | info | | quackapi_log_query | Preserve a redacted raw query string in access logs; default false. Overridden by log_query named parameter. | BOOLEAN | GLOBAL | [] | false | | quackapi_max_pending_requests | Maximum queued HTTP connections | BIGINT | GLOBAL | [] | 256 | | quackapi_max_response_bytes | Maximum uncompressed response bytes | BIGINT | GLOBAL | [] | 16777216 | | quackapi_memory_limit | Memory limit applied by quackapi_serve (e.g. '4GB', '512MB'). Empty (default): do not clobber a non-default DuckDB memory_limit; only apply the 256MB serve default when nothing was configured. Overridden by memory_limit named parameter. | VARCHAR | GLOBAL | [] | | | quackapi_pg_dsn | Postgres DSN for the native libpq handler path (thread-local PGconn). Empty (default) keeps DuckDB-only execution. Overridden by pg_dsn named parameter on quackapi_serve / quackapi_request. | VARCHAR | GLOBAL | [] | | | quackapi_query_timeout_ms | Maximum query execution time in milliseconds | BIGINT | GLOBAL | [] | 30000 | | quackapi_request_ring | Number of recent TCP requests retained by quackapi_requests(). Default 10000; zero disables the in-memory ring. Overridden by request_ring named parameter. | BIGINT | GLOBAL | [] | 10000 | | quackapi_slow_request_ms | Requests at or above this duration are logged at warn level. Default 1000ms. Overridden by slow_request_ms named parameter. | BIGINT | GLOBAL | [] | 1000 | | temp_directory | Set the directory to which temporary files are written. | VARCHAR | GLOBAL | [] | post.db.tmp |