The uuid crate: generating and parsing UUIDs in Rust
Generate and parse UUIDs.
At a glance
- What is it?
- uuid is a Rust library for 128-bit unique identifiers that pulls in hashing or randomness only for the version you actually use, ships a no_std path for embedded targets, and parses without any feature at all.
- Who is it for?
- The uuid crate fits Rust services that need identifiers without a central authority, and it fits embedded work because the no_std category and the rng and js features are declared rather than assumed. It does not fit code that needs a guaranteed collision-free identifier, since the README states the uniqueness property is not strictly guaranteed.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the uuid crate gives a Rust project
A UUID is a 128-bit value stored as 16 octets and regularly written as a hex string in five hyphen separated groups, such as 67e55044-10b1-426f-9247-bb680e5fe0c8. The point of the format is that you can mint an identifier without a central allocating authority, which is why the crate's README points at distributed systems, and also at databases and network protocols where the same need appears in less exotic form.
The Rust crate at uuid-rs/uuid is the implementation most Rust projects reach for, and its structure follows from one design decision: everything version specific is a Cargo feature. Generating a random v4 identifier costs a dependency on a random number source. Generating a v5 name based identifier costs a SHA-1 implementation. Parsing an identifier costs nothing at all.
The repository layout backs this up. There is a src/ directory, a separate rng/ directory, a benches/ directory for benchmarks, a fuzz/ directory, and an examples/ directory. The Cargo.toml categories list includes no-std, wasm and parser-implementations, so the crate is built to be used in embedded targets, in browsers, and as the parsing layer of something larger.
Adding uuid to Cargo.toml and choosing a version
The dependency goes into Cargo.toml, and the version you ask for is the version of the crate itself:
[dependencies.uuid]
version = "1.28.0"
# Lets you generate random UUIDs
features = [
"v4",
]That feature list is the whole decision. The default feature set is std, and the version features are opt in, so a project that only parses identifiers can depend on uuid with no features at all and pull in neither a hashing library nor a random number source.
The mapping from version to dependency is declared in the manifest:
v1 = ["atomic"]
v3 = ["md5"]
v4 = ["rng"]
v5 = ["sha1"]
v6 = ["atomic"]
v7 = ["rng"]
v8 = []Read that as a cost table. v3 and v5 need a hash implementation, v1 and v6 need the atomic support, v4 and v7 need randomness, and v8 needs neither. Enabling v4 when you only wanted to parse strings is the most common way to make this crate heavier than the job requires.
Two optional integration features are worth knowing about, since they are the ones a reviewer will ask about: serde and borsh for serialisation, and slog for logging, alongside arbitrary for property based testing.
Generating a random identifier and a compile-time constant
With the v4 feature enabled, minting an identifier is a single call:
use uuid::Uuid;
let id = Uuid::new_v4();For values that are known ahead of time, such as an identifier that appears in a fixture or a test vector, the crate offers a macro that can be used in a const context:
use uuid::{uuid, Uuid};
const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");The macro is a compile-time parse, so a malformed literal becomes a build error instead of a runtime one. The manifest still carries a deprecated feature, macro-diagnostics, and the comment in the manifest is explicit that it is now a no-op, which tells you the diagnostic behaviour moved into the compiler and the feature was kept only so existing Cargo.toml files keep building.
The crate also exposes a uuid_unstable cfg through its docs.rs metadata, and the rustc and rustdoc arguments in the manifest switch that on for the published documentation. That is a documentation arrangement, not a runtime switch, and it is worth knowing if you read the docs and find behaviour described that your own build does not have.
Parsing and checking the version of an identifier
Parsing needs no feature flags at all, which the README states directly. The parse function returns a Result, and the version of the parsed value can be inspected afterwards:
use uuid::{Uuid, Version};
let my_uuid = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8")?;
assert_eq!(Some(Version::Random), my_uuid.get_version());The Version enum is what lets a service accept any UUID while still knowing whether the value it received is a random one, a time ordered one or a name based one. That distinction matters when a database column is typed by version, and get_version returning an Option reflects that an identifier can be parsed without its variant being known.
If parsing throughput is the bottleneck, the README points at a separate library, uuid-simd, as the fast path. The difference in approach is that uuid-simd is a separate crate, whereas the uuid crate keeps a single portable implementation that works in no_std builds and in the browser. Choosing between them is a question of whether parsing speed is a bottleneck, not of which library is more capable.
no_std, wasm and where randomness comes from
The manifest declares the standard library as a default feature, and the std feature forwards to the optional wasm-bindgen and js-sys dependencies, which is how the same crate works in a browser without a separate implementation. The web target is opted in through its own feature:
js = ["dep:wasm-bindgen", "dep:js-sys"]
rng = ["dep:getrandom"]Randomness is therefore a dependency decision, not a hidden one. The rng feature pulls in getrandom, and the rng-getrandom feature adds a uuid specific internal library on top of it. Since the rng directory is a separate top level entry in the repository, the random number plumbing is a piece of the project that can be read and audited on its own, which is the right shape for the component that decides the uniqueness of every v4 identifier you mint.
The crate also lists no-std as a Cargo category and supports it, which is what makes it usable on microcontrollers. The cost of that support is that the rng feature has to reach a source of entropy that works on the target, and a platform without one is a case the crate cannot paper over.
Releases, licence and the cost of staying current
The project moves quickly. Version 1.28.0 was published on 2026-10-10, version 1.27.0 on 2026-10-02 and version 1.26.1 on 2026-09-10, and the last push to the repository was on 2026-10-10. Three releases inside a month is a signal that the API surface is still moving, and that is the main upgrade cost to plan for: a feature you rely on could be renamed or reshaped in a minor release.
The manifest sets rust-version to 1.89.0 and edition 2021, so a project on an older toolchain cannot take the newest version. A conservative approach is to pin the version you validated and to read the release notes when you move, rather than floating on the newest minor.
Licensing is the friendly kind. The manifest records license = "Apache-2.0 OR MIT", and the README offers both licences at your option, with the Apache-2.0 and MIT files in the repository root. For a crate whose output is identifiers that end up in other people's databases, dual licensing removes the usual question about which obligations travel with the generated values. The README also states that contributions are dual licensed under the same terms unless a contributor states otherwise.
The licence detail in the repository metadata is less clear than the README, which lists the project as holding a custom licence that GitHub cannot classify, and that is worth checking directly in the LICENSE files before you rely on it in a compliance review.
When a UUID is the wrong identifier
The README is unusually blunt about the property everyone else glosses over. The uniqueness property is not strictly guaranteed, and for practical purposes an unintentional collision is extremely unlikely. That is a probability argument, not a guarantee, and a database that treats a UUID as a primary key is still relying on it.
That is the first wrong-tool case. A system that needs a guaranteed unique key, such as a financial ledger where a duplicate identifier is a correctness problem rather than an inconvenience, wants an allocator that can check for collisions, not a 128-bit random value.
The second case is sequential access. Random identifiers scatter inserts across an index, and a system whose write pattern is append only is often better served by a counter that the database assigns. The crate does offer time ordered versions, v1 and v6, which place a timestamp in the high bits and keep some locality, and the version features for them are declared separately, so a team that wants that property has to ask for it explicitly rather than assume it.
The third case is volume. Every identifier is 16 bytes of storage and a 36 character string on the wire, and a service that generates them by the billion pays for that in index size and in transfer cost. The crate is the right answer when identifiers must be unique across systems that do not talk to each other, and the wrong answer when one system is the only one minting them.
Editorial conclusion
The uuid crate fits Rust services that need identifiers without a central authority, and it fits embedded work because the no_std category and the rng and js features are declared rather than assumed. It does not fit code that needs a guaranteed collision-free identifier, since the README states the uniqueness property is not strictly guaranteed. Check first that the version feature you enable matches the identifier you need to emit.
Frequently asked questions
How do I add the uuid crate to a Rust project?
Add [dependencies.uuid] with version = "1.28.0" to Cargo.toml and list the version features you need in a features array, for example ["v4"] for random identifiers. Parsing works with no features at all.
How do I generate a random UUID in Rust?
Enable the v4 feature and call Uuid::new_v4(). The v4 feature pulls in the rng feature, which depends on getrandom, so the crate also needs a source of randomness available on your target.
What is the difference between the uuid crate and uuid-simd?
uuid-simd is a separate library for parsing UUIDs really fast, which the README recommends when parsing speed matters. The uuid crate keeps one portable implementation that also works in no_std builds and in the browser.
Which UUID versions does the uuid crate support?
The manifest declares features for v1, v3, v4, v5, v6, v7 and v8. v3 requires md5, v5 requires sha1, v1 and v6 require atomic support, v4 and v7 require rng, and v8 requires no extra dependency.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/uuid-rs-uuid)Was this useful?