The short answer
Pick Metabase if the people asking the questions don't write SQL: its query builder joined customers to orders by itself, and a sales or finance team can answer new questions without you. Pick Grafana if you already run it for your servers, think in time ranges and SQL, or want alerts on your data every minute: it used a quarter or less of Metabase's memory, but every chart on business data was a SQL query we wrote.
What we tested
We installed both on the same fresh Melonslab VC-P Alloy (2 vCPU, 8 GB) with Debian 13, one after the other, by following our guides Metabase with rootless Podman and Prometheus and Grafana step by step. Both read one database on PostgreSQL 18, set up as in the PostgreSQL guide, each through a login of its own that can only read.
The database held twelve months of a made-up Swedish wholesaler, October 2025 to September 2026: 20,000 customers, 275,000 orders and 265,000 invoices, 64 MB in all. In each app we built the same three things:
- revenue per month over the year;
- a table of the 20 customers with the most revenue, with their city and number of orders;
- an Orders dashboard with a date filter, holding those two and four more charts: total revenue, orders by status, revenue by city and orders per week.
Both gave the same figures to the öre, for the whole year and for March 2026 alone. Then we compared sharing, permissions and alerts, timed the same questions in both, ran each guide's backup and restore, and measured the memory after a reboot.
The numbers
| Metabase 0.64.2.2 | Grafana 13.2.4 | |
|---|---|---|
| Containers | 2: Metabase, PostgreSQL 18 for its own data | 1: Grafana. Our guide adds Prometheus and Alertmanager for server monitoring |
| Memory, idle after a reboot | about 1.63 GB (Metabase 1.60 GB, PostgreSQL 32 MB) | 260 to 390 MB for Grafana (Prometheus 40 MB, Alertmanager 12 MB) |
| Images on disk | 1.39 GB | 1.43 GB (1.77 GB with Prometheus and Alertmanager) |
| Other disk | 0.69 GB, a copy of Metabase's program in its container, and 80 MB of its own database | 2.5 MB of data |
| First start, image download included | about 2.5 minutes | about 2 minutes |
| Steps in our guide | 13 | 14, plus the data source below |
| Charts on our data built without SQL | 6 of 6 | 0 of 6 |
| Backup | a 1.7 MB database dump and a key | a 2.3 MB copy of a volume, with Grafana stopped |
Memory is each app's containers, measured with podman stats five minutes after a reboot, after each dashboard had been opened once. The shared PostgreSQL used about 165 MB on top of that, for both.
Setup
Both guides worked as written. Metabase's guide connects your database in step 7, through the read-only login from step 1. Our Grafana guide is written for watching servers, so a business database is an addition. We created a login grafana_ro exactly as metabase_ro in step 1 of the Metabase guide, and stored its password as a secret, as monitoring:
printf %s 'the-grafana_ro-password' | podman secret create grafana-shop-password -
Then three additions to the Grafana guide's files. In monitoring.pod, below PublishPort=, the line from the Metabase guide that lets the pod reach PostgreSQL on the server's 127.0.0.1 at 169.254.1.3:
Network=pasta:--map-host-loopback,169.254.1.3
In grafana.container, below the other Secret= line:
Secret=grafana-shop-password
And at the end of ~/monitoring/datasources.yml:
- name: Shop
type: grafana-postgresql-datasource
uid: shop
url: 169.254.1.3:5432
user: grafana_ro
jsonData:
database: appdb
sslmode: disable
postgresVersion: 1500
secureJsonData:
password: $__file{/run/secrets/grafana-shop-password}
After systemctl --user daemon-reload and systemctl --user restart monitoring-pod, the data source answered Database Connection OK, and Prometheus still reached node_exporter. If you only want Grafana for business data, you need none of Prometheus, Alertmanager or node_exporter.
Building the dashboards
This is the real difference.
In Metabase, all six charts were questions in its query builder: pick the Orders table, Sum of Total, grouped by Created At: Month, filtered on Status is paid. For the top customers we grouped by the customer's name and city, which Metabase offered straight from the Orders table because it had read the foreign key to customers. It wrote the join itself. The dashboard's Date filter is linked to Created At in each card, and accepts a specific range, a month, or "previous 30 days". A user who may not write SQL could still build new questions this way: we set All Users to Query builder only, as the Metabase guide shows, and such a user could group customers by segment but had SQL refused.
In Grafana, every panel was a SQL query. The PostgreSQL editor has a Builder mode, but it works on one table at a time, so the top customers, which need a join, are SQL either way. The date filter is Grafana's time picker, which every dashboard has, but it only filters a panel whose SQL uses the $__timeFilter(created_at) macro, so you add that to each query. Two things surprised us:
- Weekly groups with
$__timeGroup(created_at, 1w)started on Thursdays, because Grafana counts weeks from 1 January 1970, a Thursday. Metabase's weeks started on Sundays, and you can change that under Localization. In Grafana,date_trunc('week', created_at)in your SQL gives Monday weeks. - Revenue per month as bars with a label per month needed the month as text,
to_char(date_trunc('month', created_at), 'YYYY-MM'). As a time series, Grafana draws it on a continuous time axis.
Once written, Grafana's panels have more settings than Metabase's charts, such as thresholds, units and overrides per field. Metabase, on the other hand, is built for clicking on from a chart into the rows behind it, which Grafana is not; we did not test that by hand.
Speed
Both send SQL to the same PostgreSQL, so the database does most of the work. We ran each of the six questions seven times over the whole year, through each app's own API, and took the median:
| Question | Metabase | Grafana |
|---|---|---|
| Revenue per month | 608 ms | 597 ms |
| Top customers | 710 ms | 435 ms |
| Orders per week | 533 ms | 430 ms |
| Total revenue | 375 ms | 135 ms |
| Orders by status | 381 ms | 154 ms |
| Revenue by city | 607 ms | 227 ms |
Metabase took about 0.1 to 0.4 seconds longer for each question. Neither felt slow. On a larger database, an index or a summary table matters far more than the choice of app.
Sharing and embedding
Both made a public link that opened without a login, and both kept a filter on it: Metabase's public dashboard took the Date filter, and Grafana's shared dashboard let visitors change the time range once we chose Enable time range. Grafana's shared dashboards do not support dashboard variables, according to its documentation. Turn on public links only for dashboards that hold nothing private: anyone with the link sees them.
Metabase's open-source edition can also embed a dashboard in your own site or customer portal with a signed link, which it now calls guest embeds. We embedded the Orders dashboard this way. According to Metabase's documentation, such embeds show a "Powered by Metabase" banner on the free edition, and cannot drill through; removing the banner, and embeds that log users in, need Pro. We did not test embedding Grafana in another site.
Permissions
Metabase has groups, and per database you choose whether a group may use the query builder, write SQL, or neither, and which collections of questions it may see. Hiding rows or columns per user, such as each sales rep seeing only their customers, needs Pro.
Grafana has the roles Viewer, Editor and Admin, and permissions on folders and dashboards. But in Grafana's open-source edition, any logged-in user can send any query to any data source, whatever dashboards they may see. We checked: a user with only the Viewer role read customers' email addresses with a SQL query through Grafana's API. Grafana's documentation says the same, and that data source permissions need Grafana Enterprise or Cloud. So in Grafana, the database login is your real permission: grant grafana_ro only the tables or views that every Grafana user may see, rather than SELECT ON ALL TABLES as in step 1.
In both, the read-only login held: a DELETE failed with cannot execute DELETE in a read-only transaction.
Alerts
Both sent an alert on our data to a test webhook without any email set up.
- Metabase alerts on a saved question: when it has results, or when a value goes above or below a goal, checked on a schedule such as every hour or every morning. The alert carried the question's chart as an image. It can also send by email or Slack. Metabase refused a webhook address on
169.254.1.3as an internal address, so point it at a real address outside the pod. - Grafana evaluates alert rules every minute: our rule, "paid revenue in the last 24 hours below 1,000", fired within a minute and sent the values with it. It has many more channels, and silences, grouping and repeat intervals, as you would expect from a monitoring tool.
Metabase can also email a dashboard to a list of people on a schedule, which it calls subscriptions. Grafana's documentation describes scheduled PDF reports for Grafana Enterprise and Cloud.
Resources
Metabase runs on Java and took 1.6 GB after a reboot. Java lets it grow to a quarter of the server's memory, 2 GB here, so give it a server with at least 4 GB. Grafana is a Go program and used 260 to 390 MB. Grafana keeps its dashboards in a small SQLite database in its volume; Metabase in a PostgreSQL of its own.
Metabase used more disk than its 1.39 GB of images: each time it starts, the container copies Metabase's 0.69 GB program file, because the image changes its owner. That space is freed and taken again at every restart, so count on about 2.2 GB.
Updates and backups
The Metabase guide follows the v0.64.x tag, so podman-auto-update.timer installs Metabase's bug and security fixes for 0.64 by itself: while we tested, it was already at 0.64.2.2, a newer fix than the guide's 0.64.2.1. A new version such as 0.65 changes its database, so you move to it by hand after a backup. The Grafana guide follows latest, which also brings new major versions by itself; use a tag such as 13.2 to choose when those come.
Metabase's backup is a pg_dump that runs while it works, plus the encryption key for the stored database passwords. Grafana's backup stops it for a moment to copy its volume. We restored both into empty volumes and found our dashboards and questions intact, and both came back by themselves after a reboot. Your business data is in neither: it stays in your own database, which the PostgreSQL guide backs up.
Language
Both are available in Swedish. In Metabase, choose Admin > Settings > Localization for everyone, or Language in your account settings. In Grafana, choose Swedish under Language in your profile, or for everyone in the default preferences under Administration. Table and column names stay as in your database in both.
Licence and cost
We checked the projects' own pages on 14 October 2026.
- Metabase is open source under the AGPL 3.0, and made by Metabase, Inc. in San Francisco. Self-hosting the open-source edition is free, for any number of users. Starter costs 100 US dollars a month for five users, and Pro 575 US dollars a month for ten users plus 12 dollars for each extra one; Pro adds single sign-on, row and column permissions, caching controls, usage auditing and embeds without Metabase's banner. Enterprise starts at 20,000 dollars a year.
- Grafana is open source under the AGPL 3.0, and made by Grafana Labs in New York. Self-hosting is free. Grafana Enterprise adds data source permissions and reports, among other things, from 25,000 dollars a year. Grafana Cloud is free for three users, and its Pro tier costs 19 dollars a month plus 8 dollars for each extra user.
Both open-source editions did what we tested without a licence. Both send usage data and check for updates by default; each guide shows how to switch that off.
Which one to pick
Metabase suits a team that wants answers from the company's data without a developer for each new question: sales by region, top customers, unpaid invoices, all built by clicking, with drill-down, email subscriptions and embeds in your own portal. Its weak points are the memory, 1.6 GB of Java, the disk its container takes at every start, alerts that run on a schedule rather than every minute, and row-level permissions that cost money. Follow the Metabase guide; it runs comfortably on a VC-P Alloy next to PostgreSQL.
Grafana suits you if your dashboards are mostly about time: orders per hour, sign-ups today against last week, alerts the minute something drops, next to the server graphs you may already have. Its weak points for business questions are that every chart is SQL you write, that it cannot limit which data a logged-in user can query, and that drilling into the rows behind a chart is not built in. Follow the Prometheus and Grafana guide with the data source above; Grafana alone would run on a smaller server, and the whole guide on a VC-P Alloy.
Both together, with the shared PostgreSQL, used about 2.7 GB of the server's 8 GB, so a VC-P Alloy runs them side by side, as on our test server.