The only agent that thinks for itself

Autonomous Monitoring with self-learning AI built-in, operating independently across your entire stack.

Unlimited Metrics & Logs
Machine learning & MCP
5% CPU, 150MB RAM
3GB disk, >1 year retention
800+ integrations, zero config
Dashboards, alerts out of the box
> Discover Netdata Agents

Centralized metrics streaming and storage

Aggregate metrics from multiple agents into centralized Parent nodes for unified monitoring across your infrastructure.

Stream from unlimited agents
Long-term data retention
High availability clustering
Data replication & backup
Scalable architecture
Enterprise-grade security
> Learn about Parents

Fully managed cloud platform

Access your monitoring data from anywhere with our SaaS platform. No infrastructure to manage, automatic updates, and global availability.

Zero infrastructure management
99.9% uptime SLA
Global data centers
Automatic updates & patches
Enterprise SSO & RBAC
SOC2 & ISO certified
> Explore Netdata Cloud

Deploy Netdata Cloud in your infrastructure

Run the full Netdata Cloud platform on-premises for complete data sovereignty and compliance with your security policies.

Complete data sovereignty
Air-gapped deployment
Custom compliance controls
Private network integration
Dedicated support team
Kubernetes & Docker support
> Learn about Cloud On-Premises

Powerful, intuitive monitoring interface

Modern, responsive UI built for real-time troubleshooting with customizable dashboards and advanced visualization capabilities.

Real-time chart updates
Customizable dashboards
Dark & light themes
Advanced filtering & search
Responsive on all devices
Collaboration features
> Explore Netdata UI

Monitor on the go

Native iOS and Android apps bring full monitoring capabilities to your mobile device with real-time alerts and notifications.

iOS & Android apps
Push notifications
Touch-optimized interface
Offline data access
Biometric authentication
Widget support
> Download apps

The future of infrastructure observability

See our strategic direction across AI-native observability, full-stack signals, operational intelligence, and enterprise platform maturity.

AI-native observability
Full-stack signal coverage
Operational intelligence
Enterprise platform maturity
Agent releases every 6 weeks
Cloud continuous delivery
> Explore Product Roadmap

Best energy efficiency

True real-time per-second

100% automated zero config

Centralized observability

Multi-year retention

High availability built-in

Zero maintenance

Always up-to-date

Enterprise security

Complete data control

Air-gap ready

Compliance certified

Millisecond responsiveness

Infinite zoom & pan

Works on any device

Native performance

Instant alerts

Monitor anywhere

AI-native observability

Continuous delivery

Open source foundation

80% Faster Incident Resolution

AI-powered troubleshooting from detection, to root cause and blast radius identification, to reporting.

True Real-Time and Simple, even at Scale

Linearly and infinitely scalable full-stack observability, that can be deployed even mid-crisis.

90% Cost Reduction, Full Fidelity

Instead of centralizing the data, Netdata distributes the code, eliminating pipelines and complexity.

See and Map Your Entire Network

Live topology, flow analytics, and SNMP device and trap monitoring — unified with your full-stack observability.

Control Without Surrender

SOC 2 Type 2 certified with every metric kept on your infrastructure.

Integrations

800+ collectors and notification channels, auto-discovered and ready out of the box.

800+ data collectors
Auto-discovery & zero config
Cloud, infra, app protocols
Notifications out of the box
> Explore integrations
Real Results
46% Cost Reduction

Reduced monitoring costs by 46% while cutting staff overhead by 67%.

— Leonardo Antunez, Codyas

Zero Pipeline

No data shipping. No central storage costs. Query at the edge.

From Our Users
"Out-of-the-Box"

So many out-of-the-box features! I mostly don't have to develop anything.

— Simon Beginn, LANCOM Systems

No Query Language

Point-and-click troubleshooting. No PromQL, no LogQL, no learning curve.

Enterprise Ready
67% Less Staff, 46% Cost Cut

Enterprise efficiency without enterprise complexity—real ROI from day one.

— Leonardo Antunez, Codyas

SOC 2 Type 2 Certified

Zero data egress. Only metadata reaches the cloud. Your metrics stay on your infrastructure.

Full Coverage
800+ Collectors

Auto-discovered and configured. No manual setup required.

