Trove

TypeIDs

K-sortable, collision-resistant identifiers with entity-type prefixes for objects, buckets, uploads, and streams.

Every entity in Trove is identified by a TypeID -- a globally unique, K-sortable, URL-safe identifier that encodes both the entity type and a UUIDv7-based suffix.

Format

prefix_suffix
  • prefix -- Identifies the entity type (e.g., obj for objects, bkt for buckets)
  • suffix -- A UUIDv7-based, base32-encoded identifier

Example: obj_01h455vb4pex5vsknk084sn02q

Prefix Constants

Each Trove entity type has a dedicated prefix:

PrefixConstantEntity
objPrefixObjectObjects
bktPrefixBucketBuckets
uplPrefixUploadSessionUpload sessions
dwnPrefixDownloadSessionDownload sessions
strPrefixStreamStreams
polPrefixPoolPools
verPrefixVersionVersions
chkPrefixChunkChunks

Generating IDs

Use the convenience constructors to generate new IDs for each entity type:

import "github.com/xraph/trove/id"

objID  := id.NewObjectID()          // obj_01h455vb4pex5vsknk084sn02q
bktID  := id.NewBucketID()          // bkt_01h455vb4pex5vsknk084sn02q
uplID  := id.NewUploadSessionID()   // upl_01h455vb4pex5vsknk084sn02q
strID  := id.NewStreamID()          // str_01h455vb4pex5vsknk084sn02q
verID  := id.NewVersionID()         // ver_01h455vb4pex5vsknk084sn02q
chkID  := id.NewChunkID()           // chk_01h455vb4pex5vsknk084sn02q

Or use the generic constructor with any prefix:

myID := id.New(id.PrefixObject) // obj_...

Parsing IDs

Parse a TypeID string into a structured ID value:

// Parse any TypeID
parsed, err := id.Parse("obj_01h455vb4pex5vsknk084sn02q")

// Parse with prefix validation
parsed, err := id.ParseWithPrefix("obj_01h455...", id.PrefixObject)    // ok
parsed, err := id.ParseWithPrefix("bkt_01h455...", id.PrefixObject)    // error: prefix mismatch

// Type-specific parsers
objID, err := id.ParseObjectID("obj_01h455...")
bktID, err := id.ParseBucketID("bkt_01h455...")
uplID, err := id.ParseUploadSessionID("upl_01h455...")

For hardcoded IDs in tests or configuration, use the must-parse variants that panic on error:

known := id.MustParse("obj_01h455vb4pex5vsknk084sn02q")
known := id.MustParseWithPrefix("obj_01h455...", id.PrefixObject)

ID Methods

The ID type provides these methods:

MethodReturnDescription
String()stringFull TypeID string (prefix_suffix)
Prefix()PrefixThe prefix component
IsNil()boolWhether this is the zero-value ID
MarshalText()([]byte, error)Text serialization
UnmarshalText(data)errorText deserialization
Value()(driver.Value, error)SQL value for database storage
Scan(src)errorSQL scan for database retrieval

The zero value id.Nil represents an unset ID. IsNil() returns true and String() returns an empty string for nil IDs.

Database Compatibility

TypeIDs work transparently with SQL databases and MongoDB via standard Go interfaces.

SQL (PostgreSQL, MySQL, SQLite)

The ID type implements database/sql/driver.Valuer and database/sql.Scanner:

// Insert -- Value() returns the string representation
_, err := db.Exec("INSERT INTO objects (id, key) VALUES ($1, $2)", objID, "file.txt")

// Query -- Scan() reads the string back into an ID
var result id.ID
err := db.QueryRow("SELECT id FROM objects WHERE key = $1", "file.txt").Scan(&result)

Nil IDs store as SQL NULL, making them suitable for optional foreign key columns.

MongoDB (BSON)

The ID type implements MarshalBSONValue and UnmarshalBSONValue for the mongo-driver v2:

type Document struct {
    ID    id.ID  `bson:"_id"`
    Title string `bson:"title"`
}

IDs are stored as BSON strings, enabling text-based queries and human-readable document inspection.

Why TypeIDs

K-Sortable

TypeIDs are based on UUIDv7, which embeds a millisecond-precision timestamp. IDs sort chronologically by creation time, making database indexes efficient (no random scatter) and eliminating the need for separate created_at indexes when ordering by ID.

Collision-Resistant

UUIDv7 provides 48 bits of timestamp and 74 bits of randomness, yielding a negligible collision probability even at millions of IDs per second.

Self-Describing

The prefix makes IDs self-documenting. When you see obj_01h455vb4pex5vsknk084sn02q in a log or database, you immediately know it refers to an object -- not a bucket, stream, or upload session.

On this page