Limits¶
fdyno is constrained by three different contracts. They must not be treated as one quota system:
- DynamoDB-documented constraints define the client behavior fdyno aims to reproduce.
- fdyno validation and workflow boundaries are what the current implementation rejects, splits, filters, or leaves to operators.
- FoundationDB limits apply to the encoded physical transaction after base chunks, indexes, stream images, metadata, keys, and conflict ranges are included.
DynamoDB sizes use binary units (1 KiB = 1,024 bytes), although AWS labels them KB
and MB. FoundationDB's affected-data, key, and value limits below are exact decimal
byte counts from its documentation.
Limit table¶
| Area | Current boundary | Kind / owner | Observable result | Mitigation | Source |
|---|---|---|---|---|---|
| Protocol: request line or headers | 16 KiB each at fdyno's application check | Hard · fdyno | HTTP 431 Request Header Fields Too Large |
Reduce cookies/custom headers and signed-header set; use a proxy with compatible limits | code |
| Protocol: request body | 16 MiB raw and after decompression | Hard · fdyno | Request rejected before action execution; no mutation | Split requests; compression cannot bypass the decompressed cap | code · tests |
| Query / Scan page | Approximately 1 MiB of accepted/scanned item data per response page | Hard page boundary · fdyno, modeled on DynamoDB | LastEvaluatedKey is returned; the page may include the item crossing the internal budget |
Continue from LastEvaluatedKey; do not assume one snapshot across pages |
code · AWS |
| Item | 400 KiB, including attribute-name and value sizes under fdyno's DynamoDB sizing logic | Hard · fdyno validation / DynamoDB | ValidationException; write does not commit |
Split the logical object across items or externalize large payloads | code · tests · AWS |
| Primary-key value | Partition key 2,048 bytes; sort key 1,024 bytes | Hard · fdyno validation / DynamoDB | ValidationException beyond the bound; selected tests accept 2,048 and reject 2,049 partition-key bytes on write and read |
Hash or shorten external identifiers while preserving collision handling | code · boundary tests · AWS |
| Nested document or expression value | 32 levels; 31 map wrappers plus a leaf at level 32 is accepted, while 32 wrappers plus a leaf at level 33 is rejected | Hard · fdyno validation / DynamoDB | ValidationException before Put, Delete, Update, or transaction mutation evaluation |
Flatten the document or split it into related items | code · test · AWS |
| Expression parameter | 4,096 bytes in the raw expression string; 4,097 rejected for Update, Condition, Query/Scan Filter, and Projection | Hard · fdyno validation / DynamoDB | ValidationException with the expression-size diagnostic |
Shorten attribute paths or split work; alias expansion does not count against the raw expression string | code · tests · AWS |
BatchGetItem |
100 keys total and per table | Hard · fdyno validation / DynamoDB | ValidationException; no batch read |
Split key sets and combine results client-side | code · tests |
BatchWriteItem |
25 put/delete requests total and per table | Hard · fdyno validation / DynamoDB | Invalid request: ValidationException; physically oversized valid request: chunks may commit and failures return in UnprocessedItems |
Retry only UnprocessedItems; use TransactWriteItems when all-or-nothing is required |
code · AWS |
| Batch 16 MiB limit | AWS documents 16 MiB for BatchGetItem results and BatchWriteItem requests; fdyno has a generic 16 MiB request-body cap, but no focused test verifies a 16 MiB BatchGetItem result limit |
Compatibility boundary · mixed | Requests over fdyno's body cap fail; large batch-read response behavior should not be assumed identical | Keep batches below both count and payload bounds; test large-result behavior | AWS · fdyno edge |
| Transaction actions | 100 actions for TransactGetItems, TransactWriteItems, and PartiQL ExecuteTransaction |
Hard · fdyno validation / DynamoDB | ValidationException |
Split only if application invariants permit; otherwise redesign the transaction boundary | code · tests |
| DynamoDB transaction data | AWS documents 4 MiB for TransactWriteItems and TransactGetItems; fdyno currently prechecks 4 MiB across Put item bodies for TransactWriteItems, and no separate 4 MiB TransactGetItems result enforcement was identified |
Hard TWI precheck + compatibility gap · fdyno | Oversized Put total: ValidationException; other aggregate cases remain subject to the physical FoundationDB limits |
Reduce item/action count; test large updates and transaction reads; leave room for physical amplification | code · AWS |
| FoundationDB transaction | 10,000,000 bytes of affected data, including written keys/values/ranges and read/conflict keys/ranges | Hard · FoundationDB | FDB size error; transactional fdyno paths map size/key/value errors to ValidationException; BatchWriteItem may split only for transaction-too-large |
Reduce the atomic write/read set; project less; use bounded workflow transactions where atomicity is not required | FDB · mapping |
| FoundationDB transaction lifetime | Transactions over five seconds from the first read are unsupported | Hard · FoundationDB | Usually transaction_too_old / not_committed; fdyno retries until its operation budget or returns an error |
Keep transaction callbacks short; page maintenance; reduce contention/load | FDB |
| FoundationDB key / value | Key: 10,000 bytes; value: 100,000 bytes | Hard · FoundationDB | FDB key/value-too-large error, normally mapped to ValidationException on data paths |
fdyno chunks item, index, stream, backup, restore, and receipt payloads; table metadata remains one value | FDB · storage inventory |
| Number | At most 38 significant digits; non-zero magnitude from 1E-130 through 9.9999999999999999999999999999999E+125, and the negative mirror |
Hard · fdyno validation / DynamoDB | ValidationException for malformed/whitespace-bearing N strings, or a transaction cancellation reason where that API reports item validation per action; valid leading signs, exponent forms, and zero forms read back canonically |
Send exact decimal strings and validate before arithmetic | code · precision tests · format tests · AWS |
| Secondary-index count | 20 GSIs and 5 LSIs per table | Hard · fdyno validation; DynamoDB's 20-GSI value is a default quota, fdyno's is not adjustable | ValidationException during create/update |
Consolidate access patterns or denormalize data | code · tests · AWS |
INCLUDE projection |
20 named non-key attributes per index; 100 occurrences summed across all GSIs/LSIs | Hard · fdyno validation / DynamoDB | ValidationException |
Use KEYS_ONLY/ALL where appropriate or reduce duplicate projections |
code · AWS |
| LSI item collection | DynamoDB documents 10 GiB per partition-key item collection when LSIs exist; no equivalent aggregate fdyno validator was found | Compatibility gap / cluster-dependent · fdyno | Do not expect an early ItemCollectionSizeLimitExceededException; eventual constraints are FoundationDB capacity/transaction behavior |
Test large item collections and monitor storage; redesign hot/unbounded partitions | AWS · evidence memo |
| Stream shard topology | Default 1; fixed count 1–100 persisted per enabled generation | Hard configuration range + generation immutability · fdyno | Invalid environment defaults use 1; changing count requires a new empty generation and invalidates old iterators | Choose before enablement; consume the persisted shards returned by DescribeStream |
code · Change streams |
GetRecords page |
1–1,000 records; default 1,000 | Hard · fdyno validation / DynamoDB compatibility | Out-of-range limit returns ValidationException |
Poll repeatedly and checkpoint the last durable sequence number | code |
| Stream record storage | Direct FDYNOC01 through 10,000 bytes; larger binary records use at most 1,024 chunks with a versioned manifest; legacy JSON records remain readable |
Hard · fdyno bounds and FoundationDB transaction size | Oversized or corrupt records fail the operation; item, index, and record never commit partially | Prefer KEYS_ONLY when transaction amplification matters; test maximum-shaped mutations |
code · storage inventory |
| Stream retention | Unlimited growth when trimmer is off; when enabled, retention defaults to 24 hours and each pass examines a configurable bounded prefix (default 1,000 records per table/shard) | Soft / configuration-dependent · fdyno | Storage grows without bound when off; when enabled, a lagging consumer can lose trimmed records without an explicit gap error | Set and capacity the trimmer, synchronize clocks, and monitor oldest record vs checkpoint externally | startup · implementation |
| TTL visibility and reclamation | Expired items are hidden on selected reads; bounded physical sweep starts by default at 1m and can be disabled with DYNODB_TTL_SWEEP_INTERVAL=off or 0 |
Soft / API- and configuration-dependent · fdyno | GetItem, BatchGetItem, Query, and Scan hide expiry; disabled sweep leaves untouched expired storage; TransactGetItems and reviewed PartiQL reads do not apply the same filter |
Keep sweep enabled and monitor it; test every read API; never use physical deletion time as a correctness clock | startup · TTL code · compatibility |
| Table backup snapshot | No fixed table-size promise; all pages must remain readable at one pinned FoundationDB version | Soft workflow boundary · data size/load/cluster dependent | ValidationException when the read version ages out; no mixed-version backup is published |
Use fdyno backup only for bounded table copies; use FoundationDB-native backup for unbounded/DR workflows | code · Backup & restore |
| Backup/restore memory and recovery | One decoded and encoded backup page is held at a time; large restores use durable batches and resumable progress | Soft workflow boundary · fdyno/host | The request can end while recovery continues; a fenced target remains CREATING and unavailable until complete |
Wait for ACTIVE, validate before cutover, and monitor stale/failed jobs |
code · runbook |
| Foreground operation budget | 30 seconds by default, configurable; retries and all workflow transactions share the HTTP request budget | Soft configuration boundary · fdyno | Deadline error; after a commit attempt the message states that outcome may be unknown | Set client/server deadlines coherently; use a stable transaction token or reconcile state | code · Reliable writes |
| Throughput, concurrency, table size/count | No fdyno request-unit throttle, concurrency gate, or universal throughput/table-size promise | Cluster-dependent · operator | Saturation appears as latency, memory pressure, FDB errors, deadlines, or unavailability; this is not a reliable DynamoDB throttling signal | Load-test the exact topology; add external admission control; monitor FoundationDB capacity and fault tolerance | operations · current measurement scope · capacity code |
Protocol and item boundaries¶
The 16 MiB body limit applies to every fdyno request, not only DynamoDB batch APIs. The body is bounded before signature verification and again after decompression, so a small compressed payload cannot expand without limit. A focused black-box test for the exact fdyno 16 MiB boundary has not been identified; existing manual-request tests cover oversized input and compression behavior.
The 400 KiB item check is logical DynamoDB sizing. fdyno then encodes and, for base storage, divides larger encoded values into 10,000-byte chunks. Chunking avoids FoundationDB's single-value ceiling but does not exempt the operation from the 10,000,000-byte affected-data limit, and it does not apply to every value type. Stream records are a counterexample.
Query and scan pagination is an API boundary, not a consistency lease. The next call
starts after LastEvaluatedKey in a new FoundationDB read transaction. See
Consistency model.
Batch and transactional boundaries¶
BatchWriteItem and TransactWriteItems have different failure
contracts:
TransactWriteItemsmust fit one FoundationDB transaction. It is never split; an oversized physical transaction is rejected.BatchWriteItemis non-atomic. fdyno first attempts one transaction. On FoundationDBtransaction_too_large, it validates the whole request in a rolled- back transaction, estimates conservative chunks under a 4 MiB internal budget, and commits chunks separately. Runtime failures are returned inUnprocessedItems.
The 4 MiB transactional precheck is not a guarantee that a request will fit FoundationDB. Current code totals Put item bodies at that check. Update results, chunk keys, active index projections, binary stream records, metadata, idempotency state, and conflict ranges contribute to the physical transaction and can lower the effective ceiling. Test maximum-shaped requests with the same indexes and stream view as production.
FoundationDB transaction limits¶
FoundationDB defines transaction size as affected data, not only values written. Written keys, values, and ranges count; read keys/ranges and explicit conflict ranges also count, while values that are only read do not. Its documentation additionally advises redesigning transactions above one megabyte because they can hurt performance, even though the hard maximum is 10,000,000 bytes. Treat that one-megabyte statement as FoundationDB design guidance, not an fdyno validation threshold.
fdyno's 30-second default operation budget does not extend FoundationDB's five-second
transaction lifetime. It permits retries and multi-transaction workflows to share a
bounded request lifetime. The service maps FoundationDB error codes 2101–2103
(transaction, key, and value too large) to an actionable DynamoDB-shaped
ValidationException on mapped data paths.
Numbers and indexes¶
Numbers are parsed and compared as exact decimal values rather than converted as a
whole through float64. Accepted values are normalized, including exponent
expansion and removal of insignificant zeroes. The limit still applies after
arithmetic: an update that produces excess precision or magnitude fails rather than
rounding silently.
The index-count limits are fdyno hard validations. This differs from AWS's service- quota model, where the documented 20-GSI value is a default that may be adjustable. fdyno also does not establish DynamoDB's aggregate 10 GiB LSI item-collection limit; its reported item-collection size metrics are not a substitute for enforcing or measuring that AWS storage boundary. AWS also documents a 400 KiB combined limit for a base item plus its corresponding LSI entries. fdyno's current item validator measures the logical item; no equivalent combined LSI-size validation was identified. The encoded index writes still count against FoundationDB's physical transaction limits.
Every index increases the physical transaction size. An ALL projection can duplicate
most of an item in each index entry; an INCLUDE projection duplicates selected
attributes. Count limits therefore do not imply that a maximum-size item with the
maximum number of indexes fits one FoundationDB transaction.
Stream and TTL worker settings¶
DYNODB_STREAM_SHARDS is the process default for a newly enabled generation. fdyno
stores the selected count in table metadata. The range 1–100 is an implementation
limit, not a DynamoDB quota. Static shards add consumer parallelism but not commit
capacity. Iterators do not expire on the server.
Retention and TTL reclamation are bounded background work rather than instantaneous guarantees. Their configured scan maximum is per pass, so a worker can fall behind when arrivals exceed sustained cleanup. Both rely on host wall clocks. Zero or negative durations are not safely rejected by all startup paths; validate deployment configuration before launching workers.
TTL read behavior is narrower than physical deletion. Selected reads hide an expired item immediately according to host time, then lazy cleanup or the sweeper rechecks expiry in the deleting transaction. A concurrent refresh is therefore not deleted by a stale sweep. Until deletion commits, storage and any API path that does not call the TTL filter can still encounter the row.
Backup and operational boundaries¶
fdyno table backup has no advertised maximum item count or byte size. Creation and restore use bounded decoded pages and verified chunks, but every source page must still read one pinned FoundationDB version before it ages out. fdyno fails rather than moving to a newer version mid-snapshot. This is a consistency-preserving failure, not a capacity promise.
Backup data is stored in the same FoundationDB database as the source. It shares the cluster's failure domain and does not supply a second disaster-recovery copy. Historical PITR is unsupported: enablement and restore fail explicitly rather than returning current state under a historical label.
There is no universal requests-per-second, concurrent-request, table-count,
database-size, availability, RPO, or RTO number for fdyno. Those values depend on
FoundationDB topology, storage engine, hardware, data distribution, conflict rate,
item, index, and stream sizes, and external admission control. DescribeLimits returns
fixed compatibility-shaped values; they are not enforced cluster capacity and are
not repeated here.
Evidence sources and gaps¶
When sources disagree or cover different layers, interpret them in this order:
- AWS DynamoDB constraints describe DynamoDB, not automatically fdyno.
- The linked fdyno implementation and black-box tests establish current fdyno validation and behavior.
- FoundationDB known limitations constrain the encoded transaction regardless of DynamoDB request validity.
These gaps require tests. Do not infer guarantees for them:
- No focused black-box test was located for the exact 16 MiB raw/decompressed body boundary.
- No systematic matrix measures physical transaction amplification at the exact FoundationDB limits across item size, index projection, and stream view.
- Static multi-shard streams lack a normal CI matrix across configured shard counts, and iterator expiration is absent.
- Backup snapshot expiry and interrupted restore behavior have no published tested size range.
- TTL filtering is not uniform across every read API in the reviewed code.
- No published benchmark establishes cluster-independent throughput or tail latency.
For related behavior and limits, continue with Guarantees, Tradeoffs, Transactions, and Deployment & operations.