Any Notification Channel

Slack, PagerDuty, Teams, email, webhooks—all built-in.

Built for the People Who Get Paged

Because 3am alerts deserve instant answers, not hour-long hunts.

Every Industry Has Rules. We Master Them.

See how healthcare, finance, and government teams cut monitoring costs 90% while staying audit-ready.

Monitor Any Technology. Configure Nothing.

Install the agent. It already knows your stack.
From Our Users
"A Rare Unicorn"

Netdata gives more than you invest in it. A rare unicorn that obeys the Pareto rule.

— Eduard Porquet Mateu, TMB Barcelona

99% Downtime Reduction

Reduced website downtime by 99% and cloud bill by 30% using Netdata alerts.

— Falkland Islands Government

Real Savings
30% Cloud Cost Reduction

Optimized resource allocation based on Netdata alerts cut cloud spending by 30%.

— Falkland Islands Government

46% Cost Cut

Reduced monitoring staff by 67% while cutting operational costs by 46%.

— Codyas

Real Coverage
"Plugin for Everything"

Netdata has agent capacity or a plugin for everything, including Windows and Kubernetes.

— Eduard Porquet Mateu, TMB Barcelona

"Out-of-the-Box"

So many out-of-the-box features! I mostly don't have to develop anything.

— Simon Beginn, LANCOM Systems

Real Speed
Troubleshooting in 30 Seconds

From 2-3 minutes to 30 seconds—instant visibility into any node issue.

— Matthew Artist, Nodecraft

20% Downtime Reduction

20% less downtime and 40% budget optimization from out-of-the-box monitoring.

— Simon Beginn, LANCOM Systems

Pay per Node. Unlimited Everything Else.

One price per node. Unlimited metrics, logs, users, and retention. No per-GB surprises.

Free tier—forever
No metric limits or caps
Retention you control
Cancel anytime
> See pricing plans

What's Your Monitoring Really Costing You?

Most teams overpay by 40-60%. Let's find out why.

Expose hidden metric charges
Calculate tool consolidation
Customers report 30-67% savings
Results in under 60 seconds
> See what you're really paying

Your Infrastructure Is Unique. Let's Talk.

Because monitoring 10 nodes is different from monitoring 10,000.

On-prem & air-gapped deployment
Volume pricing & agreements
Architecture review for your scale
Compliance & security support
> Start a conversation

Monitoring That Sells Itself

Deploy in minutes. Impress clients in hours. Earn recurring revenue for years.

30-second live demos close deals
Zero config = zero support burden
Competitive margins & deal protection
Response in 48 hours
> Apply to partner

Per-Second Metrics at Homelab Prices

Same engine, same dashboards, same ML. Just priced for tinkerers.

Community: Free forever · 5 nodes · non-commercial
Homelab: $90/yr · unlimited nodes · fair usage
> Get the Homelab Plan

$1,000 Per Referral. Unlimited Referrals.

Your colleagues get 10% off. You get 10% commission. Everyone wins.

10% of subscriptions, up to $1,000 each
Track earnings inside Netdata Cloud
PayPal/Venmo payouts in 3-4 weeks
No caps, no complexity
> Get your referral link
Cost Proof
40% Budget Optimization

"Netdata's significant positive impact" — LANCOM Systems

Calculate Your Savings

Compare vs Datadog, Grafana, Dynatrace

Savings Proof
46% Cost Reduction

"Cut costs by 46%, staff by 67%" — Codyas

30% Cloud Bill Savings

"Reduced cloud bill by 30%" — Falkland Islands Gov

Enterprise Proof
"Better Than Combined Alternatives"

"Better observability with Netdata than combining other tools." — TMB Barcelona

Real Engineers, <24h Response

DPA, SLAs, on-prem, volume pricing

Why Partners Win
Demo Live Infrastructure

One command, 30 seconds, real data—no sandbox needed

Zero Tickets, High Margins

Auto-config + per-node pricing = predictable profit

Homelab Ready
Free Video Course

8-episode Netdata tutorial by LearnLinux.tv

76k+ GitHub Stars

3rd most starred monitoring project

Worth Recommending
Product That Delivers

Customers report 40-67% cost cuts, 99% downtime reduction

