Skip to navigation

Record limits and key rules

This page lists the size limits that Runtype applies when you write a Record, the rules that it uses to rename metadata keys, and the vector search features that each vector store supports. A write that breaks a limit fails with 400 and stores nothing.

Size limits

The following table lists the limits for each Record:

FieldLimitError code
type255 charactersRequest validation error
name500 charactersRequest validation error
metadata size256 KB (262,144 bytes) as UTF-8 JSONMETADATA_TOO_LARGE
metadata top-level keys200 keysMETADATA_TOO_MANY_KEYS
metadata key length64 characters, measured after normalizationMETADATA_KEY_TOO_LONG
metadata nesting depth5 levels. The top-level object is level 1.METADATA_TOO_DEEP
messages count10,000 messagesMESSAGES_TOO_LARGE
One message’s content1 MB (1,048,576 bytes) as UTF-8 JSONMESSAGES_TOO_LARGE
All messages content32 MB (33,554,432 bytes) in totalMESSAGES_TOO_LARGE

The key count and key length limits apply to top-level keys only. Keys inside nested objects count toward the size and depth limits.

Runtype checks the limits against the metadata that the write produces. An update with metadata replaces the whole object, so the replacement object must fit. A bulk edit merges your changes into each Record first, so a bulk edit that adds keys can push a Record over the key limit.

The same limits apply to the Upsert Record and Update Record Flow steps and to Agent tools that write Records. In a CSV import, a row that breaks a limit fails, and the other rows are still imported.

Limit error response

A metadata or messages limit error has the following shape:

{
"error": "record_payload_too_large",
"details": [
{
"code": "METADATA_TOO_MANY_KEYS",
"message": "Record metadata has 214 keys, which exceeds the 200-key limit.",
"path": "metadata"
}
]
}

For a MESSAGES_TOO_LARGE error, path is messages. Runtype reports only the first limit that a write breaks.

Metadata key normalization

Runtype converts each top-level metadata key to lowercase snake_case before it stores the Record. The Runtype API applies this rule, so it applies to the dashboard, the TypeScript SDK, the runtype CLI, the Runtype MCP server, and CSV import.

Runtype changes each key as follows:

  1. Removes spaces at the start and end.
  2. Converts letters to lowercase.
  3. Replaces each run of characters other than a to z and 0 to 9 with one underscore.
  4. Removes underscores at the start and end.

The following table shows examples:

Key that you sendStored key
First Namefirst_name
orderIDorderid
Price (USD)price_usd
e-maile_mail
cafécaf

Runtype keeps each original key as a display label in metadataLabels. Keys inside nested objects keep their original form.

The Upsert Record and Update Record Flow steps do not normalize keys. They store keys exactly as the source object has them.

Renamed keys (KEY_RENAMED)

Two keys can normalize to the same name, such as Email and email. Runtype stores the first key under the normalized name. It stores each later key under the normalized name plus an underscore and the key’s position in the object, counted from zero. The write succeeds, and the response includes a warnings array with one KEY_RENAMED entry for each renamed key.

The following request sends two keys that normalize to email:

curl --request POST https://api.runtype.com/v1/records \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"type": "customer",
"name": "Dana Kim",
"metadata": { "Email": "dana@example.com", "email": "billing@example.com" }
}'

Replace YOUR_API_KEY with your Runtype API key.

The API returns 201. The response contains the following fields, together with the other Record fields:

{
"metadata": {
"email": "dana@example.com",
"email_1": "billing@example.com"
},
"warnings": [
{ "code": "KEY_RENAMED", "from": "email", "to": "email_1" }
]
}

To keep control of your key names, send keys that are already lowercase snake_case and unique.

Reserved keys (METADATA_RESERVED_KEY)

Runtype rejects a key that normalizes to an empty string or to constructor or prototype. For example, !!!, ---, and Constructor are rejected. The API returns 400 and stores nothing:

{
"error": "metadata_reserved_key",
"details": [
{
"code": "METADATA_RESERVED_KEY",
"message": "Metadata key \"!!!\" normalizes to a reserved or empty name and cannot be used.",
"path": "metadata.!!!"
}
]
}

To fix the error, rename or remove each key that details lists. In a CSV import, a column header that normalizes to a reserved or empty name fails every row.

Vector store support

The Vector Search and Store Vector Flow steps and the Semantic Search tool each support a different set of vector stores. The following table shows what works with each store:

FeaturePostgreSQL (pgvector)Cloudflare VectorizeWeaviate
Vector Search stepYesYesNo. The step fails when the Flow runs.
Store Vector stepYes. Adds an embedding to an existing Record.YesNo. The step fails when the Flow runs.
Semantic Search toolYesNo. The tool returns no results and an error.Yes
recordType filterReturns only Records of that typeMatches vectors whose type metadata equals the valueNot applicable
metadataFiltersIgnoredExact match on each key. Values must be strings, numbers, or Booleans.Not applicable
NamespacesNoYesNo
Embedding model matchRequired. Search returns only Records embedded with the same model.Use the same model for storing and searchingUse the same model for storing and searching
SetupNoneA Cloudflare Vectorize integrationA Weaviate integration

In the Semantic Search tool, PostgreSQL (pgvector) appears as Platform Records (pgvector). If you omit the vector store in a Vector Search step, the step searches PostgreSQL (pgvector).

For how to filter and read search results, see Filtering and searching records.

Next steps