Osmium Chat Protocol uses Snowflake IDs for all primary identifiers. Snowflake IDs are 64-bit integers that encode both a timestamp and unique sequence, making them:
Sortable by creation time - Higher IDs are always newer
Globally unique - No collisions across distributed systems
Compact - Only 8 bytes, efficient for storage and transmission
Decentralized - Can be generated without coordination
fixed64 is always 8 bytes on the wire, unlike uint64 which uses variable-length encoding. This is perfect for Snowflake IDs since they’re almost always large numbers that would take 8-10 bytes with variable encoding anyway.
// ⚠️ WRONG: JavaScript numbers lose precision above 2^53const userId: number = 1234567890123456789; // Will be rounded!// ✅ CORRECT: Use BigInt for Snowflake IDsconst userId: bigint = 1234567890123456789n;// Converting from various formatsconst fromString = BigInt('1234567890123456789');const fromHex = BigInt('0x112210F47DE98115');// Comparing Snowflakes (newer messages have higher IDs)if (message1.message_id > message2.message_id) { console.log('message1 is newer');}// Sorting by creation timemessages.sort((a, b) => { if (a.message_id < b.message_id) return -1; if (a.message_id > b.message_id) return 1; return 0;});
Never use JavaScript number type for Snowflake IDs. JavaScript numbers are IEEE 754 double-precision floats and can only safely represent integers up to 2^53 - 1. Snowflake IDs are 64-bit integers and will lose precision. Always use BigInt.
# Python integers have arbitrary precision - no special handling needed!user_id: int = 1234567890123456789# Comparing and sorting works as expectedif message1.message_id > message2.message_id: print('message1 is newer')messages.sort(key=lambda m: m.message_id)# Converting to/from stringsuser_id_str = str(user_id)user_id = int(user_id_str)
// Use u64 for Snowflake IDslet user_id: u64 = 1234567890123456789;// Comparison and sorting work naturallyif message1.message_id > message2.message_id { println!("message1 is newer");}messages.sort_by_key(|m| m.message_id);// Parsing from stringslet user_id: u64 = "1234567890123456789".parse()?;
function getSnowflakeTimestamp(snowflake: bigint): Date { // Custom epoch (adjust based on actual implementation) const EPOCH = 1640995200000n; // Example: Jan 1, 2022 // Extract timestamp (upper 42 bits) const timestamp = snowflake >> 22n; // Add epoch to get Unix timestamp const unixMs = timestamp + EPOCH; return new Date(Number(unixMs));}const messageId = 1234567890123456789n;const createdAt = getSnowflakeTimestamp(messageId);console.log('Message created at:', createdAt);
While you can extract timestamps from Snowflake IDs, don’t rely on this for business logic. The server may return explicit timestamps in message objects. Treat Snowflake IDs primarily as unique identifiers.
// Store the last seen message IDlet lastSeenMessageId = getLastSeenMessageId();// Fetch all new messages since thenconst newMessages = messages.filter(m => m.message_id > lastSeenMessageId);// Update last seenif (newMessages.length > 0) { lastSeenMessageId = newMessages[newMessages.length - 1].message_id; saveLastSeenMessageId(lastSeenMessageId);}
// Use Snowflake IDs as Map keys for efficient deduplicationconst messageMap = new Map<bigint, Message>();for (const message of incomingMessages) { messageMap.set(message.message_id, message);}// Convert back to array, guaranteed uniqueconst uniqueMessages = Array.from(messageMap.values());