Zero Risk to Your Rep

Free tier lets them try before they buy

AI Support Assistant, Available 24/7

Nedi has access to all official documentation, source code, and resources. Ask any question about Netdata—responds in your language.

Deployment & configuration
Troubleshooting & sizing
Alerts & notifications
Evidence-based answers
> Ask Nedi now

Never Fight Fires Alone

Docs, community, and expert help—pick your path to resolution.

Learn.netdata.cloud docs
Discord, Forums, GitHub
Premium support available
> Get answers now

60 Seconds to First Dashboard

One command to install. Zero config. 850+ integrations documented.

Linux, Windows, K8s, Docker
Auto-discovers your stack
> Read our documentation

76,000+ Engineers Strong

615+ contributors. 1.5M daily downloads. One mission: simplify observability.

Per-Second. 90% Cheaper. Data Stays Home.

Side-by-side comparisons: costs, real-time granularity, and data sovereignty for every major tool.

See why teams switch from Datadog, Prometheus, Grafana, and more.

> Browse all comparisons
Edge-Native Observability, Born Open Source
Per-second visibility, ML on every metric, and data that never leaves your infrastructure.
Founded in 2016
615+ contributors worldwide
Remote-first, engineering-driven
Open source first
> Read our story
Promises We Publish—and Prove
12 principles backed by open code, independent validation, and measurable outcomes.
Open source, peer-reviewed
Zero config, instant value
Data sovereignty by design
Aligned pricing, no surprises
> See all 12 principles
Edge-Native, AI-Ready, 100% Open
76k+ stars. Full ML, AI, and automation—GPLv3+, not premium add-ons.
76,000+ GitHub stars
GPLv3+ licensed forever
ML on every metric, included
Zero vendor lock-in
> Explore our open source
Build Real-Time Observability for the World
Remote-first team shipping per-second monitoring with ML on every metric.
Remote-first, fully distributed
Open source (76k+ stars)
Challenging technical problems
Your code on millions of systems
> See open roles
Meet the Team Behind Netdata
Conferences, meetups, and tradeshows where you can see Netdata in action and talk to the engineers who build it.
Live demos and deep dives
Book 1-on-1 meetings
Talks and panel sessions
Event recaps and photos
> See all events
Talk to a Netdata Human in <24 Hours
Sales, partnerships, press, or professional services—real engineers, fast answers.
Discuss your observability needs
Pricing and volume discounts
Partnership opportunities
Media and press inquiries
> Book a conversation
Your Data. Your Rules.
On-prem data, cloud control plane, transparent terms.
Trust & Scale
76,000+ GitHub Stars

One of the most popular open-source monitoring projects

SOC 2 Type 2 Certified

Enterprise-grade security and compliance

Data Sovereignty

Your metrics stay on your infrastructure

Validated
University of Amsterdam

"Most energy-efficient monitoring solution" — ICSOC 2023, peer-reviewed

ADASTEC (Autonomous Driving)

"Doesn't miss alerts—mission-critical trust for safety software"

Community Stats
615+ Contributors

Global community improving monitoring for everyone

1.5M+ Downloads/Day

Trusted by teams worldwide

GPLv3+ Licensed

Free forever, fully open source agent

Why Join?
Remote-First

Work from anywhere, async-friendly culture

Impact at Scale

Your work helps millions of systems

$ guides / nats / nats-stream-max-bytes-limit ▌

Operations Guides

NATS stream max_bytes: one stream hitting its limit while the server has room

Publishers to one JetStream stream start getting rejected with a “maximum bytes exceeded” error. You check the server: JetStream storage is at 40% of reserved_storage, the disk has hundreds of gigabytes free, and every server-level dashboard is green. Nothing about the server looks full.

What happened: max_bytes is a per-stream limit, independent of server-level and account-level JetStream quotas. One stream reached its own configured ceiling and started enforcing its discard policy while every other stream kept working. If your monitoring only watches aggregate JetStream storage (/jsz without parameters), this failure is invisible until publishers start erroring.

The inverse footgun makes this worse. A stream created with max_bytes: -1 (unbounded, and a common default in copied configs) will grow until it consumes the account-level or server-level storage budget, at which point every stream in that account starts rejecting writes. One misconfigured stream takes the rest down with it.

