How to Install VictoriaMetrics on Ubuntu 24.04 VPS: Fast, Cost-Efficient Prometheus Alternative
VictoriaMetrics is a high-performance, open-source time series database and monitoring platform that solves the operational pain points of running Prometheus at any real scale. It ingests Prometheus remote_write natively, speaks PromQL plus its own more powerful MetricsQL dialect, and stores metrics with up to 10x better compression while using a fraction of the RAM. This guide walks you through installing VictoriaMetrics on an Ubuntu 24.04 VPS, starting with the single-node vmsingle binary, layering on vmagent for scraping and vmalert for alerting rules, wiring it into Grafana, and finally scaling out to the vmcluster architecture with replication.
Already running Prometheus? VictoriaMetrics is a drop-in long-term storage backend. You can keep Prometheus in place, add remote_write to VictoriaMetrics, and reduce your retention-related disk bill from day one.Table of Contents
What is VictoriaMetrics?
VictoriaMetrics is a fast, cost-effective, open-source time series database (TSDB) and monitoring solution. It is wire-compatible with Prometheus — meaning every tool that talks to Prometheus (Grafana, kube-state-metrics, node_exporter, Alertmanager, and thousands of exporters) also talks to VictoriaMetrics — but it uses a fundamentally different storage engine designed for massive cardinality and long retention on commodity hardware.
The project is distributed as a family of statically linked Go binaries with no external dependencies. vmsingle (the single-node binary) handles ingestion, storage, and query in one process and is what most teams start with. vmagent is a lightweight, stateless scraper and remote_write proxy that replaces the scrape side of Prometheus and supports multi-tenant relabeling, buffering, and streaming aggregation. vmalert evaluates Prometheus-style alerting and recording rules against any PromQL/MetricsQL endpoint and pushes alerts to Alertmanager. For horizontal scale, vmcluster splits the single-node binary into three components — vmstorage (stateful shards), vminsert (ingestion router), and vmselect (query fan-out) — which together support replication, multi-tenancy, and linear scale-out to billions of active time series.
The use cases are broad. DevOps teams use VictoriaMetrics as long-term storage for Prometheus, keeping 90 days of high-resolution metrics on a single VPS where Prometheus alone would need ten times the disk. SaaS platforms use vmcluster multi-tenancy to isolate customer metrics without running a separate stack per tenant. IoT and industrial projects use it to ingest millions of data points per second from devices and sensors. Kubernetes operators use the VictoriaMetrics Operator and VMAgent/VMAlert/VMCluster CRDs as a modern replacement for the kube-prometheus-stack. And Grafana power users adopt it for the MetricsQL extensions, which add functions that PromQL cannot easily express — like rollup_rate, keep_last_value, and streaming aggregation.
Why Self-Host VictoriaMetrics Instead of Prometheus?
Prometheus is an excellent monitoring system, but it was deliberately designed around local storage with a 15-day default retention and a single-node architecture. Anyone running Prometheus for more than a few dozen hosts eventually hits the same four walls: memory blow-up under high cardinality, disk growth that outpaces Moore's law, single-node scale ceiling, and lack of built-in replication. VictoriaMetrics was purpose-built to fix those four problems while staying 100% wire-compatible.
- 10x better compression — VictoriaMetrics routinely stores the same time series in one-tenth the disk space of Prometheus. On a 7-day retention window, a fleet producing 500K active series typically drops from ~120 GB (Prometheus) to ~10-15 GB (VictoriaMetrics).
- Dramatically lower RAM usage — VictoriaMetrics uses approximately 7x less RAM than Prometheus for equivalent workloads. Ingesting 1M samples/sec with 2M active time series fits comfortably in 8 GB of RAM.
- Faster queries at high cardinality — VictoriaMetrics is 20x faster than Prometheus for queries over high-cardinality labels, where Prometheus's index becomes a bottleneck.
- Long retention out of the box — Pass
-retentionPeriod=12and keep a year of data on a single node. Prometheus users typically need Thanos, Cortex, or Mimir to achieve the same — each adding operational complexity. - Horizontal scale when you need it —
vmclusterreplicates and shards across commodity nodes. Move from single-node to cluster without changing your dashboards, alerts, or scrapers. - Built-in replication — Set
-replicationFactor=2or-replicationFactor=3in vmcluster and survive node loss without external storage dependencies. - Prometheus wire-compatible — Grafana, Alertmanager, and all exporters work unchanged. You can migrate gradually by pointing Prometheus's
remote_writeat VictoriaMetrics and keeping both running. - MetricsQL extensions — A superset of PromQL adds functions for streaming aggregation, gap-filling, rollups, and histogram manipulation that make certain dashboards dramatically simpler.
Cost Comparison: Prometheus vs. VictoriaMetrics on the Same VPS
For a fleet producing 500K active time series with 10-second scrape intervals at 30-day retention:
| Metric | Prometheus (alone) | VictoriaMetrics (vmsingle) |
|---|---|---|
| Disk required (30 days) | ~480 GB | ~45 GB |
| RAM required at steady state | ~14 GB | ~2.5 GB |
| Startup time after restart | 2-10 minutes | < 5 seconds |
| Query p99 over 7d range | 3-8 seconds | 0.2-0.6 seconds |
| High-cardinality query | Frequent OOMs | Handles it |
| Replication | External (Thanos/Mimir) | Native in cluster mode |
| Recommended VPS plan | 32 GB RAM, 1 TB disk | 8-12 GB RAM, 100 GB disk |
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access to your server
- At least 4 GB of RAM for small-to-medium fleets (8-12 GB recommended for production)
- At least 50 GB of disk for a comfortable retention window
- Existing Prometheus or exporters are optional — vmagent can scrape directly
Recommended Plan: CloudCore Professional>
For a single-node VictoriaMetrics stack plus vmagent and vmalert comfortably serving a mid-size fleet (up to ~1M active series, 30-60 day retention), we recommend the CloudCore Professional plan:>
- 6 vCPU cores
- 12 GB RAM
- 100 GB NVMe SSD
- Unmetered bandwidth
- EUR 19.99/month>
This leaves plenty of headroom for Grafana, Alertmanager, and vmalert on the same host. For fleets above 1M active series or multi-tenant SaaS deployments, see our larger plans and consider the vmcluster setup later in this guide.
Connect to your server via SSH to get started:
ssh root@your-server-ipStep 1: Update System Packages
Start by refreshing the package index and applying any pending upgrades.
sudo apt update && sudo apt upgrade -yInstall the handful of tools we will need:
sudo apt install -y curl wget tar ca-certificates ufwIf the kernel was upgraded, reboot before continuing:
sudo rebootStep 2: Download and Install vmsingle
VictoriaMetrics publishes signed release binaries on GitHub. We will download the latest single-node build, extract it to /usr/local/bin, and create a dedicated system user.
Export the current release version into a shell variable so the rest of the commands remain copy-pasteable. Check the releases page for the newest version.
export VM_VERSION="v1.109.1"Download the single-node archive:
cd /tmp
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/victoria-metrics-linux-amd64-${VM_VERSION}.tar.gzExtract and install the binary:
tar -xzf victoria-metrics-linux-amd64-${VM_VERSION}.tar.gz
sudo mv victoria-metrics-prod /usr/local/bin/victoria-metrics
sudo chmod +x /usr/local/bin/victoria-metricsCreate a dedicated system user and data directory:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin victoriametrics
sudo mkdir -p /var/lib/victoria-metrics
sudo chown -R victoriametrics:victoriametrics /var/lib/victoria-metricsVerify the binary works:
/usr/local/bin/victoria-metrics --versionExpected output:
victoria-metrics-20250115-000000-tags-v1.109.1-0-abcdef12Step 3: Create a systemd Service
A proper systemd unit keeps VictoriaMetrics running across reboots, captures logs into journald, and gives you a single place to configure retention, storage path, and ingestion limits.
Create the unit file:
sudo tee /etc/systemd/system/victoriametrics.service > /dev/null <<'EOF' [Unit] Description=VictoriaMetrics single-node TSDB After=network-online.target Wants=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/victoria-metrics \ -storageDataPath=/var/lib/victoria-metrics \ -retentionPeriod=3 \ -httpListenAddr=:8428 \ -selfScrapeInterval=30s \ -memory.allowedPercent=60
Restart=on-failure RestartSec=5 LimitNOFILE=1048576
Hardening
NoNewPrivileges=true ProtectSystem=full ProtectHome=true PrivateTmp=true
[Install] WantedBy=multi-user.target EOF
Key flags explained:
-storageDataPath=/var/lib/victoria-metrics— Where TSDB files are written. Point this at your largest disk or mounted volume.-retentionPeriod=3— Keep 3 months of data. Use3d,12(months), or1yas needed. Default is 1 month.-httpListenAddr=:8428— The HTTP port for ingestion, queries, and the built-in UI.-selfScrapeInterval=30s— VictoriaMetrics scrapes its own/metricsendpoint every 30s.-memory.allowedPercent=60— Cap internal memory use at 60% of system RAM. Lower this on shared hosts.
sudo systemctl daemon-reload
sudo systemctl enable --now victoriametricsStep 4: Verify the Installation
Check that the service is active:
sudo systemctl status victoriametricsExpected output:
● victoriametrics.service - VictoriaMetrics single-node TSDB
Loaded: loaded (/etc/systemd/system/victoriametrics.service; enabled; preset: enabled)
Active: active (running) since Wed 2026-04-16 10:00:00 UTC; 10s ago
Main PID: 2345 (victoria-metric)
Tasks: 14 (limit: 14236)
Memory: 82.4M
CGroup: /system.slice/victoriametrics.service
└─2345 /usr/local/bin/victoria-metrics -storageDataPath=...Probe the health endpoint:
curl http://localhost:8428/healthExpected output:
OKOpen the built-in vmui in your browser (or via curl) to confirm the query engine is live:
curl 'http://localhost:8428/api/v1/query?query=vm_rows'Expected JSON response:
{"status":"success","isPartial":false,"data":{"resultType":"vector","result":[{"metric":{"__name__":"vm_rows","type":"indexdb"},"value":[1744800000,"0"]}]}}You now have a running VictoriaMetrics node. The web UI is available at http://your-server-ip:8428/vmui/ once you open the firewall (covered in Step 8).
Step 5: Ingest Prometheus remote_write
The fastest way to get real data into VictoriaMetrics is to have Prometheus ship its samples via remote_write. If you have an existing Prometheus server (see our guide on how to install Prometheus on Ubuntu), edit its configuration:
# /etc/prometheus/prometheus.yml
remote_write:
- url: http://your-vm-server:8428/api/v1/write
queue_config:
max_samples_per_send: 10000
capacity: 20000
max_shards: 30Restart Prometheus:
sudo systemctl restart prometheusWithin a few seconds you should see series start flowing. Confirm by querying for a metric you know Prometheus is scraping, such as up:
curl 'http://localhost:8428/api/v1/query?query=up' | jq .You should see an entry for every target Prometheus monitors. You can now safely reduce Prometheus's local retention (for example, --storage.tsdb.retention.time=1d) and let VictoriaMetrics be your long-term store.
Writing Directly from Exporters (No Prometheus)
VictoriaMetrics also accepts pushed samples in multiple formats directly — Prometheus exposition, InfluxDB line protocol, Graphite plaintext, OpenTSDB, and CSV. Example using the InfluxDB line protocol (handy if you are migrating from an InfluxDB deployment):
curl -X POST 'http://localhost:8428/write' --data-binary \
'temperature,location=office value=23.5 1744800000000000000'Step 6: Install vmagent for Scraping
vmagent is the recommended replacement for the scrape side of Prometheus. It is stateless, uses far less memory, supports multi-target relabeling, and can buffer to disk if the downstream VictoriaMetrics is unreachable.
Download the vmagent binary (shipped in the same release bundle as vmsingle — use the -utils archive or grab the dedicated vmutils build):
cd /tmp
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}/vmutils-linux-amd64-${VM_VERSION}.tar.gz
tar -xzf vmutils-linux-amd64-${VM_VERSION}.tar.gz
sudo mv vmagent-prod /usr/local/bin/vmagent
sudo mv vmalert-prod /usr/local/bin/vmalert
sudo chmod +x /usr/local/bin/vmagent /usr/local/bin/vmalertCreate a Prometheus-style scrape config. vmagent uses the exact same YAML schema as Prometheus, so existing configs drop in unchanged:
sudo mkdir -p /etc/vmagent sudo tee /etc/vmagent/scrape.yml > /dev/null <<'EOF' global: scrape_interval: 15s external_labels: cluster: production replica: vmagent-1scrape_configs: - job_name: 'node' static_configs: - targets: ['localhost:9100']
- job_name: 'victoriametrics' static_configs: - targets: ['localhost:8428'] EOF
Create a persistent queue directory for when VictoriaMetrics is briefly unreachable:
sudo mkdir -p /var/lib/vmagent
sudo chown -R victoriametrics:victoriametrics /var/lib/vmagent /etc/vmagentCreate the systemd unit:
sudo tee /etc/systemd/system/vmagent.service > /dev/null <<'EOF' [Unit] Description=vmagent — VictoriaMetrics scraper After=network-online.target victoriametrics.service Wants=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmagent \ -promscrape.config=/etc/vmagent/scrape.yml \ -remoteWrite.url=http://127.0.0.1:8428/api/v1/write \ -remoteWrite.tmpDataPath=/var/lib/vmagent \ -httpListenAddr=:8429
Restart=on-failure RestartSec=5 LimitNOFILE=1048576
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now vmagent
Verify it is scraping:
curl -s http://localhost:8429/targets | head -40Or query VictoriaMetrics to see fresh data from node_exporter:
curl 'http://localhost:8428/api/v1/query?query=node_load1' | jq .vmagent's persistent queue is the unsung hero here: if vmsingle is restarted for an upgrade, vmagent continues collecting and buffers to disk until ingestion resumes — no gaps in your dashboards.
Step 7: Install vmalert for Alerting Rules
vmalert evaluates Prometheus-style alerting and recording rules against any PromQL/MetricsQL endpoint and forwards firing alerts to Alertmanager.
Create a rules file:
sudo mkdir -p /etc/vmalert sudo tee /etc/vmalert/rules.yml > /dev/null <<'EOF' groups: - name: host-alerts interval: 30s rules: - alert: HighCPU expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85 for: 5m labels: severity: warning annotations: summary: "High CPU on {{ $labels.instance }}" description: "CPU above 85% for 5 minutes (current: {{ $value | printf \"%.1f\" }}%)."- alert: LowDisk expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10 for: 10m labels: severity: critical annotations: summary: "Disk almost full on {{ $labels.instance }}"
- name: recording-rules interval: 30s rules: - record: instance:node_cpu:rate5m expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) EOF
sudo chown -R victoriametrics:victoriametrics /etc/vmalert
Create the systemd unit. Note -notifier.url points to Alertmanager — install it separately or omit the flag if you only want recording rules.
sudo tee /etc/systemd/system/vmalert.service > /dev/null <<'EOF' [Unit] Description=vmalert — VictoriaMetrics rule evaluator After=network-online.target victoriametrics.service Wants=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmalert \ -rule=/etc/vmalert/rules.yml \ -datasource.url=http://127.0.0.1:8428 \ -remoteWrite.url=http://127.0.0.1:8428 \ -remoteRead.url=http://127.0.0.1:8428 \ -notifier.url=http://127.0.0.1:9093 \ -httpListenAddr=:8880 \ -evaluationInterval=30s
Restart=on-failure RestartSec=5
[Install] WantedBy=multi-user.target EOF
sudo systemctl daemon-reload sudo systemctl enable --now vmalert
Check the rule evaluation UI:
curl -s http://localhost:8880/api/v1/rules | jq .The -remoteWrite.url flag is what makes recording rules persist: evaluated expressions are written back into VictoriaMetrics as new time series, letting your dashboards query pre-aggregated data without recomputing expensive expressions on every render.
Step 8: Connect Grafana as a Data Source
VictoriaMetrics speaks Prometheus wire protocol, so Grafana sees it as just another Prometheus endpoint. If you do not yet have Grafana installed, see our guide on how to install Grafana on Ubuntu.
Before wiring Grafana, open the firewall to allow local network access (or keep 8428 internal and proxy through Grafana only):
sudo ufw allow from 10.0.0.0/8 to any port 8428
sudo ufw allow from 127.0.0.1 to any port 8428
sudo ufw enableIn Grafana:
http://127.0.0.1:8428 (or your VPS's private IP + port).Import dashboard 1860 (Node Exporter Full) as a smoke test — every panel should populate within a minute.
Why the VictoriaMetrics Data Source Plugin?
The official VictoriaMetrics data source plugin adds autocomplete for the MetricsQL functions that PromQL does not have, plus a trace view for query performance debugging. For any dashboard that uses MetricsQL-only functions, install it:
sudo grafana-cli plugins install victoriametrics-metrics-datasource
sudo systemctl restart grafana-serverStep 9: Explore MetricsQL Extensions
MetricsQL is a superset of PromQL. Every PromQL query runs unchanged, but MetricsQL adds functions that dramatically simplify common dashboards.
rollup_rate(m[5m]) — Returns three series simultaneously: min, max, and avg of the per-second rate over the window. One query, three lines on the chart.
rollup_rate(node_network_receive_bytes_total[5m])keep_last_value(m) — Fills gaps caused by missed scrapes with the last known value, which is a lifesaver for spotty exporters.
keep_last_value(up)interpolate(m) — Linear interpolation across missing points, perfect for smooth dashboards on low-frequency metrics.
histogram_quantile over multiple buckets — MetricsQL's variant accepts any quantile from 0 to 1 and handles the le="+Inf" bucket more leniently than Prometheus.
share_le_over_time(m[window], le) — Returns the share of samples below a threshold over a time window. Useful for SLO dashboards.
share_le_over_time(http_request_duration_seconds[5m], 0.3)topk_last(k, m) — The top k series by their last value, without the "series swap" flicker you get from vanilla PromQL's topk.
@ modifier in ranges — Evaluate a subquery at a fixed timestamp, enabling week-over-week comparisons in a single expression.
Full MetricsQL reference: docs.victoriametrics.com/MetricsQL.html.
Step 10: Scale Out with vmcluster (Replication)
Once you approach 1-2 million active series or need replication for HA, graduate from vmsingle to vmcluster. The cluster splits into three stateless-or-stateful roles:
- vmstorage — Stateful storage nodes. Data is sharded across them. Losing one takes its shard offline unless replication is enabled.
- vminsert — Stateless ingestion router. Hashes each time series to
replicationFactorstorage nodes. - vmselect — Stateless query fan-out. Sends queries to all storage nodes and merges results.
Recommended Minimal Cluster
For basic HA with replication factor 2, you need at least two storage nodes (so a lost node does not lose data) plus vminsert and vmselect (which can share a host with storage in small deployments):
| Role | Count | Port(s) |
|---|---|---|
| vmstorage | 2+ | 8400 (vminsert), 8401 (vmselect), 8482 (HTTP) |
| vminsert | 2+ | 8480 |
| vmselect | 2+ | 8481 |
Install vmstorage
Download the cluster binaries (different archive from vmsingle):
cd /tmp
wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/${VM_VERSION}-cluster/victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz
tar -xzf victoria-metrics-linux-amd64-${VM_VERSION}-cluster.tar.gz
sudo mv vmstorage-prod /usr/local/bin/vmstorage
sudo mv vminsert-prod /usr/local/bin/vminsert
sudo mv vmselect-prod /usr/local/bin/vmselect
sudo chmod +x /usr/local/bin/vm{storage,insert,select}Systemd unit for vmstorage (run this on each storage node):
sudo tee /etc/systemd/system/vmstorage.service > /dev/null <<'EOF' [Unit] Description=vmstorage — VictoriaMetrics cluster storage After=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmstorage \ -storageDataPath=/var/lib/vmstorage \ -retentionPeriod=6 \ -vminsertAddr=:8400 \ -vmselectAddr=:8401 \ -httpListenAddr=:8482
Restart=on-failure LimitNOFILE=1048576
[Install] WantedBy=multi-user.target EOF
Install vminsert and vmselect
On one or more router nodes, run vminsert and vmselect pointing at all your storage nodes. With -replicationFactor=2, vminsert writes every sample to two different storage nodes.
sudo tee /etc/systemd/system/vminsert.service > /dev/null <<'EOF' [Unit] Description=vminsert — VictoriaMetrics cluster ingestion After=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vminsert \ -storageNode=storage-1.internal:8400,storage-2.internal:8400 \ -replicationFactor=2 \ -httpListenAddr=:8480
Restart=on-failure LimitNOFILE=1048576
[Install] WantedBy=multi-user.target EOF
sudo tee /etc/systemd/system/vmselect.service > /dev/null <<'EOF' [Unit] Description=vmselect — VictoriaMetrics cluster query After=network-online.target[Service] Type=simple User=victoriametrics Group=victoriametrics ExecStart=/usr/local/bin/vmselect \ -storageNode=storage-1.internal:8401,storage-2.internal:8401 \ -dedup.minScrapeInterval=15s \ -httpListenAddr=:8481
Restart=on-failure LimitNOFILE=1048576
[Install] WantedBy=multi-user.target EOF
Enable all three on their respective hosts:
sudo systemctl daemon-reload
sudo systemctl enable --now vmstorage # on storage hosts
sudo systemctl enable --now vminsert # on router hosts
sudo systemctl enable --now vmselect # on router hostsPoint vmagent and Grafana at the Cluster
vmagent now writes to vminsert:
-remoteWrite.url=http://vminsert.internal:8480/insert/0/prometheus/api/v1/writeGrafana queries vmselect (note the tenant-prefixed path — use 0 for single-tenant):
http://vmselect.internal:8481/select/0/prometheusThe 0 in those paths is the tenant ID. vmcluster is multi-tenant by design: each tenant gets an isolated namespace with no cross-tenant query access.
Replication Semantics
With -replicationFactor=2, vminsert writes every sample to 2 storage nodes and vmselect deduplicates on read. You can lose one storage node without losing data or serving partial queries (vmselect sets isPartial=false as long as every shard has at least one replica available). For stricter durability, set -replicationFactor=3 and run three storage nodes.
Full cluster documentation: docs.victoriametrics.com/Cluster-VictoriaMetrics.html.
Performance Tuning
Retention and Disk Planning
-retentionPeriod=N accepts values like 30d, 6 (months), or 2y. Disk usage scales roughly linearly with active time series and retention. A good back-of-envelope formula for vmsingle:
bytes_on_disk = active_series samples_per_day retention_days * 0.4Where 0.4 bytes/sample is a typical VictoriaMetrics compression ratio. A fleet with 500K active series and a 15s scrape interval (5,760 samples/series/day) at 90-day retention gives roughly 104 GB.
Memory Tuning
VictoriaMetrics caches index data in RAM. Control memory ceiling with:
-memory.allowedPercent=60 # default 60% of system RAM
-memory.allowedBytes=8GB # absolute capOn a 12 GB VPS running vmsingle plus vmagent and vmalert, -memory.allowedPercent=50 leaves room for the neighbors.
Cardinality Control with streaming aggregation
Runaway label cardinality (think UUIDs in labels) is the one workload that can still OOM VictoriaMetrics. Use vmagent's streaming aggregation to pre-aggregate at scrape time:
# /etc/vmagent/aggregation.yml
- match: 'http_requests_total'
interval: 1m
outputs: ['total', 'count_series']
by: ['service', 'status']Then add -streamAggr.config=/etc/vmagent/aggregation.yml to the vmagent flags. The high-cardinality raw metric is collapsed before it ever reaches storage.
Index and Query Caches
The -search.maxConcurrentRequests and -search.maxQueryDuration flags prevent a runaway Grafana dashboard from starving ingestion:
-search.maxConcurrentRequests=16
-search.maxQueryDuration=30sDeduplication
In a cluster with replicationFactor > 1, or when two Prometheus servers remote_write the same metrics, set -dedup.minScrapeInterval=15s on vmsingle (or vmselect in cluster mode) to drop duplicate samples during queries.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
victoria-metrics: bind: address already in use on :8428 | Another process has the port | sudo lsof -i :8428 and stop/reconfigure the conflicting service |
Prometheus remote_write fails with context deadline exceeded | VM endpoint unreachable or overloaded | Check firewall from Prom host; raise queue_config.max_shards in Prometheus |
| Dashboards stop updating but service is "running" | vmagent queue directory full | Check /var/lib/vmagent free space; raise -remoteWrite.maxDiskUsagePerURL=10GB |
| Alerts not firing | -notifier.url missing or Alertmanager down | curl http://localhost:8880/api/v1/alerts to inspect vmalert state |
| High memory usage, occasional OOM | Cardinality explosion | Inspect /api/v1/status/tsdb for top label pairs; apply streaming aggregation |
vmcluster query returns isPartial: true | One or more vmstorage nodes unreachable | systemctl status vmstorage on each storage host; check network between vmselect and vmstorage |
| Disk fills faster than expected | Retention too high or cardinality growing | Inspect vm_data_size_bytes; reduce -retentionPeriod or aggregate |
| Grafana queries time out | Expensive MetricsQL or long range | Add recording rules via vmalert; set -search.maxQueryDuration |
Viewing Logs
sudo journalctl -u victoriametrics -f
sudo journalctl -u vmagent -f
sudo journalctl -u vmalert -fFor cluster components:
sudo journalctl -u vmstorage -u vminsert -u vmselect -fUseful Introspection Endpoints
GET /api/v1/status/tsdb— top label pairs and cardinality breakdownGET /api/v1/status/active_queries— currently running queriesGET /metrics— self-monitoring metrics (scrape into VM itself)GET /flags— effective runtime flags
FAQ
Is VictoriaMetrics really a drop-in replacement for Prometheus?
For storage, querying, and data ingestion, yes — it speaks the Prometheus remote_write protocol, exposes the full Prometheus HTTP query API (/api/v1/query, /api/v1/query_range, /api/v1/label/*), and evaluates PromQL without modification. Where it differs is scraping (handled by vmagent instead of Prometheus's built-in scraper) and alerting (handled by vmalert or Alertmanager directly). Every Grafana dashboard built for Prometheus works against VictoriaMetrics unchanged, and every exporter (node_exporter, blackbox_exporter, postgres_exporter, kube-state-metrics, etc.) works with vmagent as the scraper.
When should I choose vmsingle vs vmcluster?
Start with vmsingle. A single well-sized VPS (8-16 GB RAM, NVMe disk) easily handles 1-2 million active time series and 100k samples per second — enough for most mid-sized fleets. Move to vmcluster when you need: (1) native replication for HA, (2) multi-tenancy to isolate customer workloads, (3) horizontal scale beyond a single node's RAM ceiling, or (4) independent scaling of ingestion versus query workloads. The migration path is gentle: you can export from vmsingle and re-ingest into vmcluster with zero downtime on the read side if you keep vmsingle running during the cutover.
How does VictoriaMetrics compare to InfluxDB, TimescaleDB, and Thanos?
Compared to InfluxDB, VictoriaMetrics is purpose-built for Prometheus ecosystem integration and typically ingests more samples per CPU core with smaller disk footprint; InfluxDB has broader downsampling and a first-class SQL interface (Flux/InfluxQL). See our InfluxDB install guide for the InfluxDB side. Compared to TimescaleDB, VictoriaMetrics skips the full relational model in favor of specialized metric operations, trading SQL joins for 5-10x better ingestion throughput. Compared to Thanos/Cortex/Mimir, VictoriaMetrics is dramatically simpler to operate (no Kafka, no object storage mandatory, no complex query sharding), and benchmarks consistently show better query latency under high cardinality — at the cost of some features like full downsampling tiers and object-storage backed infinite retention.
Can I run VictoriaMetrics alongside an existing Prometheus setup?
Absolutely, and this is the recommended migration path. Keep Prometheus scraping and alerting as-is, add a remote_write block pointing at VictoriaMetrics, then gradually (a) shorten Prometheus's local retention to save disk, (b) move long-range Grafana queries to the VictoriaMetrics data source, and finally (c) replace Prometheus with vmagent once you trust the new stack. There is no flag day — both systems store the same metrics with the same label semantics.
Does VictoriaMetrics support downsampling?
The open-source version does not do automatic downsampling in the storage engine — instead, use vmalert recording rules to compute 5-minute or 1-hour rollups and query those recording-rule series from dashboards that span long time ranges. The Enterprise edition adds built-in downsampling tiers. For most fleets, recording rules plus MetricsQL's rollup_* functions deliver equivalent practical benefit.
What's the biggest operational pitfall to watch for?
Label cardinality. Any label whose value set is unbounded (user IDs, request IDs, UUIDs, full URL paths with query strings) will inflate the index and eventually push memory usage past healthy limits. Monitor vm_cache_entries{type="storage/tsid"} and the /api/v1/status/tsdb endpoint, and apply vmagent's streaming aggregation or relabel_config to drop or collapse high-cardinality labels before they reach storage.
Next Steps
Now that VictoriaMetrics is running on your VPS, here are recommended next steps:
- Add exporters to round out your monitoring — Deploy
node_exporteron every host,blackbox_exporterfor synthetic checks, andpostgres_exporter/mysqld_exporterif you run databases. vmagent scrapes them exactly like Prometheus does. - Install Alertmanager — Pair vmalert with Alertmanager for deduplication, routing (Slack, PagerDuty, email), and silencing.
- Build Grafana dashboards — Import community dashboards from grafana.com/grafana/dashboards/ (IDs 1860, 11074, and 10826 are popular starters). See our Grafana install guide if you have not set it up yet.
- Migrate from InfluxDB or Prometheus — Use
vmctl(bundled with the cluster archive) to import historical data from Prometheus snapshots, InfluxDB, or OpenTSDB. - Harden with TLS and auth — Put Nginx in front of
:8428, terminate TLS with Let's Encrypt, and add Basic Auth or mTLS for external access. The same pattern applies to vmagent, vmalert, and vmselect. - Compare to Prometheus natively — Our Prometheus install guide walks through the reference setup so you can benchmark the two side by side on the same VPS.
- Explore the official docs — The full documentation at docs.victoriametrics.com covers advanced topics like backups with
vmbackup/vmrestore, multi-tenancy, streaming aggregation recipes, and the Kubernetes Operator.
Need a VPS sized right for VictoriaMetrics?>
Our CloudCore Professional plan — 6 vCPU, 12 GB RAM, 100 GB NVMe SSD at EUR 19.99/month — comfortably hosts vmsingle + vmagent + vmalert + Grafana + Alertmanager for a mid-size fleet, with headroom for 30-90 days of retention. Need more? Our larger plans scale smoothly into vmcluster territory.>
Launch your CloudCore Professional VPS now and have VictoriaMetrics ingesting metrics within the hour.