Skip to main content

Andromeda's own bounds

The specification sets none of these limits. Each one exists for a storage or resource reason, and each refusal uses the error type the specification gives for an implementation limit.

  • Tenant name: [A-Za-z_][A-Za-z0-9_-]*, at most 1,005 octets

    The specification types the tenant as a string and sets no length. The length is the identifier limit less the 19 octets of urn:ngsi-ld:Tenant:, because a tenant is also exposed as a resource under that identifier. Refused with 400 BadRequestData.

  • Identifier length: 1,024 UTF-8 octets

    PostgreSQL refuses an index entry over 2,704 bytes, and some index keys hold two identifiers. Refused with 400 BadRequestData.

  • Scope: 1,000 characters per level, 3,000 encoded bytes per Scope

    That is the limit of the index the Scope search runs on. Refused with 400 BadRequestData.

  • Number size: 131,072 digits before the decimal point and 16,383 after

    That is the range PostgreSQL NUMERIC holds exactly. Refused with 400 BadRequestData.

  • Request header section: 32 KiB, set by request_limits.max_header_section (8 KiB to 32 KiB)

    Limits the memory each request head takes. It is measured the same way on HTTP/1.1, HTTP/2 and HTTP/3, so every protocol gives the same answer. Refused with a bare 431.

  • Request body: 64 MiB, set by request_limits.max_body

    Limits the memory per request. Refused with 413 RequestEntityTooLarge.

  • JSON values per request: 4,000,000, set by request_limits.max_json_values

    Limits the memory per request. Refused with 413 RequestEntityTooLarge.

  • JSON values per entity: 1,000,000, set by request_limits.max_entity_json_values

    Limits the memory per stored entity. The values inside a Property's value and valueList are counted as the write reads them. The entries of a Relationship object, a ListRelationship objectList, a VocabProperty vocab, a LanguageProperty languageMap and the entity scope are counted before the member is expanded, and so are the attributes, instances and sub-attributes themselves, each by the rule the entity count uses for it. A write far over the limit is refused before the broker builds the rest of it. That holds even when the @context uses a feature the broker's own expansion doesn't model and the JSON-LD processor expands the request instead, because such a request is counted from its decoded form, whatever the context, before the processor sees it. Refused with 413 RequestEntityTooLarge.

  • Positions per geometry: 1,000,000, set by request_limits.max_geometry_positions

    Limits the memory per geometry. Refused with 413 on a write and 403 TooComplexQuery on a query. In a create, update, replace or merge body, a partial attribute update or replace attribute body, a temporal write or a batch item, a geometry is read no further than three times the limit in ordinates, since a position holds at most three. Refusing one there costs the same memory whatever its size. A geometry in a registration, and the coordinates of a geoQ, are counted once they have been read whole.

  • Nesting per attribute: 32 levels, set by request_limits.max_attribute_nesting (at most 62)

    Every stored value has to read back through a JSON reader that refuses 128 nested containers. A q or orderBy path walks at most the default 32 levels, and linked-entity hops count against the same budget. Refused with 400 BadRequestData.

  • Comparisons per q filter: 1,000, set by request_limits.max_q_comparisons

    Each comparison is a test of its own against the stored values. Every Query Term counts one, and a value list such as color=="red","blue" counts one per value. The limit applies to entity and temporal queries, deletes by query, and subscriptions. Refused with 403 TooComplexQuery.

  • Nesting per q filter: 16 levels, set by request_limits.max_q_nesting (at most 64)

    Each level of ; and | combinations adds a level to the condition the store evaluates. a;b nests one level, a;(b|c) and a|b;c two, and parentheses around a single Query Term add none. Parentheses written more than 64 deep are refused whatever the setting, before the rest of the filter is read. Refused with 403 TooComplexQuery. A stored subscription isn't checked again when either limit is lowered.

  • @context document size: 2 MiB, set by jsonld.fetch.max_size

    Limits the memory per context fetch. Answered with 504 LdContextNotAvailable.

  • @context reference depth: 8

    Limits context resolution. Refused with 400 BadRequestData.

  • Request duration: 30 s, set by request_limits.timeout

    Limits the resources one request holds. Answered with 408 RequestTimeout while the request body is still arriving, and with 500 InternalError after that.

  • Page size: a limit of at most 1,000

    Applies to every paged collection, meaning entities, temporal evolutions, subscriptions, context source subscriptions, registrations, @contexts and tenants. The page size is the limit you ask for, so a larger limit is refused rather than answered with a smaller page. Refused with 403 TooManyResults, which names the cap.

  • Page bytes: 64 MiB a page, set by request_limits.max_page_body

    Applies to the collections of entities, temporal evolutions, subscriptions and registrations. How many items a page holds doesn't tell what it costs once rendered, so a page whose rendered body goes over the ceiling is refused whole rather than cut short. Ask for a smaller limit and follow the next page pointer. Refused with 403 TooManyResults, naming the page size and the ceiling. The page is rendered before it is measured, so the refusal doesn't save the cost of rendering it.