This guide covers how to confirm which limit was hit, how to fix it without losing data you did not intend to lose, and how to monitor per-stream utilization so the next occurrence pages you at 80% instead of at rejection time.

What this means

JetStream enforces storage limits at three independent levels:

  1. Per-stream: max_bytes in the stream configuration caps the total bytes that stream may store. Editable after stream creation.
  2. Per-account: JetStream resource limits configured on the account cap total JetStream memory and file storage for all streams in that account.
  3. Per-server: max_file_store / max_memory_store cap JetStream storage for the whole server, reported via /jsz as reserved_storage and reserved_memory.

A stream can be hard-blocked by its own max_bytes while levels 2 and 3 have abundant headroom. That is the incident this article covers.

Enforcement at max_bytes depends on the stream’s discard policy:

  • DiscardOld (default): the oldest messages are deleted to make room for new ones. Publishes keep succeeding. You lose data silently, and slow consumers lose messages they never saw.
  • DiscardNew: new publishes are rejected. Producers see the error immediately. This is the configuration that generates the incident page.

The same per-stream blindness applies on the growth side. If one stream is max_bytes: -1, no stream-level limit stops it. It consumes shared account or server storage until the aggregate limit trips, and then DiscardNew behavior applies account-wide: all streams start rejecting.

flowchart TD
  A[Publish rejected or old data missing] --> B{Stream state.bytes near config.max_bytes?}
  B -->|Yes| C[Per-stream limit hit]
  B -->|No| D{Aggregate jsz.storage near reserved_storage?}
  D -->|Yes| E[Server or account limit hit - likely an unbounded stream]
  D -->|No| F[Not a storage limit - check Raft, disk I/O, API errors]
  C --> G{Discard policy?}
  G -->|DiscardNew| H[Publishes rejected with maximum bytes exceeded]
  G -->|DiscardOld| I[Oldest messages silently deleted]

Common causes

CauseWhat it looks likeFirst thing to check
Stream sized too small for real trafficstate.bytes pinned at config.max_bytes, steady publish rejectionsstate.bytes / config.max_bytes ratio for the stream
Consumer stall filling the streamStream bytes climbing, first_seq static, consumers not ackingnum_pending and num_ack_pending per consumer
DiscardNew with LimitsPolicy retentionRejections continue even after consumers drain; stream does not auto-recoverStream config: discard and retention policy
Unbounded stream (max_bytes: -1)One stream’s bytes dwarf all others; aggregate storage near reserved limitPer-stream bytes sorted descending
0-byte store files after unclean shutdown (older versions)Stream grows past its configured max_bytes until server limit tripsnats-server version; affected versions pre-2.9.17
Stream max_bytes reservationNew streams fail with an insufficient memory/storage error even though usage is lowStream storage type and sum of configured max_bytes against the matching server quota

Two of these deserve detail because they are version-dependent and non-obvious:

0-byte files bypassing limits. Unclean shutdowns can leave 0-byte .blk and .fss files in the stream’s message store directory. Affected server versions failed to account for these files when enforcing max_bytes, so the stream grew past its own limit until it hit the server-level store limit. The initial fix in 2.9.11 was incomplete; the fuller fix landed in 2.9.17. If you are running older than 2.9.17 and have had unclean shutdowns, upgrade before trusting per-stream accounting.

Storage reservation by configured max_bytes. JetStream reserves max_bytes when a stream is created or resized, even if actual usage is near zero: memory streams count against max_memory_store, and file streams count against max_file_store. Operators have reported that several streams with large max_bytes values can exhaust the matching server quota and fail creation with “insufficient memory resources available” (error 10028) despite low real usage. Maintainers confirmed that JetStream does not over-commit reservations.

Quick checks

All read-only. Run against the monitoring port (default 8222).

# Per-stream bytes vs configured max_bytes: the core check
curl -s "http://localhost:8222/jsz?streams=true" | \
  jq '.account_details[].stream_detail[] |
      {name: .name,
       bytes: .state.bytes,
       max_bytes: .config.max_bytes,
       msgs: .state.messages,
       first_seq: .state.first_seq,
       discard: .config.discard}'

