BetterDB vs redis_exporter
An exporter gives you the number. BetterDB keeps the evidence: the slow commands, the denied ACL calls, the clients that were connected. All of it is still there after the ring buffer rotates. It also flags anomalies against a learned baseline and forecasts when memory, CPU or ops/sec will hit their ceiling, and the core metrics still go to Prometheus.
Which one do you need?
Stay on redis_exporter when…
- INFO-level gauges and counters in Grafana are all you need
- You export values or sizes of specific keys, stream and consumer-group metrics, or custom Lua metrics
- You alert on per-command latency histograms
- You want the smallest footprint possible: one Go binary and no storage
Run both when…
- redis_exporter already runs as a sidecar on every pod - the Valkey Operator ships it that way
- Your dashboards and alerts are built on redis_* names and nobody wants to port them this quarter
- BetterDB becomes one more scrape target; the betterdb_ prefix means no name collisions
Use BetterDB instead when…
- You want the slow commands themselves, grouped by pattern - not a count of how many there were
- You need to see what happened before the page fired, after the ring buffer has rotated
- You would rather import dashboards and alert rules than build them
- You monitor several instances and want one service instead of one exporter per pod
Side by side
| Need | BetterDB | redis_exporter |
|---|---|---|
| What it is | A monitoring application: UI, persisted history, a Prometheus endpoint and OTLP export | A single-purpose Prometheus exporter. No UI, no storage |
| Core INFO metrics (memory, CPU, clients, keyspace, replication, persistence) | Yes, as betterdb_* series | Yes, as redis_* series - most of INFO is exported |
| Slowlog | Every entry persisted and grouped by command pattern, with count, average duration and share per pattern | Slowlog length, last entry ID and last entry duration |
| COMMANDLOG (Valkey 8.1+) | Large-request and large-reply entries persisted and grouped by pattern | Entry counts for the slow, large-request and large-reply logs, plus the configured thresholds |
| CLUSTER SLOT-STATS (Valkey 8.0+) | Key count for the largest slots (top 100 by default) and a slot heatmap in the UI | Key count, CPU time and network bytes per slot, behind --include-cluster-slot-stats (v1.95.0+) |
| Per-command latency | Call counts and average latency per command | Call counts and total duration, plus latency histograms and percentiles per command |
| ACL denials | ACL LOG entries persisted as an audit trail, broken down by reason and by user | Denied counters by reason, from INFO |
| Client visibility | Connections by client name and ACL user, kept as history with a 90-day peak | Connected and blocked counts; optional per-client series for the current moment (--export-client-list) |
| Anomaly detection | Learned baselines and correlated diagnoses, also exported as metrics (Pro, free in early access) | None - you write the thresholds as alert rules |
| Capacity forecasting | Projected time-to-ceiling for memory, CPU, ops/sec and fragmentation, also exported as a metric | None - you write predict_linear() queries in PromQL |
| Key-level metrics | Sampled memory by key pattern and the largest keys (Pro, free in early access) | Values and sizes of named keys, key counts by pattern, memory by key group, stream metrics |
| Custom metrics | Not supported | Lua scripts via --script |
| Sentinel | Discovers data nodes through Sentinel; no Sentinel-level series | Sentinel metrics |
| Dashboards and alert rules | Built-in UI, ten Grafana dashboards and an Alertmanager rules file | A community Grafana dashboard and the redis-mixin (sample rules, alerts and dashboards) |
| When the database is queried | On its own polling interval (5s by default); a scrape reads cached values | On every scrape |
| Footprint | One Node.js service for all your connections, plus SQLite or Postgres if you want history to survive restarts | One Go binary. One exporter can scrape many targets, or run as a sidecar per pod |
| License | Open core: MIT core including the Prometheus endpoint; some features are commercial | MIT, community-maintained |
Checked against redis_exporter v1.97.0, November 2026. It moves fast - if a row is out of date, tell us and we'll fix it.
What a scrape can't hold
An exporter is stateless. Each scrape is a snapshot of what the server reports at that moment, so anything that lives in a ring buffer is reduced to a number. For the slowlog, redis_exporter gives you this:
redis_slowlog_length 128 redis_slowlog_last_id 12345 redis_last_slow_execution_duration_seconds 1.25
You can alert on that. You can't tell which command was slow, and by the time someone looks, the entry may have rotated out. BetterDB reads the entries on its own schedule, stores them, and exports them grouped by command pattern:
betterdb_slowlog_pattern_count{pattern="HGETALL *"} 24
betterdb_slowlog_pattern_avg_duration_us{pattern="HGETALL *"} 1250000
betterdb_slowlog_pattern_percentage{pattern="HGETALL *"} 18.75The same applies to COMMANDLOG large requests and replies, ACL denials by user, and connections by client name. The entries behind each number stay queryable in the BetterDB UI.
Porting dashboards and alerts
Most core metrics map one to one. Swap the prefix, then check the handful that are renamed.
| redis_exporter | BetterDB | Note |
|---|---|---|
| redis_up | betterdb_poll_stale | Inverted: 1 means no successful read |
| redis_memory_used_bytes | betterdb_memory_used_bytes | |
| redis_memory_max_bytes | betterdb_memory_max_bytes | |
| redis_mem_fragmentation_ratio | betterdb_memory_fragmentation_ratio | Renamed |
| redis_connected_clients | betterdb_connected_clients | |
| redis_rejected_connections_total | betterdb_rejected_connections_total | |
| redis_commands_processed_total | betterdb_commands_processed_total | |
| redis_keyspace_hits_total | betterdb_keyspace_hits_total | Same for misses |
| redis_evicted_keys_total | betterdb_evicted_keys_total | Same for expired keys |
| redis_cpu_sys_seconds_total | betterdb_cpu_sys_seconds_total | Same for user CPU |
| redis_db_keys{db="db0"} | betterdb_db_keys{db="0"} | Label value is the bare index |
| redis_commands_total{cmd} | betterdb_commandstats_calls_total{command} | Renamed, and the label too |
| redis_connected_slaves | betterdb_connected_slaves | |
| redis_master_repl_offset | betterdb_replication_offset | Renamed |
| redis_master_link_up | betterdb_master_link_up | |
| redis_rdb_last_bgsave_status | betterdb_rdb_last_bgsave_ok | Renamed |
| redis_slowlog_length | betterdb_slowlog_length |
- Every BetterDB series carries a
connectionlabel. One BetterDB instance exports all the databases it monitors, so filter onconnectionwhere you used to filter oninstance. - BetterDB publishes cumulative values such as
betterdb_commands_processed_totalas gauges.rate()works on them the same way. - If series count matters, set
METRICS_EXPORT_PROFILE=vitalsfor a fixed set of core series per connection.
See it in Grafana before you switch
The dashboards in our public Grafana are built only on betterdb_* series, fed by BetterDB's Prometheus endpoint and OTLP export. All ten ship with BetterDB: Instance Vitals, Query Patterns, Clients & Pub/Sub, Keyspace & Eviction, Persistence, Security & ACL, Cluster Slots, Vector Search, Anomalies and Monitor Internals.
FAQ
Can BetterDB replace redis_exporter?
For the core metrics, yes. BetterDB exports memory, CPU, clients, throughput, keyspace, replication, persistence and cluster health from its own Prometheus endpoint, so Prometheus can scrape BetterDB instead of the exporter. You would give up a few things redis_exporter does that BetterDB does not: per-command latency histograms, values and sizes of specific keys, stream metrics, Sentinel metrics, and custom Lua-script metrics. If you depend on any of those, keep the exporter for them.
Does redis_exporter support Valkey COMMANDLOG and CLUSTER SLOT-STATS?
Yes, in recent versions. It exports the number of entries in each COMMANDLOG log and the configured thresholds, and from v1.95.0 it can export per-slot key count, CPU time and network bytes with --include-cluster-slot-stats. What it does not export is the entries themselves: which commands were slow or oversized, and from which pattern. BetterDB persists those entries and groups them by command pattern.
Will my existing redis_exporter dashboards and alerts work with BetterDB?
Not unchanged. BetterDB series use the betterdb_ prefix and a connection label, and a handful of metrics are renamed. Most core metrics map one to one, so porting an alert is usually a find-and-replace on the prefix. BetterDB also ships ten Grafana dashboards and an Alertmanager rules file if you would rather start from those.
Can I run BetterDB and redis_exporter together?
Yes. The betterdb_ and redis_ prefixes never collide, so both can feed the same Prometheus. This is the common setup on Kubernetes, where the Valkey Operator already runs redis_exporter as a sidecar in every pod and BetterDB is added as one more scrape target for query patterns, ACL audit and anomalies.
Is BetterDB heavier than redis_exporter?
Yes. redis_exporter is a single Go binary with no state. BetterDB is a Node.js service that also stores history, in memory by default or in SQLite or Postgres. One BetterDB instance covers all your connections, and the vitals export profile caps the output at 33 series per standalone primary if Prometheus cardinality is the concern.
Is the BetterDB Prometheus endpoint free?
Yes. The endpoint is part of the MIT-licensed core.
Deciding between more tools? When should you use BetterDB? →
Add it as a scrape target in one command
Ready to get started?
Start monitoring in minutes - no infrastructure to maintain. Team collaboration, agent-based monitoring for private databases, and more. Or self-host - open source core, zero lock-in.