Why dedicated storage for your metrics
A standalone Prometheus mixes two jobs: scraping your services' metrics every fifteen seconds, and storing them. The first is light; the second grows with every series and every day of history. You end up cutting retention to a few weeks, and the question "was latency already this high last quarter?" goes unanswered.
VictoriaMetrics separates the two. Prometheus — or Grafana Alloy, vmagent, Telegraf — keeps scraping, then sends every sample to VictoriaMetrics, which compresses and keeps it. Because it answers the Prometheus query API, Grafana queries it without changing a single dashboard.
What VictoriaMetrics brings
- Prometheus-compatible —
remote_writetarget, Prometheus query API, Grafana data source with no plugin. - PromQL and MetricsQL — your PromQL queries work as-is; MetricsQL adds handier functions.
- Compact storage — strong series compression, several months of retention on a modest disk.
- Multi-protocol — InfluxDB line protocol, Graphite, OpenTSDB, OpenTelemetry, CSV and JSON import.
- vmui interface — series exploration, graphs, cardinality analysis and slowest queries.
- A single binary — one container, no external dependency, a few tens of megabytes of RAM at rest.
VictoriaMetrics versus Prometheus local storage
Scroll the table
| VictoriaMetrics | Prometheus alone | |
|---|---|---|
| Typical retention | Several months to several years | Fifteen days by default |
| Centralise several servers | Yes, via remote_write | No, one instance per scope |
| Query language | PromQL and MetricsQL | PromQL |
| Ingestion formats | Prometheus, InfluxDB, Graphite, OpenTSDB, OTLP | Prometheus scraping |
| Grafana | Prometheus data source | Prometheus data source |
| Target scraping | Possible, but left to Prometheus or vmagent | Yes, that is its job |
Prerequisites
An Ubuntu 24.04 VPS with 1 GB of RAM is enough to start; plan 2 GB and more disk if you centralise many servers. You need Docker with the Compose plugin, and a domain name pointing to the VPS, with nginx and an HTTPS certificate: your servers will send their metrics there and Grafana will query it, so the address must be stable and encrypted.
Ideally, install VictoriaMetrics on a machine separate from the servers it monitors: if it goes down with them, you lose precisely the data that explains the outage.
Install VictoriaMetrics with Docker Compose
Prepare the directory and the password
Create the application directory and a
.envfile holding the password of theadminuser.mkdir -p /opt/victoriametrics && cd /opt/victoriametrics echo "ADMIN_PASSWORD=$(openssl rand -hex 16)" > .env chmod 600 .envWrite the docker-compose.yml
The port is published on the loopback interface only: only nginx reaches it. The two
-httpAuthoptions protect every endpoint — interface, queries and ingestion.-retentionPeriod=12keeps twelve months of data.services: victoriametrics: image: victoriametrics/victoria-metrics:v1.155.0 restart: unless-stopped ports: - "127.0.0.1:8428:8428" command: - -storageDataPath=/storage - -retentionPeriod=12 - -httpAuth.username=admin - -httpAuth.password=${ADMIN_PASSWORD} - -selfScrapeInterval=30s volumes: - victoriametrics-data:/storage volumes: victoriametrics-data: {}Start the container
Startup takes less than a second. The log should show "started VictoriaMetrics" followed by the start of self-scraping.
docker compose up -d docker compose logs --tail 20Publish over HTTPS with nginx
In your domain's vhost (certificate obtained with certbot), proxy to the local port. Raise
client_max_body_size:remote_writebatches quickly exceed the default limit.location / { proxy_pass http://127.0.0.1:8428; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto $scheme; client_max_body_size 64m; }
Without a password, the database is open for writing
Without the -httpAuth options, anyone who knows the address can read all your metrics and write fake ones, or even delete series through the admin API. Keep authentication enabled, and never publish port 8428 directly on the public IP: always go through the HTTPS reverse proxy.
Send metrics from Prometheus
On each server running Prometheus, add a remote_write block to prometheus.yml, then reload Prometheus. It keeps scraping as before and duplicates every sample to VictoriaMetrics.
remote_write:
- url: https://metrics.example.com/api/v1/write
basic_auth:
username: admin
password: "<ADMIN_PASSWORD>"Then check that data arrives: the up series of your targets should answer. Recent samples appear after about thirty seconds, a normal delay VictoriaMetrics applies to instant queries.
curl -u admin:<ADMIN_PASSWORD> \
'https://metrics.example.com/api/v1/query?query=up'Query VictoriaMetrics from Grafana
In Grafana, add a data source of type Prometheus with the URL https://metrics.example.com, tick Basic auth and enter the admin user and the password. Your existing dashboards — Node Exporter Full, for example — work unchanged, over the whole depth of history kept.
To explore without Grafana, open https://metrics.example.com/vmui: the built-in interface graphs queries, lists series and shows, in the cardinality tab, which metrics cost the most storage.
Retention, disk and backup
Retention is set with -retentionPeriod: a bare number counts months, and the suffixes d, w or y count days, weeks or years. Disk usage depends mostly on the number of active series and the scrape frequency: measure it after a week (du -sh on the volume) rather than estimating it. To back up, the official vmbackup tool takes consistent snapshots without stopping the database; otherwise, stop the container before copying the volume.
Send metrics without Prometheus
Prometheus is not mandatory. VictoriaMetrics directly accepts the Prometheus text format, the InfluxDB line protocol, Graphite, OpenTSDB and OpenTelemetry. An application can therefore push its own counters with a single HTTP call — handy for a business metric, a backup script or a scheduled job that does not run long enough to be scraped.
curl -u admin:<ADMIN_PASSWORD> \
-d 'orders_total{shop="casa"} 1284' \
https://metrics.example.com/api/v1/import/prometheusIf you already use Telegraf, point its InfluxDB output to https://metrics.example.com with the same credentials: VictoriaMetrics presents itself as an InfluxDB database for writes. To scrape targets without installing Prometheus on every machine, the lightweight vmagent reads the same scrape_configs as Prometheus and ships everything via remote_write; it buffers samples on disk if VictoriaMetrics is briefly unreachable.
Keep cardinality under control
The cost of a time series database does not depend on the number of samples but on the number of series: every unique combination of metric name and labels creates one. A label carrying a user ID, an IP address or a full URL multiplies series by the thousand, and that is what fills memory and disk — with VictoriaMetrics as with Prometheus.
The Cardinality tab of vmui lists the metrics and labels producing the most series. Check it after connecting a new service: a label with unbounded values is fixed at the source, in the application or with a metric_relabel_configs rule on the Prometheus side, before it fills months of storage.
Update VictoriaMetrics
The project ships a new release several times a month, with detailed release notes. The storage format stays compatible across versions: updating means changing the image number in docker-compose.yml, then restarting the container. The data volume is kept, and the short gap during the restart is absorbed by the Prometheus or vmagent buffer, which resends pending samples.
cd /opt/victoriametrics
docker compose pull
docker compose up -dOne-click install from the ServOrbit Marketplace
The ServOrbit Marketplace installs VictoriaMetrics on your VPS without a command line: it deploys the official container, generates the password of the admin user, enables authentication on every endpoint and publishes the interface over HTTPS on a subdomain of your domain or on the VPS's free subdomain. The password is shown in your client area; all that is left is to add the remote_write block to your servers and the data source in Grafana.