# Aggregate view: is the server or account actually full?
curl -s http://localhost:8222/jsz | \
  jq '{bytes, messages, memory, storage, reserved_memory, reserved_storage}'

# API errors: publish rejections show up here
curl -s http://localhost:8222/jsz | \
  jq '{api_total: .api.total, api_errors: .api.errors, inflight: .api.inflight}'

# CLI view of all streams with current usage
nats stream report

# Single stream detail: config, state, consumer count
nats stream info STREAM_NAME --json | \
  jq '{max_bytes: .config.max_bytes, discard: .config.discard,
       retention: .config.retention, state: .state}'

# If bytes are climbing, find stalled consumers on the stream
curl -s "http://localhost:8222/jsz?streams=true&consumers=true" | \
  jq '.account_details[].stream_detail[] |
      select(.name == "STREAM_NAME") |
      .consumer_detail[]? |
      {name: .name, num_pending, num_ack_pending, num_redelivered}'

Reading the output:

  • max_bytes: -1 means unbounded. Treat every unbounded stream as a liability until justified.
  • A first_seq that never advances while messages grows means nothing is being reclaimed: either no discards are happening (DiscardNew) or consumers are not acking (interest or workqueue retention).
  • api.errors is cumulative. Compute the rate between two scrapes; a sustained positive rate during the incident window confirms active rejections.

How to diagnose it

  1. Confirm the rejection is a per-stream limit, not the aggregate. Compare per-stream state.bytes against config.max_bytes for the erroring stream, and compare /jsz storage against reserved_storage. If the stream ratio is near 1.0 and the aggregate is not, you have the per-stream case.
  2. Read the discard policy. DiscardNew means producers are being rejected. DiscardOld means the stream is silently deleting its oldest messages. The remediation and the urgency of data-loss assessment differ completely.
  3. Check the retention policy and consumer state. With interest retention, messages are deleted only when all consumers have acknowledged them, so one stalled consumer blocks all space reclamation. With workqueue, any one consumer’s ack frees the message. With limits, retention is purely policy-driven. Find out which you are running before touching anything.
  4. Determine whether the stream is over-retaining or undersized. If consumers are healthy and keeping up, the limit is simply too small for current publish volume. If consumers are stalled (num_ack_pending at the configured MaxAckPending, or a dead consumer still registered), the limit may be fine and the real fault is the consumer.
  5. If the aggregate limit is the one being hit, find the unbounded stream. Sort per-stream bytes descending. The stream consuming a disproportionate share, especially one with max_bytes: -1, is your culprit. Fixing its limit or retention fixes every other stream.
  6. Check the server version against known accounting bugs. If the stream grew past its configured max_bytes at all, suspect the 0-byte file accounting bug on versions before 2.9.17, particularly after unclean shutdowns.
  7. For streams failing at creation time, remember the reservation behavior: the sum of configured max_bytes values for memory streams must fit inside max_memory_store, and the sum for file streams must fit inside max_file_store, regardless of real usage.

Metrics and signals to monitor

SignalWhy it mattersWarning sign
Per-stream state.bytes / config.max_bytesThe leading indicator this entire article is about; aggregate metrics hide itRatio > 0.8
Per-stream max_bytes == -1Unbounded streams can exhaust shared account/server storage and take other streams downAny unbounded stream without a documented reason
/jsz storage / reserved_storageThe aggregate ceiling an unbounded stream eventually tripsApproaching 90%
/jsz api.errors ratePublish rejections surface here; the lagging indicator of a full streamSustained positive rate
Per-consumer num_pending, num_ack_pendingStalled consumers fill streams under interest/workqueue retentionSustained growth; ack_pending at MaxAckPending
Stream first_seq movementStatic first_seq with growing messages means no reclamation is happeningDivergence from last_seq over time

Use a ratio, not an absolute threshold: alert when state.bytes / config.max_bytes exceeds 0.8 per stream. Absolute thresholds break across streams of different sizes. Per-stream data requires /jsz?streams=true, which returns much more data than the bare endpoint; on servers with very many streams, poll it at a slower interval than your core metrics.

Fixes

The limit is too small for real traffic

Raise max_bytes on the stream. It is editable after creation:

# Raise the limit on an existing stream (example: 50 GiB)
nats stream edit STREAM_NAME --max-bytes 50GB

