Suppose your product already has the ID 550e8400-e29b-41d4-a716-446655440000 in the primary database. It shows up in events, logs, and API responses. But when you load that same product into Manticore, the application still has to assign it another, numeric ID.
Before Manticore Search 28.5.0, the document ID was an unsigned 64-bit number. A UUID could be stored in a separate string attribute, but that did not make it the document ID. UPDATE, REPLACE, and DELETE still required a numeric id.
As a result, you had to keep a mapping between the UUID from the primary database and the numeric ID in the Manticore table. Now you can do without it: an RT table in Manticore can use a UUID as the document ID.
Why a second ID is a problem
A mapping table between IDs is not exactly complicated, but only as long as the application is loading data and searching. The problems start when documents change.
A worker receives an event with a UUID, finds the matching numeric ID, and only then sends the update to Manticore. Deletion follows the same path. If the mapping record is missing or stale, the wrong document may be updated, or the changes may never reach Manticore at all.
Another option is to turn the UUID into a 64-bit hash. Then the application itself has to account for possible collisions. You can also introduce a separate sequence counter, but then it has to be coordinated across all processes that create documents.
There is another subtle point with numeric IDs, and it appears at the API level. Inside Manticore it is a uint64, while SQL shows it as a signed BIGINT. Because of that, SQL can return values greater than 2^63-1 as negative numbers, and the client has to convert them carefully. A UUID is passed and returned as a string, so there is no need to worry about signed range or overflow.
id uuid solves the problem at the root: the object identifier no longer needs conversion. The same UUID is used in the primary DB, the queue, Manticore, logs, and the external API.
What a UUID is
UUID is essentially a 128-bit identifier that does not require a central registry to create. In text form, it usually consists of 36 characters: 32 hexadecimal digits and four hyphens.
550e8400-e29b-41d4-a716-446655440000
A UUID contains a version and a variant. The version defines how the remaining bits are formed. UUIDv4 is based on random or pseudorandom data. UUIDv7 includes a time component and preserves the chronological order of identifiers. In UUIDv8, the placement of the remaining bits is defined by a specific implementation.
The lack of a central registry makes it possible to assign an ID before writing to a shared database. For example, two independent services can create objects in parallel, and a mobile client with no LTE signal can prepare data without a server connection. After synchronization, the object keeps the same identifier.
However, a UUID should not be treated as an absolute guarantee of uniqueness. In practice, that depends on the correctness of the chosen generator. Also keep in mind that a UUID is not a secret and does not replace a password, token, or permission check.
What changed in Manticore 28.5.0
For an RT table, you can now explicitly set the document ID type:
CREATE TABLE products_uuid (
id uuid,
title text,
sku string,
price int
);
INSERT INTO products_uuid (id, title, sku, price)
VALUES (
'550e8400-e29b-41d4-a716-446655440000',
'Mechanical keyboard',
'KB-001',
149
);
After insertion, the same UUID can be used in equality and IN filters, as well as in UPDATE, REPLACE, and DELETE. SQL returns the ID as a string. You can also pass an explicit UUID or ask Manticore to generate an ID through the JSON API; we will cover detailed requests and responses in the next article.
If you run INSERT again with a UUID that already exists, Manticore rejects it, just as it used to with a numeric ID. Use REPLACE to overwrite a document by ID.
Note that the uuid type applies only to the document ID. You cannot declare a regular user attribute with the uuid type.
Who creates the UUID
There are two options:
| How the document is written | Who creates the ID | What Manticore does |
|---|---|---|
The id field is provided | The primary DB, a client library, or another system component | Validates the format, version, and variant, then stores the UUID in lowercase |
The id field is missing | Manticore | Creates a UUIDv8 and encodes its internal numeric auto-ID into it |
If your application already creates the UUID, you do not need to adapt it to Manticore. The format is standard: five groups of 8-4-4-4-12. The version can be any from v1 to v8, and the variant position must contain 8, 9, a, or b. Case does not matter: you can send the UUID in uppercase, but Manticore will store it in lowercase.
That is where validation ends: Manticore checks the UUID format, but not the quality of the generator. The client library is responsible for the randomness of UUIDv4 and the correct time component in UUIDv7.
Server-side generation works differently. If the id field is not provided, Manticore creates a UUIDv8 with its own structure and encodes the built-in numeric auto-ID into it. This is not a random UUIDv4 and it is not a secret value.
A UUIDv8 created by the application will be validated and stored by Manticore as is; the server will not reshape it according to its own scheme.
Technical note. The full UUID remains the external identifier: Manticore does not replace it with a 64-bit hash and does not require the application to store a mapping table. How the UUID is laid out inside the engine is an implementation detail and does not affect the external contract.
Where it works
You can use a UUID as the document ID in regular RT tables, RT tables with engine='columnar', and tables in a replication cluster. With such IDs, exact match search, IN filters, and the usual document operations are available: INSERT, REPLACE, UPDATE, and DELETE.
Keep these limitations in mind:
- the
uuidtype is not suitable for regular attributes: Manticore will reject a declaration such asguid uuid; - in plain, percolate/PQ, and shard tables, UUIDs cannot be used as the document ID;
- an existing table cannot be switched from a numeric ID to a UUID, or back, with
ALTER TABLE; - range conditions
<,<=,>and>=, as well as arithmetic operations on IDs of this type, are not supported; - the document ID cannot be changed through
UPDATE- this applies to both UUIDs and numeric IDs; - for automatic generation, the
idfield must be omitted: the value0does not work here as a special marker.
This is easy to forget when porting legacy code. For a numeric RT table, 0 can mean “create the ID automatically.” In a UUID table, you simply need to leave out the id field.
UUIDv7 also does not make id suitable for time-based filters. You can use it as an external identifier, but Manticore does not yet support queries like id > ....
Summary
If the UUID already exists in the primary DB, you can now pass it to Manticore together with the document. If the document appears in Manticore first, do not specify id and take the generated UUID from the response.
From there, use the same UUID in UPDATE, REPLACE, and DELETE. There is no longer any need to give the document a separate numeric ID and keep a mapping between the two identifiers.
The full contract and current limitations are documented here: UUID document IDs . Support for UUID as a document ID appeared in Manticore Search 28.5.0 .
In the next article, a practical guide to using UUIDs as document IDs , we will step through how to set and generate IDs with SQL and JSON, search, update, replace, and delete documents, and handle errors.
