motherduckdb/grafana-duckdb-datasource

TypeScript

161

217 commits

updated Sep 21, 2026

See the code

README

Grafana DuckDB Data Source Plugin

The DuckDB data source plugin lets you query and visualize DuckDB data in Grafana. DuckDB is an in-process SQL OLAP database management system that provides fast analytics on local files. DuckDB's SQL dialect is derived from PostgreSQL so this plugin works similarly to the Grafana Postgres plugin and works for most SQL queries that would work in Postgres.

The plugin is built and maintained by MotherDuck, a data platform that provides a cloud-based serverless DuckDB as a service, with additional features like data sharing, read scaling and more.

Compatibility

This plugin requires:

  • Grafana Version 10.4.0 or later.
  • glibc 2.35 or later (this means Ubuntu 22.04 or above)

[!WARNING] Alpine/Musl platforms are NOT supported. This plugin uses duckdb-go which only provides glibc-based Linux binaries. Alpine Linux uses musl libc and is incompatible. Docker users: You must use Ubuntu-based Grafana images (grafana/grafana:latest-ubuntu). The default Grafana image is Alpine-based and will not work.

Features

  • Query editor with syntax highlighting and auto-completion.
  • Import data from various file formats (CSV, Parquet, JSON) through DuckDB extensions.
  • Automatically reload the DuckDB file when the file has changed, allowing for data updates via hot-swapping the file.
  • Connect to and query data in MotherDuck.

Installation

Download the plugin for your (OS, architecture) from the releases page.

Since the plugin is currently unsigned, modify the grafana.ini file to allow unsigned plugins:

...
allow_loading_unsigned_plugins = motherduck-duckdb-datasource
...

Then, unzip the plugin and move it to the Grafana plugins directory:

mv motherduck-duckdb-datasource-<version>.zip
unzip motherduck-duckdb-datasource-<version>.zip -d YOUR_PLUGIN_DIR/motherduck-duckdb-datasource

Finally, restart the Grafana server.

Running with Docker

To run the plugin with a Grafana Docker container, you must use the Ubuntu-based Grafana image instead of the default Alpine-based one. Use the following command to start a Grafana container with the plugin:

docker run -d \
  --name=grafana \
  -p 3000:3000 \
  -v $(pwd)/motherduck-duckdb-datasource:/var/lib/grafana/plugins/motherduck-duckdb-datasource \
  -e "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=motherduck-duckdb-datasource" \
  grafana/grafana:latest-ubuntu

This mounts your local plugin directory into the container and configures Grafana to allow loading the unsigned plugin. Remember to replace $(pwd)/motherduck-duckdb-datasource with the actual path to your plugin directory if needed.

Configuration

Data Source Options

NameDescriptionRequired
PathPath to DuckDB database file, if empty, connects to duckDB in in-memory mode.Yes
MotherDuck TokenToken for MotherDuck API accessNo

Connecting to MotherDuck

Set the path to the MotherDuck database you want to query, and supply a MotherDuck Token:

PathResult
md:my_databasequeries that database, addressed as my_database.schema.table
md:attaches every database in your MotherDuck account

Query Editor Options

The query editor supports standard SQL syntax and includes special Grafana macros for time range filtering and variable interpolation.

Macros

MacroDescriptionExample
$__timeFilterAdds a time range filter using the dashboard's time rangeWHERE $__timeFilter(time_column)
$__timeFromStart of the dashboard time rangeWHERE time_column > $__timeFrom
$__timeToEnd of the dashboard time rangeWHERE time_column < $__timeTo
$__intervalDashboard time range intervalGROUP BY time_bucket($__interval, time_column)
$__unixEpochFilterTime range filter for Unix timestampsWHERE $__unixEpochFilter(timestamp_column)

Query Examples

Time Series Data

SELECT
  time_bucket($__interval, timestamp) AS time,
  avg(value) as average,
  max(value) as maximum
FROM metrics
WHERE $__timeFilter(timestamp)
GROUP BY 1
ORDER BY 1

Table Query