One destructive caveat: lowering max_bytes on a stream that currently holds more than the new limit deletes messages immediately to fit the new limit, with no grace period. Raising is safe; shrinking deletes data on the spot.

Also confirm the server and account can afford the new per-stream limit. The sum of all stream limits should fit inside reserved_storage with at least 25% aggregate headroom to absorb bursts, consumer slowdowns, and compaction overhead.

The stream is full because consumers are stalled

Raising max_bytes buys time but does not fix the fault. Fix the consumer: restart or scale the consuming application, and check whether num_ack_pending is pinned at the consumer’s MaxAckPending (delivery stalled) or whether the consumer is simply gone while still registered. Under interest retention, a dead consumer blocks all reclamation. Deleting a consumer you have confirmed is dead immediately makes its pending messages eligible for deletion; understand that this discards those messages.

For a DiscardNew stream that has already hit the wall: it does not auto-recover when consumers drain, because acknowledged messages are not removed under limits retention. Your options are to purge messages explicitly, raise max_bytes, or change the discard policy to DiscardOld. Purging is destructive; confirm downstream consumers have processed or no longer need the data first.

An unbounded stream is eating shared storage

Set an explicit max_bytes on the offending stream, sized from its real growth rate, and choose a discard policy deliberately. This immediately bounds its blast radius. If the aggregate limit has already tripped and other streams are rejecting, freeing space from the runaway stream (purge, or a lower max_bytes with the immediate-deletion caveat above) restores service for everything else.

To prevent recurrence at the account level, nats-server supports max_bytes_required (since v2.7.0): when set, every stream in the account must declare an explicit max_bytes, so new unbounded streams cannot be created. Companion account settings memory_max_stream_bytes and disk_max_stream_bytes cap how large any single stream’s limit may be. These guardrails make this incident class structurally impossible.

You are on an affected server version

If per-stream accounting has been violated (stream past its own limit) and you are pre-2.9.17 with a history of unclean shutdowns, upgrade. When sizing streams, size max_memory_store against the sum of configured memory-stream max_bytes, and max_file_store against the sum of configured file-stream max_bytes, not observed usage.

Prevention

  • Set max_bytes on every stream, no exceptions. Treat -1 as a misconfiguration. Where you cannot set it organizationally, enforce it technically with account-level max_bytes_required.
  • Alert on the per-stream ratio. Warn at state.bytes / config.max_bytes > 0.8, critically above 0.9, per stream. Aggregate storage alerts alone will never catch this incident.
  • Choose the discard policy deliberately. DiscardOld is silent data loss for slow consumers. DiscardNew is loud producer failure. Neither is wrong, but you should know which failure mode each stream will exhibit before it happens.
  • Match retention to consumer reality. Interest retention plus one flaky consumer equals a stream that never reclaims. If consumers are unreliable, limits retention with a sane max_bytes and DiscardOld may be safer.
  • Budget limits against capacity. Sum the per-stream max_bytes values per server and per account, and keep the total inside the aggregate quota with at least 25% headroom. JetStream reserves configured max_bytes against the matching storage quota, so this is not optional.
  • Include per-stream utilization in capacity review. A stream trending from 0.5 to 0.8 of its limit over a month gives you weeks of runway to resize. See the capacity section of how NATS works in production for the broader saturation model.

How Netdata helps

  • Netdata collects JetStream aggregates from /jsz (bytes, messages, memory, storage, reserved quotas, API totals and errors), so the server-level side of this incident is visible continuously rather than on demand.
  • The api.errors rate is the lagging signal for publish rejections; charting it alongside storage utilization tells you whether rejections correlate with a storage ceiling or with something else (Raft, disk I/O).
  • Correlating JetStream storage growth with consumer-side symptoms (publish rates, throughput asymmetry) helps distinguish “stream undersized” from “consumer stalled” without logging into the server.
  • Uptime tracking catches the unclean-shutdown scenario behind the 0-byte file accounting bug on older server versions, which is when per-stream limits stop being trustworthy.
  • Netdata’s NATS collector currently reports aggregate JetStream figures, not per-stream state.bytes / config.max_bytes ratios; per-stream alerting requires polling /jsz?streams=true separately.