{"id":39570185,"url":"https://github.com/jaihind213/radio-duck","last_synced_at":"2026-01-18T07:17:58.423Z","repository":{"id":196012096,"uuid":"694113906","full_name":"jaihind213/radio-duck","owner":"jaihind213","description":"Duckdb server you can talk to over http","archived":false,"fork":false,"pushed_at":"2024-05-14T02:35:59.000Z","size":1298,"stargazers_count":13,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-07T08:16:55.329Z","etag":null,"topics":["duckdb","http"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jaihind213.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-20T11:05:58.000Z","updated_at":"2025-01-25T22:06:28.000Z","dependencies_parsed_at":"2024-05-14T03:28:48.297Z","dependency_job_id":"e658170d-2684-4148-b5ac-c45d151b8a5b","html_url":"https://github.com/jaihind213/radio-duck","commit_stats":null,"previous_names":["jaihind213/radio-duck"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jaihind213/radio-duck","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaihind213%2Fradio-duck","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaihind213%2Fradio-duck/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaihind213%2Fradio-duck/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaihind213%2Fradio-duck/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jaihind213","download_url":"https://codeload.github.com/jaihind213/radio-duck/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jaihind213%2Fradio-duck/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28532930,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["duckdb","http"],"created_at":"2026-01-18T07:17:56.322Z","updated_at":"2026-01-18T07:17:58.417Z","avatar_url":"https://github.com/jaihind213.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Radio-Duck\nConnect to a Duckdb server over Http.\n\n![Project Image](radioduck.png)\n\n## Project Objectives\n\n- Talk to duckDb over transport protocols like Http.\n- Provide an alternative to embedding duckDb\n- Make DuckDb highly available for apps like Business intelligence dashboards\n- Ability to query data while data is being loaded.\n\n## Use cases\n\n- Act as data backend for Business intelligence dashboards like (metabase/superset) without embedding duckDb\n\n![UseCase1 Image](superset_radio_duck.png)\n\n- Highly available Duckdb\n\n![UseCase2 Image](radio_ha.png)\n\n## Features\n\n### Run sql on Duckdb over http\n\n#### Run sql\nYou can send a sql via http post request. refer to docs @ http://localhost:8000/docs\n\n#### Transaction support\nIt's possible but in a limited fashion (i.e. in a single http post request)\n```bash\n#example:\ncurl -X 'POST' \\\n  'http://localhost:8000/v1/sql/' \\\n  -H 'accept: application/json' \\\n  -H 'Content-Type: application/json' \\\n  -d '{\n  \"sql\": \"BEGIN; select * from pond; COMMIT;\"\n}'\n```\n\n### Load data from cloud blob storage like s3/azure \nIt's the same as you are interacting with duckDb using sql.\n\n### Consume data from streams like kafka \n[todo]\n\n## Requirements\n\n- install mamba https://mamba.readthedocs.io/en/latest/\n- install docker\n\n```\ncd PROJECT_DIR\nmamba create -n radio-duck python=3.10\nmamba activate radio-duck\nmamba install poetry\npoetry install\n```\n\n## Run Tests\n```\npytest\n```\n\n## Live Demo\n\nFeel free to run some sql with https://radioduck.pythonanywhere.com/docs\n\nNote: Please try it on firefox/chrome. safari has some issue. \n\n## Try me with Docker\n\n- Image available at dockerHub for Platforms: linux/arm64,linux/amd64.\n- https://hub.docker.com/r/jaihind213/radio-duck\n\n```\n#pull from docker hub\ndocker pull jaihind213/radio-duck:latest\n# for arm64 -\u003e 'docker run --platform linux/arm64 -p 8000:8000 -t jaihind213/radio-duck:latest'\ndocker run -p 8000:8000 -t jaihind213/radio-duck:latest\n#or\ndocker run -p 8000:8000 -v \u003cpath_to_data_dir\u003e:/radio-duck/pond -t jaihind213/radio-duck:latest\n#or\ndocker run -p 8000:8000 -v \u003cpath_to_data_dir\u003e:/radio-duck/pond -v \u003cpath_to_my_config.ini\u003e:/radio-duck/pond/my_config.ini -t jaihind213/radio-duck:latest python3 /radio-duck/server.py /radio-duck/pond/my_config.ini\n```\n\nThen access http://localhost:8000/docs and play with the api.\n\n### Configure RadioDuck with your secret credentials to access Azure blob storage / Aws s3\n\nrefer to https://duckdb.org/docs/configuration/secrets_manager.html\n\n### Build Docker image\n```bash\nsh buildDocker.sh \u003cproj_version\u003e \u003cduckb_version\u003e\n#sh buildDocker.sh 0.1.2 0.9.0 local no\n```\n\n#### Docker Image versioning\n\nThe docker image version is in the following format:\n```text\nd\u003cDUCKDB_VERSION\u003e-v\u003cPROJECT_VERSION\u003e-\u003cDOCKERFILE_VERSION\u003e\nex: d0.10.0-v0.1.2-c1d9c346 \n\nThis specifies that radio duck is running with duckdb=0.10.0, the project version being 0.1.2.\nThese versions are derived from pyproject.toml\n```\n\n## Try me with Apache Superset\n```\n#run radio-duck\ndocker run -p 8000:8000 -t jaihind213/radio-duck:latest\n# for macM1 -\u003e 'add --platform linux/amd64 '\n#run superset\ndocker pull jaihind213/superset-radioduck:latest\n# for macM1 -\u003e 'add --platform linux/amd64 '\ndocker run -e TALISMAN_ENABLED=\"False\" -e ADMIN_USERNAME=admin -e ADMIN_PASSWORD=admin -e SUPERSET_SECRET_KEY=\u003csome_good_key\u003e -p 8088:8088 jaihind213/superset-radioduck:latest\n```\nThen access http://localhost:8088/\n\nThen configure database with alchemy URI 'radio_duck+district5://user:pass@\u003cHOST_IP\u003e:8000/?api=/v1/sql/\u0026scheme=http'\n\n\u003cspan style=\"color:red;\"\u003eVideo of Demo\u003c/span\u003e.\n\n[![Demo](demo_thumbnail.png)](https://youtu.be/GUBj2uzly94?si=2QZm4WWnARM1kwgv \"Demo video\")\n\n## Try me with Python code via District5 library\n\nhttps://github.com/jaihind213/district5\n```\n#python 3.9^\npip install district5\n#start the duckdb server i.e. radio-duck\ndocker run -p 8000:8000 -t jaihind213/radio-duck:latest\n#the duckdb starts up with a sample table whose ddl is: \n#'create table pond(duck_type string, total int)'\necho \"we will try to query that\"\n```\n\n```\n\nfrom sqlalchemy import create_engine, text\nfrom sqlalchemy.dialects import registry\n\nregistry.register(\n    \"radio_duck.district5\", \"radio_duck.sqlalchemy\", \"RadioDuckDialect\"\n)\n\n\n#run docker instance of radio-duck\n#docker run -p 8000:8000 -t jaihind213/radio-duck:latest\nengine = create_engine(\n    \"radio_duck+district5://user:pass@localhost:8000/?api=/v1/sql/\u0026scheme=http\"\n)\n# Establish a database connection\nconn = engine.connect()\n\n# Define a SQL query using qmark style or positional style\ntry:\n    query_1 = text(\"\"\"SELECT duck_type, total FROM pond where total \u003e :total\"\"\")\n    params = {\"total\": 0}\n    result = conn.execute(query_1, params)\n    # Fetch and print the results\n    for row in result:\n        print(row)\n\n    print(\"--------------\")\n    query_2 = \"SELECT duck_type, total FROM pond where total \u003e ?\"\n    result = conn.execute(query_2, (0,))\n\n    for row in result:\n        print(row)\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\n\nfinally:\n    # Close the database connection\n    conn.close()\n    engine.dispose()\n\n```\n\n### Check for Docker image Vulnerabilities\n```\nsh buildDocker.sh \u003cversion\u003e\nsh docker_sec_check.sh\n# github actions is scanning for Vulnerabilities\n```\n\n## Notes:\n\n- todo: stream large datasets / compress results say json-smile?\n- todo: limit number of conns to duckdb ?\n- todo: return query_id ,useful for debugging.\n- todo: handle transactions over http ? i.e. multiple http requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaihind213%2Fradio-duck","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjaihind213%2Fradio-duck","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjaihind213%2Fradio-duck/lists"}