> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# 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:

| Field                     | Limit                                       | Error code               |
| ------------------------- | ------------------------------------------- | ------------------------ |
| `type`                    | 255 characters                              | Request validation error |
| `name`                    | 500 characters                              | Request validation error |
| `metadata` size           | 256 KB (262,144 bytes) as UTF-8 JSON        | `METADATA_TOO_LARGE`     |
| `metadata` top-level keys | 200 keys                                    | `METADATA_TOO_MANY_KEYS` |
| `metadata` key length     | 64 characters, measured after normalization | `METADATA_KEY_TOO_LONG`  |
| `metadata` nesting depth  | 5 levels. The top-level object is level 1.  | `METADATA_TOO_DEEP`      |
| `messages` count          | 10,000 messages                             | `MESSAGES_TOO_LARGE`     |
| One message's `content`   | 1 MB (1,048,576 bytes) as UTF-8 JSON        | `MESSAGES_TOO_LARGE`     |
| All `messages` content    | 32 MB (33,554,432 bytes) in total           | `MESSAGES_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:

```json
{
  "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 send | Stored key   |
| ----------------- | ------------ |
| `First Name`      | `first_name` |
| `orderID`         | `orderid`    |
| `Price (USD)`     | `price_usd`  |
| `e-mail`          | `e_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`:

```bash
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:

```json
{
  "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:

```json
{
  "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:

| Feature                  | PostgreSQL (pgvector)                                               | Cloudflare Vectorize                                                   | Weaviate                                     |
| ------------------------ | ------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------------------------------------- |
| **Vector Search** step   | Yes                                                                 | Yes                                                                    | No. The step fails when the Flow runs.       |
| **Store Vector** step    | Yes. Adds an embedding to an existing Record.                       | Yes                                                                    | No. The step fails when the Flow runs.       |
| **Semantic Search** tool | Yes                                                                 | No. The tool returns no results and an error.                          | Yes                                          |
| `recordType` filter      | Returns only Records of that type                                   | Matches vectors whose `type` metadata equals the value                 | Not applicable                               |
| `metadataFilters`        | Ignored                                                             | Exact match on each key. Values must be strings, numbers, or Booleans. | Not applicable                               |
| Namespaces               | No                                                                  | Yes                                                                    | No                                           |
| Embedding model match    | Required. Search returns only Records embedded with the same model. | Use the same model for storing and searching                           | Use the same model for storing and searching |
| Setup                    | None                                                                | A Cloudflare Vectorize integration                                     | A 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](/user-guide/records/filtering-and-searching-records).

## Next steps

* [Defining a schema for a record type](/user-guide/records/defining-a-schema): validate metadata fields and types when you write a Record
* [Creating and managing records](/user-guide/records/creating-and-managing-records): create and edit Records in the dashboard
* [Building retrieval that works](/user-guide/records/building-retrieval-that-works): index and search Records for retrieval-augmented generation
* [Weaviate (vector search)](/user-guide/integrations/weaviate-vector-search): connect Weaviate for the **Semantic Search** tool