Pre-1.0 hoardDB is pre-1.0. Expect breaking changes.

Limits

Every size and count that hoardDB enforces, with its default, how to change it and what you see when you reach it. This page is the numbers; Limitations is the list of things hoardDB does not do, and explains the reasoning behind several of these.

A limit that an operator can change is a setting of one node. A write that reaches a replica is not checked against the replica’s own value, so keep these settings the same on every node of a cluster.

How big can one thing be

WhatDefaultYou can setSettingWhen you reach it
A document24 MiB (25,165,824 bytes)4 KiB to 30 MiB (4,096 to 31,457,280 bytes)HOARDDB_MAX_DOCUMENT_BYTES, storage.max_document_bytesThe write is refused; an update that would grow a document past it is refused and leaves the document unchanged
A blob16 MiB (16,777,216 bytes)1 byte to 31.9 MiB (33,488,896 bytes)HOARDDB_MAX_BLOB_BYTES, storage.max_blob_bytesThe write is refused
One protocol frame32 MiB (33,554,432 bytes)fixednoneThe server closes the connection and logs closing connection: bad frame with frame length N exceeds maximum 33554432
What one query may hold in memory16 MiB1 MiB to 24 MiB (a smaller value is raised to 1 MiB, with a warning)HOARDDB_QUERY_MAX_RESULT_BYTES, query.max_result_bytesThe query is refused with RESULT_TOO_LARGE
One atomic batch15% of the memtable (20 MB at 128 MiB)follows storage.memtable_mbHOARDDB_MEMTABLE_MBThe whole batch is refused and nothing of it is written
One statement typed in the CLI64 KiB per linefixednoneCLI error: read input: bufio.Scanner: token too long
A bucket’s size, or the documents in itno limitThe disk is the bound

Why the document and blob limits are not 32 MiB. Everything a client sends, and the copy a node sends to a replica, travels in one frame of at most 32 MiB, and the frame also carries the key, the bucket name and the request’s envelope. The ceilings leave room for that: a document tops out at 30 MiB, and a blob at 32 MiB less 64 KiB. A value outside the range you can set stops the server from starting, with a message naming the setting and the range; it is never quietly lowered.

What the refusals say. They state the size you sent, the limit this server is running with, the setting that changes it and what to do instead:

Blob "videos/intro.mp4" is 5.0 GiB; this server's limit is 16 MiB
(storage.max_blob_bytes, maximum 31.9 MiB). For larger files, keep the file on
your own storage and store a pointer document — see "Large file stores" in the
docs.
<label> is <size>; this server's limit is <limit> per document
(storage.max_document_bytes, maximum 30 MiB).

The CLI refuses a blob larger than the 31.9 MiB ceiling before it sends any of it, since no server would accept it.

What to do instead of raising a limit.

  • A list that keeps growing belongs in a nested store field, whose elements are stored separately and do not count towards the parent document.
  • A file that is large belongs on storage you run, with a pointer document in hoardDB. Large file stores is the pattern.
  • A bulk load that is refused for its size is a bulk load that should be split: hoardDB-cli ingest halves a refused batch and retries, so a file of any size loads. See Load a file.

How many buckets

A bucket is a key range in the one store a node keeps for all its buckets. It costs no file, no file descriptor, no memory mapping and no goroutine of its own, and it adds one small entry to the node’s in-memory catalog. Adding a bucket is adding keys, not opening anything.

The figure to plan around is thousands of buckets per node. hoardDB is built for many small buckets, one per user or per post, and it does not publish a larger number until it has measured one on this layout. Higher counts may work on your hardware; they are not a promise. What a bucket costs, and how to see how many a node serves, is in Is this node full?.

hoardDB keeps no metric per bucket. A series per bucket is not viable at these counts, so the metrics are totals for the node, and per-bucket detail is a command you run (describe bucket, stats).

The memtable

The memtable is the write buffer in front of the node’s one store. It is a per-node setting: every bucket shares it, so it does not grow with the number of buckets.

A new node picks its size once, from the memory it is allowed (its container or cgroup limit, or the machine’s RAM), and keeps it on every restart:

Memory limitMemtable chosenLargest atomic batch (15%)Memory a heavy write burst can reach
below 3.5 GiB32 MiBabout 5 MB (5,033,164 bytes)about 460 MB
3.5 GiB to below 7 GiB64 MiBabout 10 MB (10,066,329 bytes)about 725 MB
7 GiB and above128 MiBabout 20 MB (20,132,659 bytes)about 1.25 GB

The automatic choice never goes above 128 MiB. The last column is a prediction for one client loading in batches, about 200 MB plus 8.2 MB for every MiB of memtable; many concurrent writers need more.

To choose it yourself, set storage.memtable_mb (HOARDDB_MEMTABLE_MB) to a value from 32 to 1024 MiB. Sizes of 256 MiB and above are only ever set this way. A value outside the range stops the server at start:

storage.memtable_mb is 8, below the minimum of 32. The store's largest atomic
batch is 15% of the memtable, and under 32 MiB it drops below 5 MB, which the
ingest batch budget and batch splitting assume. Set storage.memtable_mb (or
HOARDDB_MEMTABLE_MB) to a value from 32 to 1024, or remove it to run at the size
this node's store chose at its first start

A bigger memtable stalls writes less and holds up to three of them in memory, each needing about 1.3 times its size, so 1024 MiB is already about 3.9 GB. It is fixed at start. A node that crashed at a larger size cannot be opened at a smaller one until it has been started once at the old size and stopped cleanly. Configuration shows how to read the size a node chose, and why.

Connections and requests

WhatDefaultRangeSetting
Concurrent client connections per node1,000HOARDDB_MAX_CONNS
Concurrent connections from one address640 turns the cap offHOARDDB_TCP_MAX_CONNS_PER_IP
Connections kept for other nodes64HOARDDB_MAX_PEER_CONNS
Idle time before a connection is closed300 secondsHOARDDB_TCP_IDLE_TIMEOUT
Time to read one frame30 secondsHOARDDB_TCP_FRAME_TIMEOUT
Requests a client may have in flight on one connection41 to 64HOARDDB_TCP_PIPELINE_FRAMES
Bytes of those requests1 MiB1 MiB to 16 MiB (a smaller value is raised to 1 MiB, with a warning)HOARDDB_TCP_PIPELINE_BYTES
Queries running at oncetwice the CPU count4 to 256HOARDDB_QUERY_CONCURRENCY
Failed logins in a row before an address is refused200 turns the limit offHOARDDB_TCP_AUTH_MAX_FAILS
Shortest user password12 charactersHOARDDB_PASSWORD_MIN_LENGTH

The client budget (HOARDDB_MAX_CONNS) and the node-to-node budget are separate, so a flood of clients cannot starve replication. A connection carries one request at a time unless the client reads ahead within the window above; a client that wants concurrency opens another connection. A query past the concurrency limit waits; it is not refused.

A value outside a range with a stated clamp is brought to the nearest end of it when the server loads its configuration. The sizes in the first table are the other kind: outside their range, the server refuses to start.

Checking a limit against your data

Before you rely on a limit, try it at its edge on your own data. The sizes and counts above are what the build enforces, and they were read from its configuration, not measured on your workload: your hardware, your kernel’s file-descriptor and memory-mapping limits, and the shape of your documents decide where a node becomes slow before any of them is reached. Is this node full? lists the resources that bind first and what to do about each.

Source: docs/user/limits.md in the repository.