Generating UUIDs in Kotlin
On this page
Kotlin 2.0.20 (October 2024) introduced a new kotlin.uuid.Uuid type that works across all Kotlin Multiplatform targets — JVM, Android, JS, and Native. On the JVM you can also use java.util.UUID (which works identically via Kotlin’s interop).
kotlin.uuid (Kotlin 2.0.20+) — multiplatform
import kotlin.uuid.Uuid
import kotlin.uuid.ExperimentalUuidApi
@OptIn(ExperimentalUuidApi::class)
fun main() {
val id: Uuid = Uuid.random()
println(id.toString()) // "0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b"
println(id.toHexString()) // "0e6f1b8c2c334f1f9c0b2a3d4e5f6a7b"
val parsed = Uuid.parse("0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b")
val fromHex = Uuid.parseHex("0e6f1b8c2c334f1f9c0b2a3d4e5f6a7b")
}
The API is currently @ExperimentalUuidApi — stable but requires opt-in. Once it leaves experimental, the opt-in goes away.
java.util.UUID (JVM only)
import java.util.UUID
val id = UUID.randomUUID()
val parsed = UUID.fromString("0e6f1b8c-2c33-4f1f-9c0b-2a3d4e5f6a7b")
Same API as Java — see the Java UUID guide.
For new Kotlin code, prefer kotlin.uuid.Uuid (Kotlin 2.0.20+) — it’s multiplatform-ready, has more features, and avoids @OptIn proliferation as the API stabilizes.
v7 in Kotlin
Neither kotlin.uuid.Uuid nor java.util.UUID ships v7 yet (as of early 2026). For JVM projects, use uuid-creator from the Java guide:
import com.github.f4b6a3.uuid.UuidCreator
val v7 = UuidCreator.getTimeOrderedEpoch()
For Multiplatform, you’ll need a small platform-specific implementation or a library like kotlin-uuid-multiplatform. Or implement v7 inline:
@OptIn(ExperimentalUuidApi::class)
fun uuidV7(): Uuid {
val now = System.currentTimeMillis()
val rand = ByteArray(10)
java.security.SecureRandom().nextBytes(rand)
val bytes = ByteArray(16)
// 48-bit timestamp
for (i in 0..5) bytes[i] = ((now shr (40 - 8 * i)) and 0xff).toByte()
bytes[6] = ((rand[0].toInt() and 0x0f) or 0x70).toByte() // version 7
bytes[7] = rand[1]
bytes[8] = ((rand[2].toInt() and 0x3f) or 0x80.toInt()).toByte() // variant
for (i in 9..15) bytes[i] = rand[i - 6]
return Uuid.fromByteArray(bytes)
}
Production code should use a library. The snippet is for understanding.
Android
For Android (any version), java.util.UUID works:
import java.util.UUID
val deviceTag = UUID.randomUUID().toString()
For Room database with a UUID primary key:
@Entity
data class User(
@PrimaryKey val id: UUID,
val email: String
)
@TypeConverter
class UuidConverter {
fun fromUuid(uuid: UUID?): String? = uuid?.toString()
fun toUuid(s: String?): UUID? = s?.let(UUID::fromString)
}
@Database(entities = [User::class], version = 1)
@TypeConverters(UuidConverter::class)
abstract class AppDatabase : RoomDatabase()
For instances of v7 generation in Android (recommended for Room primary keys), use uuid-creator or generate in your app code.
Ktor (HTTP)
import io.ktor.server.routing.*
import io.ktor.server.response.*
routing {
get("/users/{id}") {
val id = UUID.fromString(call.parameters["id"]!!)
// ...
}
}
For automatic deserialization with kotlinx.serialization:
import kotlinx.serialization.Serializable
import kotlin.uuid.Uuid
import kotlin.uuid.ExperimentalUuidApi
@OptIn(ExperimentalUuidApi::class)
@Serializable
data class User(val id: Uuid, val email: String)
kotlin.uuid.Uuid has built-in kotlinx.serialization support — serializes as the canonical string by default.
Exposed ORM
import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.kotlin.datetime.timestamp
object Users : Table() {
val id = uuid("id").autoGenerate()
val email = varchar("email", 255).uniqueIndex()
val createdAt = timestamp("created_at")
override val primaryKey = PrimaryKey(id)
}
autoGenerate() produces v4 UUIDs at insert time. For v7, generate in your application code:
val newId = UuidCreator.getTimeOrderedEpoch()
Users.insert {
it[id] = newId
it[email] = "alice@example.com"
}
Comparing
val a: Uuid = Uuid.random()
val b = a
a == b // true (data class equality)
Both kotlin.uuid.Uuid and java.util.UUID are value types with structural equality.
Bytes
@OptIn(ExperimentalUuidApi::class)
val id = Uuid.random()
val bytes: ByteArray = id.toByteArray() // RFC 4122 order, 16 bytes
val back = Uuid.fromByteArray(bytes)
For java.util.UUID:
import java.nio.ByteBuffer
fun UUID.toBytes(): ByteArray {
val bb = ByteBuffer.wrap(ByteArray(16))
bb.putLong(mostSignificantBits)
bb.putLong(leastSignificantBits)
return bb.array()
}
Common pitfalls
- Don’t mix
kotlin.uuid.Uuidandjava.util.UUIDin one codebase. They’re not the same type, and conversion requires going through string or byte representation. @OptIn(ExperimentalUuidApi::class)propagates. Either annotate at the function level for narrow scope, or at the file level for convenience. Avoid module-level opt-in unless you’ve decided.- Room doesn’t auto-handle UUID columns — you must add a
@TypeConverter. Forgetting produces a runtime crash. - Android API levels:
java.util.UUIDworks on every version.kotlin.uuid.Uuidrequires the Kotlin 2.0.20+ stdlib, which Android Gradle Plugin handles transparently.
Cheat sheet
| Goal | Kotlin 2.0.20+ | Java interop |
|---|---|---|
| Random | Uuid.random() | UUID.randomUUID() |
| Parse | Uuid.parse(s) | UUID.fromString(s) |
| Time-ordered | UuidCreator.getTimeOrderedEpoch() | same |
| Bytes (RFC) | id.toByteArray() | ByteBuffer round-trip |
| Hex form | id.toHexString() | manual |
Try the tools
- UUID generator — instant in browser
- UUID v7 generator — for Room / Exposed primary keys
- Java UUID guide — JVM patterns that apply to Kotlin too
- UUID validator — paste, decode