SELECT
  name,
  value,
  timestamp
FROM metrics
WHERE $__timeFilter(timestamp)
LIMIT 100

File Import Support

Through a rich ecosystem of extensions, DuckDB supports reading data from various file formats:

-- CSV import
SELECT * FROM read_csv_auto('path/to/file.csv');

-- Parquet import
SELECT * FROM read_parquet('path/to/file.parquet');

-- JSON import
SELECT * FROM read_json_auto('path/to/file.json');

Query Editor

Known Issues and Suggestions for Workarounds

Updating data in the DuckDB file

DuckDB's concurrency support does not allow multiple processes to attach the same DuckDB database file at the same time, if at least one of them requires read-write access. This means another process cannot connect to the same DuckDB database file to write to it while Grafana has it as a data source. There are a few ways to work around this:

  • Copy the DuckDB file for updates, then copy the updated DuckDB file to overwrite the original file. The plugin will automatically reload the file when it detects a change.
  • Write to other file formats, and read using DuckDB extensions. Note that this may be much less performant than directly querying the DuckDB file.
  • Host the database using MotherDuck, which allows writing to the database while querying it from Grafana and other clients at the same time.

Grafana DuckDB Plugin is not compatible with Alpine based images.

If you are starting out with the Grafana DuckDB plugin and are running into any of the following, double-check your base image:

  • error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
  • the plugin is missing dynamic-link libraries necessary to run
  • fork/exec ...: no such file or directory

These symptoms all have the same cause: Alpine uses musl libc, not glibc. The go-duckdb binary is compiled against glibc and cannot run on musl. The "no such file or directory" error is particularly confusing because the file exists - it's the dynamic linker (/lib/ld-linux-*.so) that's missing.

Build, test and release process

How the plugin is built and tested in CI, and how a release is cut, is documented in CONTRIBUTING.md.

Contributors

hrl20

140 commits

elefeint

33 commits

moulid-adan

17 commits

setoh2000

10 commits

motherduckdb/grafana-duckdb-datasource

TypeScript

161

217 commits

updated Sep 21, 2026

See the code

README

Grafana DuckDB Data Source Plugin

The DuckDB data source plugin lets you query and visualize DuckDB data in Grafana. DuckDB is an in-process SQL OLAP database management system that provides fast analytics on local files. DuckDB's SQL dialect is derived from PostgreSQL so this plugin works similarly to the Grafana Postgres plugin and works for most SQL queries that would work in Postgres.

The plugin is built and maintained by MotherDuck, a data platform that provides a cloud-based serverless DuckDB as a service, with additional features like data sharing, read scaling and more.

Compatibility

This plugin requires:

  • Grafana Version 10.4.0 or later.
  • glibc 2.35 or later (this means Ubuntu 22.04 or above)

[!WARNING] Alpine/Musl platforms are NOT supported. This plugin uses duckdb-go which only provides glibc-based Linux binaries. Alpine Linux uses musl libc and is incompatible. Docker users: You must use Ubuntu-based Grafana images (grafana/grafana:latest-ubuntu). The default Grafana image is Alpine-based and will not work.

Features

  • Query editor with syntax highlighting and auto-completion.
  • Import data from various file formats (CSV, Parquet, JSON) through DuckDB extensions.
  • Automatically reload the DuckDB file when the file has changed, allowing for data updates via hot-swapping the file.
  • Connect to and query data in MotherDuck.

Installation

Download the plugin for your (OS, architecture) from the releases page.

Since the plugin is currently unsigned, modify the grafana.ini file to allow unsigned plugins:

...
allow_loading_unsigned_plugins = motherduck-duckdb-datasource
...

Then, unzip the plugin and move it to the Grafana plugins directory:

mv motherduck-duckdb-datasource-<version>.zip
unzip motherduck-duckdb-datasource-<version>.zip -d YOUR_PLUGIN_DIR/motherduck-duckdb-datasource

Finally, restart the Grafana server.

Running with Docker

To run the plugin with a Grafana Docker container, you must use the Ubuntu-based Grafana image instead of the default Alpine-based one. Use the following command to start a Grafana container with the plugin:

docker run -d \
  --name=grafana \
  -p 3000:3000 \
  -v $(pwd)/motherduck-duckdb-datasource:/var/lib/grafana/plugins/motherduck-duckdb-datasource \
  -e "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=motherduck-duckdb-datasource" \
  grafana/grafana:latest-ubuntu

This mounts your local plugin directory into the container and configures Grafana to allow loading the unsigned plugin. Remember to replace $(pwd)/motherduck-duckdb-datasource with the actual path to your plugin directory if needed.

Configuration

Data Source Options

NameDescriptionRequired
PathPath to DuckDB database file, if empty, connects to duckDB in in-memory mode.Yes
MotherDuck TokenToken for MotherDuck API accessNo

Connecting to MotherDuck

Set the path to the MotherDuck database you want to query, and supply a MotherDuck Token:

PathResult
md:my_databasequeries that database, addressed as my_database.schema.table
md:attaches every database in your MotherDuck account

Query Editor Options

The query editor supports standard SQL syntax and includes special Grafana macros for time range filtering and variable interpolation.

Macros

MacroDescriptionExample
$__timeFilterAdds a time range filter using the dashboard's time rangeWHERE $__timeFilter(time_column)
$__timeFromStart of the dashboard time rangeWHERE time_column > $__timeFrom
$__timeToEnd of the dashboard time rangeWHERE time_column < $__timeTo
$__intervalDashboard time range intervalGROUP BY time_bucket($__interval, time_column)
$__unixEpochFilterTime range filter for Unix timestampsWHERE $__unixEpochFilter(timestamp_column)

Query Examples

Time Series Data

SELECT
  time_bucket($__interval, timestamp) AS time,
  avg(value) as average,
  max(value) as maximum
FROM metrics
WHERE $__timeFilter(timestamp)
GROUP BY 1
ORDER BY 1

Table Query

SELECT
  name,
  value,
  timestamp
FROM metrics
WHERE $__timeFilter(timestamp)
LIMIT 100

File Import Support

Through a rich ecosystem of extensions, DuckDB supports reading data from various file formats:

-- CSV import
SELECT * FROM read_csv_auto('path/to/file.csv');

-- Parquet import
SELECT * FROM read_parquet('path/to/file.parquet');

-- JSON import
SELECT * FROM read_json_auto('path/to/file.json');

Query Editor

Known Issues and Suggestions for Workarounds

Updating data in the DuckDB file

DuckDB's concurrency support does not allow multiple processes to attach the same DuckDB database file at the same time, if at least one of them requires read-write access. This means another process cannot connect to the same DuckDB database file to write to it while Grafana has it as a data source. There are a few ways to work around this:

  • Copy the DuckDB file for updates, then copy the updated DuckDB file to overwrite the original file. The plugin will automatically reload the file when it detects a change.
  • Write to other file formats, and read using DuckDB extensions. Note that this may be much less performant than directly querying the DuckDB file.
  • Host the database using MotherDuck, which allows writing to the database while querying it from Grafana and other clients at the same time.

Grafana DuckDB Plugin is not compatible with Alpine based images.

If you are starting out with the Grafana DuckDB plugin and are running into any of the following, double-check your base image:

  • error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
  • the plugin is missing dynamic-link libraries necessary to run
  • fork/exec ...: no such file or directory

These symptoms all have the same cause: Alpine uses musl libc, not glibc. The go-duckdb binary is compiled against glibc and cannot run on musl. The "no such file or directory" error is particularly confusing because the file exists - it's the dynamic linker (/lib/ld-linux-*.so) that's missing.

Build, test and release process

How the plugin is built and tested in CI, and how a release is cut, is documented in CONTRIBUTING.md.

Contributors

hrl20

140 commits

elefeint

33 commits

moulid-adan

17 commits

setoh2000

10 commits

Languages

TypeScript

47.7%

Go

42.5%

JavaScript

4.4%

Dockerfile

3.6%

Makefile

1.3%