UUID โ a 128-bit string you see everywhere, from REST APIs to database primary keys โ is not just one thing. It is a family of eight distinct versions, each with radically different trade-offs for privacy, sortability, and database performance. Choosing the wrong version can silently fragment every B-tree index in your production database. This guide explains them all.
1. Introduction
A Universally Unique Identifier (UUID) is a 128-bit standard for uniquely identifying information in computer systems. In the design of modern distributed systems, microservice architectures, and multi-instance databases, generating unambiguous identifiers without consulting a central registry is a fundamental performance and reliability requirement.
In the era of monolithic applications backed by a single relational database, sequential integer counters (AUTO_INCREMENT or SERIAL) served as primary keys. As systems scaled horizontally, this approach became obsolete. A centralized ID generator is a Single Point of Failure and introduces a network round-trip on every write. UUID was created to allow independent nodes to generate unique identifiers in a decentralized manner with zero or negligible probability of collision.
In engineering practice the term GUID (Globally Unique Identifier), used mainly in the Microsoft ecosystem, is also frequently encountered. Structurally, UUID and GUID are conceptually identical โ both represent 128-bit binary values. The difference comes down to history and implementation-level specifications. While the RFC defines data storage in network byte order (Big-Endian), Microsoft COM and older .NET implementations use Little-Endian internally for selected fields. This difference is significant when sorting and binary-indexing in relational database engines.
2. Standards and Specification Evolution
The standardization of unique identifiers evolved over four decades through several key milestones. Apollo NCS (late 1980s) introduced the Variant 0 concept. The Open Software Foundation (OSF) incorporated UUIDs into the Distributed Computing Environment (DCE) spec, formally splitting the 128-bit structure into time and hardware fields. RFC 4122 (2005) was the main industry standard for nearly two decades, defining versions v1โv5. RFC 9562 (May 2024) is the current IETF standard that obsoletes RFC 4122, officially standardizing UUIDv6, UUIDv7, and UUIDv8 in direct response to the B-tree performance problems caused by random UUIDs.
Every UUID contains two key control fields. The Variant field (bits 64โ65 for RFC 9562 Variant 1) defines the general interpretation of the remaining bits โ the most popular Variant 1 is marked by setting the first two bits of byte 8 to binary 10. The Version field is a 4-bit code at bits 48โ51 that identifies the specific algorithm used to generate the identifier (values 0x1 through 0x8).
Endianness matters: RFC 9562 mandates Big-Endian (Network Byte Order) for binary UUID storage and transmission โ the most significant byte is written first. Modifying this ordering at the library level destroys sortability and causes B-tree fragmentation. Always verify which byte order your language runtime uses before writing UUIDs to a database.
3. The 128-Bit Structure
The canonical text format consists of 32 hexadecimal digits arranged in five groups separated by hyphens in the layout 8-4-4-4-12, giving 36 ASCII characters total: xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx, where M is the 4-bit version and N contains 1โ3 variant bits. In the hexadecimal representation the N position always starts with one of: 8, 9, a, or b.
| Bit range | Bytes | RFC 4122 name | RFC 9562 name (v7) | Function |
|---|---|---|---|---|
| 0 โ 31 | 0 โ 3 | time_low | unix_ts_ms (part 1) | First 32 bits of timestamp or random data |
| 32 โ 47 | 4 โ 5 | time_mid | unix_ts_ms (part 2) | Next 16 bits of timestamp or random data |
| 48 โ 51 | 6 (high nibble) | version | version | UUID version code (e.g. 0111 for v7) |
| 52 โ 63 | 6 โ 7 | time_hi | rand_a | Further timestamp bits or randomness |
| 64 โ 65 | 8 (bits 0โ1) | variant | variant | Variant bits (always 10 for RFC 9562) |
| 66 โ 127 | 8 โ 15 | clock_seq / node | rand_b | Clock sequence, MAC address, or primary entropy |
4. History of UUID and the Birth of RFC 9562
| Year | Document / Standard | Versions introduced | Key characteristic |
|---|---|---|---|
| 1997 | OSF DCE Spec | v1, v2 | First official definition in the DCE environment description. |
| 2005 | RFC 4122 | v1, v2, v3, v4, v5 | IETF standardization. Introduction of randomness and MD5/SHA-1 hashing. |
| 2024 | RFC 9562 | v6, v7, v8 | Obsoletes RFC 4122. Dedicated support for B-tree structures and chronological sortability. |
RFC 4122 promoted UUIDv4 as the universal identifier. Although UUIDv4 provides excellent uniqueness through 122 bits of randomness, its completely disordered structure causes performance degradation when writing to relational databases. Inserts of completely random identifiers lead to B-tree fragmentation, frequent page split operations, and a drastic drop in cache locality. UUIDv1 had a timestamp component but arranged the time bits in the wrong order (least-significant bits first), making chronological sorting impossible, while also creating serious privacy risks by exposing the MAC address of the network interface.
5. All UUID Versions (v1 โ v8)
UUIDv1 โ Time-based + MAC Address
UUIDv1 is based on a 60-bit timestamp measured in 100-nanosecond intervals since 15 October 1582 (the Gregorian calendar reform), a 14-bit clock sequence, and a 48-bit MAC address. The critical design flaw: the most significant time bits land at positions 52โ63 while positions 0โ31 hold the least significant time_low bits. This layout makes chronological sorting of the text or binary string impossible.
| Bit field | Bit range | Width (bits) | Description |
|---|---|---|---|
| time_low | 0 โ 31 | 32 | Least significant 32 bits of Gregorian timestamp |
| time_mid | 32 โ 47 | 16 | Middle 16 bits of Gregorian timestamp |
| version | 48 โ 51 | 4 | Fixed value 0001 (version 1) |
| time_hi | 52 โ 63 | 12 | Most significant 12 bits of Gregorian timestamp |
| clock_seq | 66 โ 79 | 14 | Clock sequence protecting against system clock rollback |
| node | 80 โ 127 | 48 | Physical MAC address of the generating network interface |
UUIDv1 exposes the physical MAC address of the generating machine and the exact creation timestamp of every document or record. Use it only in legacy systems requiring backward compatibility with older software. RFC 9562 marks it as deprecated.
UUIDv2 โ DCE Security
UUIDv2 is reserved for the OSF DCE Security specification. It replaces the first 32 bits of the time_low field with a local security identifier (POSIX UID or GID), and part of the clock sequence field encodes the security domain. This version is rarely used in modern engineering practice. Its reduced space for the timestamp and clock sequence means uniqueness is only guaranteed within short time windows โ approximately 7 minutes per UID/GID per node.
UUIDv3 โ Name-based MD5
UUIDv3 is a deterministic identifier. It is produced by computing the MD5 hash of a combination of a namespace UUID (in binary form) and a resource name string. The appropriate Variant (10) and Version (0011) bits are set in the resulting 128-bit value. The same namespace + name input always produces the same UUID. Due to known MD5 collision vulnerabilities, RFC 9562 recommends UUIDv5 (SHA-1) over UUIDv3 in every deterministic scenario.
UUIDv4 โ Random
UUIDv4 is based entirely on random numbers. Of the 128 bits, 6 are reserved for the version (0100) and variant (10) bits, leaving exactly 122 bits of pure entropy. Generation must rely on a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). The probability of collision at 50% would require generating approximately 2.71 ร 10ยนโธ identifiers. Generating a billion IDs per second for a hundred years still yields a collision probability of roughly 10โปโน. UUIDv4 became the most popular version due to its simplicity โ it requires no knowledge of system time, clock state, or MAC address.
UUIDv5 โ Name-based SHA-1
UUIDv5 works analogously to UUIDv3 but uses the SHA-1 cryptographic algorithm instead of MD5. From the 160-bit SHA-1 output, the first 128 bits are taken, the version bits are overwritten with 0101, and the variant bits with 10. Because of MD5's vulnerability to collisions, RFC 9562 recommends choosing UUIDv5 in every scenario that requires identifiers deterministically generated from names.
UUIDv6 โ Reordered Time-based
UUIDv6 is a direct modification of UUIDv1 designed to provide lexical sortability in databases while maintaining structural compatibility with v1. The 60-bit Gregorian timestamp bits are rearranged so that the most significant bits come first: bits 0โ32 hold time_high (most significant), bits 33โ48 hold time_mid, bits 49โ52 hold the version (0110), and bits 53โ64 hold time_low (least significant). This bit reordering enables lexical and binary sorting and reduces B-tree fragmentation, but since it still uses Gregorian timestamps and MAC addresses it is considered a transitional version for systems migrating from UUIDv1.
UUIDv7 โ Unix Epoch Time-based (Recommended)
UUIDv7 is the solution recommended by RFC 9562 for all new systems and databases. It combines a 48-bit Unix Epoch timestamp (milliseconds since 1 January 1970) with 74 bits of random entropy.
| Section | Bit range | Width (bits) | Contents |
|---|---|---|---|
| unix_ts_ms | 0 โ 47 | 48 | Unix time in milliseconds (sufficient until year 10889 AD) |
| version | 48 โ 51 | 4 | Fixed value 0111 (version 7) |
| rand_a | 52 โ 63 | 12 | Random entropy or sub-millisecond monotonic counter |
| variant | 64 โ 65 | 2 | Fixed value 10 (Variant 1 per RFC) |
| rand_b | 66 โ 127 | 62 | Random entropy from CSPRNG |
UUIDv7 eliminates the fundamental drawbacks of its predecessors: unlike v1 it does not expose the MAC address, and unlike v4 it provides excellent database sortability by preserving chronological continuity. The 74 bits of randomness yield 2โทโด โ 1.89 ร 10ยฒยฒ combinations within the same millisecond โ making collisions astronomically unlikely even at very high generation rates.
UUIDv8 โ Custom
UUIDv8 provides a flexible format for custom solutions. It only mandates the 4 version bits (1000) and the 2 variant bits (10). The remaining 122 bits can be used freely by software architects. It is used in scenarios requiring domain-specific data embedded in the identifier โ such as a tenant ID, custom nanosecond timestamp precision, or geolocation coordinates. UUIDv8 has no universal semantics and requires a custom parser at the application layer.
6. Comparison of All UUID Versions
| Feature | v1 | v3 | v4 | v5 | v6 | v7 | v8 |
|---|---|---|---|---|---|---|---|
| Timestamp | Gregorian | None | None | None | Gregorian | Unix Epoch | Custom |
| Random bits | None | None (MD5) | 122 bits | None (SHA-1) | Partial | 74 bits | Custom |
| Hash | None | MD5 | None | SHA-1 | None | None | Custom |
| Deterministic | No | Yes | No | Yes | No | No | Custom |
| Sortability | Poor | None | None | None | Good | Excellent | Custom |
| Privacy | Poor (MAC exposed) | Good | Excellent | Good | Good | Excellent | Custom |
| RFC 9562 status | Deprecated | Rarely used | Still OK | OK | Discouraged | Recommended | Special purpose |
7. Database Performance Comparison
Using completely random UUIDv4 as a primary key causes performance problems in relational database engines. Most databases use B-tree indexing for primary keys. Data is stored on pages (typically 8 KB or 16 KB). When inserting random identifiers (UUIDv4), the database must insert new records into random positions in the tree. When the target page is full, the engine performs a page split โ creates a new page and moves 50% of data to it. With UUIDv4 this results in thousands of page split operations per million inserts, whereas for sequential IDs the number is negligible.
- Index Fragmentation: Frequent page splits leave B-tree pages only 60โ70% full, causing index bloat and doubling disk usage.
- Cache Locality: Inserting entirely random keys invalidates pages in the RAM buffer pool, forcing the database to constantly perform physical disk I/O.
- PostgreSQL 18: Introduces native uuidv7() function. Benchmarks show a 35โ50% reduction in index size and faster writes at scale compared to UUIDv4. PostgreSQL also provides uuid_extract_timestamp() and uuid_extract_version() helper functions.
- MySQL (InnoDB): Enforces a Clustered Index, meaning entire table rows are physically arranged on disk by primary key order. Using UUIDv4 in MySQL causes entire rows to be moved during page splits, producing high IOPS overhead.
- SQL Server: The uniqueidentifier type uses an atypical binary sort order (bytes 10โ15 first, then 8โ9, etc.). Generating standard UUIDv7 without proper byte reordering in .NET will cause the same fragmentation in SQL Server as UUIDv4.
- Oracle: Stores UUID in RAW(16). Without sortability, requires regular ALTER INDEX REBUILD maintenance operations.
| Metric / Engine | UUIDv4 | UUIDv7 | Performance impact |
|---|---|---|---|
| Page splits (PostgreSQL) | ~5,000โ10,000 per 1M inserts | ~10โ50 per 1M inserts | Over 95% I/O reduction |
| B-tree fill factor | ~60โ70% | ~95โ98% | Disk and RAM savings |
| MySQL InnoDB writes | Scattered writes across B-tree | Appends to rightmost leaf | Eliminates table-rewrite phenomenon |
| RAM buffer cache usage | Poor (buffer trashing) | Optimized (hot pages) | Significant drop in disk reads |
8. UUID and Databases: Migration
Choosing a primary key type involves architectural trade-offs between size, uniqueness, and performance. AUTO_INCREMENT (BIGINT) offers the smallest footprint (8 bytes) and excellent performance but reveals database size (enumeration attack) and prevents generating IDs outside the database. Classic UUIDv4 guarantees distribution but destroys B-tree indexes. UUIDv7 mitigates these drawbacks by combining sequential write performance with distributed generation without conflicts.
Migrating from UUIDv4 to UUIDv7 does not require changing the column type, since both versions are represented by the same 128-bit UUID or BINARY(16) type. The migration steps are: (1) swap ID generators in application code from v4 to v7; (2) the database gradually begins placing new rows on the right edge of the B-tree; (3) rebuild old indexes (e.g., REINDEX TABLE in PostgreSQL or OPTIMIZE TABLE in MySQL) to compact previously fragmented pages.
In .NET 9, Guid.CreateVersion7() preserves the internal Little-Endian Guid format. Without an explicit conversion using .ToByteArray(bigEndian: true) when writing to PostgreSQL, the timestamp bytes are stored in Little-Endian order, destroying chronological sortability in the B-tree index and causing index bloat of over 35% compared to the correct Big-Endian binary form.
SQL Server sorts the uniqueidentifier type starting from the last bytes (bytes 10โ15 first, then 8โ9, etc.), which is the opposite of standard UUID byte order. Storing UUIDv7 in a uniqueidentifier column without the appropriate byte permutation will cause B-tree fragmentation identical to UUIDv4.
9. UUID vs ULID vs KSUID vs Snowflake
| Feature | UUIDv4 | UUIDv7 | ULID | KSUID | Snowflake |
|---|---|---|---|---|---|
| Binary size | 16 bytes (128b) | 16 bytes (128b) | 16 bytes (128b) | 20 bytes (160b) | 8 bytes (64b) |
| Text length | 36 chars (Hex) | 36 chars (Hex) | 26 chars (Base32) | 27 chars (Base62) | 18โ20 digits |
| Sortability | None | Yes (chronological) | Yes (chronological) | Yes (chronological) | Yes (chronological) |
| IETF standard | RFC 9562 | RFC 9562 | No RFC | No RFC | No RFC |
| B-tree performance | Low | High | High | Medium | Very high |
| Coordination required | None | None | None | None | Required (Node ID) |
| Timestamp precision | None | 1 ms | 1 ms | 1 s | 1 ms |
Since the publication of RFC 9562, ULID is no longer a clear winner over UUID. ULID and UUIDv7 offer comparable technical parameters (48-bit millisecond timestamp plus entropy). The advantage of UUIDv7 is official IETF standardization and native support in databases and programming languages. Snowflake IDs offer the best B-tree performance and smallest binary size (8 bytes) but require coordinated node ID assignment, making them unsuitable for fully decentralized systems.
10. Historical UUID Problems
- MAC Address Exposure: Early software (e.g., Windows COM objects) used UUIDv1 for document identification, allowing digital files to be traced back to the physical computer of their creator.
- Insufficient Entropy and Predictable RNG: Using weak pseudo-random number generators (e.g., rand() in C or Math.random() in JavaScript) led to security vulnerabilities. In several systems, generated UUIDv4 values overlapped, enabling session hijacking.
- .NET 9 and Guid.CreateVersion7(): The new function preserves the internal Little-Endian Guid format. Without explicit bigEndian: true conversion when writing to PostgreSQL, index sizes grow over 35% compared to correct Big-Endian binary form.
- Atypical Sorting in MS SQL Server: Storing UUIDv7 in a uniqueidentifier column without proper byte permutation causes B-tree fragmentation because SQL Server sorts this type starting from the last bytes.
11. Common Misconceptions
- "UUID guarantees 100% uniqueness" โ Uniqueness for random versions is a probabilistic property. The mathematical collision risk exists, though with a proper CSPRNG it is astronomically small.
- "Every UUID is random" โ Only v4 consists almost entirely of random bits. Versions v1, v6, and v7 contain precise timestamps; v3 and v5 are deterministic cryptographic hashes.
- "UUID is faster than Integer" โ Comparing 128-bit fields in databases requires more CPU cycles than operating on 64-bit integers.
- "UUID cannot collide" โ Incorrect clock configuration, lack of access to a strong entropy source, or faulty monotonic counters can produce duplicates.
- "UUID always has 36 characters" โ The 36-character representation is only the text presentation form. At the disk layer, databases store UUID as pure 16 bytes.
12. Implementation in Programming Languages
The following libraries provide RFC 9562-compliant UUIDv7 generation. In Java, the uuid-creator library (by Fabio Lima) is the recommended choice, providing both Guid.getUuidV7() for standard generation and a non-cryptographic fast variant for extreme throughput scenarios. In .NET 9+, Guid.CreateVersion7() is built into the runtime โ always use .ToByteArray(bigEndian: true) when extracting bytes for PostgreSQL. In Python, the uuid6 module covers v6, v7, and v8; Python's standard library uuid module covers only v1, v3, v4, and v5. In Go, the google/uuid package provides uuid.NewV7(). In Rust, the uuid crate supports v7 with the "v7" feature flag. In Node.js/TypeScript, the uuid npm package (v11.0.0+) exports v7 as uuidv7.
Highest performance UUID library for the JVM. Supports all RFC 9562 versions including v7 and v7 non-cryptographic (fastest variant, ~39 ns per call, zero allocations).
Native UUID v7 support in the .NET runtime since .NET 9. Use Guid.CreateVersion7() and always call .ToByteArray(bigEndian: true) when writing bytes to PostgreSQL or other Big-Endian databases.
Lightweight Python module implementing UUID versions 6, 7, and 8 per RFC 9562. Drop-in companion to the standard library uuid module.
De facto standard UUID library in the Go ecosystem. Provides uuid.NewV7() for RFC 9562 UUIDv7 and uuid.NewRandom() for UUIDv4.
UUID library for Rust. Enable the "v7" feature flag in Cargo.toml to unlock Uuid::now_v7() for time-ordered generation.
Most popular UUID library for JavaScript/TypeScript environments. Full RFC 9562 support since v11.0.0. Import v7 as: import { v7 as uuidv7 } from "uuid".
13. Library Comparison
| Language | Library | RFC 9562 support | CSPRNG | Notes |
|---|---|---|---|---|
| Java | java.util.UUID (JDK) | No (v3, v4 only) | Yes | Basic JDK class. No native v7 support. |
| Java | uuid-creator | Full | Yes | Highest JVM performance (~39 ns for v7nc). |
| C# | System.Guid (.NET 9+) | Full (from .NET 9) | Yes | Native runtime support. Beware Little-Endian byte order for databases. |
| Python | uuid (stdlib) | Partial (v1, v3, v4, v5) | Yes | Work on v7 inclusion in Python 3.13+ is ongoing. |
| Python | uuid6 | Full | Yes | Lightweight module fulfilling RFC 9562 requirements. |
| Go | google/uuid | Full | Yes | Declarative standard in the Go ecosystem. |
| Node.js | uuid | Full (from v11.0.0) | Yes | Most popular library for JS/TS environments. |
14. Performance Benchmarks
| UUID version | Generation speed | Throughput | Memory per operation |
|---|---|---|---|
| UUIDv7 (fast / non-crypto) | ~39 ns | ~25.6M ops/sec | 0 B (reusable buffer) |
| UUIDv1 | ~100 ns | ~10.0M ops/sec | Small (clock sequence state) |
| UUIDv6 | ~100 ns | ~10.0M ops/sec | Small (clock sequence state) |
| UUIDv4 (CSPRNG) | ~140 ns | ~7.1M ops/sec | 0 B (native random allocation) |
| UUIDv5 (SHA-1) | ~260 ns | ~3.8M ops/sec | SHA-1 context buffer allocation |
The performance advantage of UUIDv7 stems from the fact that reading a 48-bit timestamp register is a CPU operation that does not require invoking the full CSPRNG entropy block for the entire bit string โ only the 74 random bits need a CSPRNG call. The non-cryptographic fast variant foregoes CSPRNG entirely for the random fields, using an atomic monotonic counter instead, which is safe only when the timestamp already provides uniqueness guarantees.
15. Decision Matrix
| Scenario | Best UUID | Architectural rationale |
|---|---|---|
| REST API / Microservices | UUIDv7 | Provides uniqueness and seamless chronological sortability. |
| PostgreSQL / MySQL Primary Key | UUIDv7 | Ideal index locality, eliminates page split phenomenon. |
| Apache Kafka / System events | UUIDv7 | Events can be sorted directly by key value. |
| Event Sourcing / Event Store | UUIDv7 | Guarantees event ordering and collision-free distributed aggregation. |
| Legacy system integrations (v1-based) | UUIDv6 | Provides sortability while maintaining backward-compatible v1 structure. |
| Deterministic resource identifier | UUIDv5 | Computes a stable ID from a Namespace + Name pair using SHA-1. |
| Privacy โ hiding creation time | UUIDv4 | Prevents reading the exact moment the ID was generated. |
| Domain-specific custom format | UUIDv8 | Allows embedding custom metadata in 122 bits. |
16. Best Engineering Practices
- Adopt UUIDv7 as the default in new projects โ the recommended choice for resource identifiers, primary keys, and event log entries.
- Always use a CSPRNG source โ ensure cryptographically secure entropy is available in the runtime environment.
- Never use UUID as an authorization mechanism โ UUID is for identification, not authentication. Knowing a UUID must not represent an access permission.
- Store UUID in native binary types โ use the native uuid type in PostgreSQL or BINARY(16) in MySQL. Avoid VARCHAR(36) text format.
- Avoid UUIDv1 and UUIDv2 in new systems โ their outdated design and potential MAC data leaks disqualify them.
- Use UUIDv5 for deterministic IDs โ when you need to compute a stable identifier from a name string, always prefer UUIDv5 (SHA-1) over UUIDv3 (MD5).
17. Frequently Asked Questions
Is UUID truly unique?
For software engineering purposes โ yes. Uniqueness of random versions (v4, v7) relies on mathematical probability. The probability of generating a duplicate when using a proper entropy source is so small that it is considered zero in practice.
Can UUID repeat?
It can only repeat in the case of a runtime environment failure: damaged random number generator, no CSPRNG access, system clock reset without monotonic counters, or a faulty multithreaded library implementation.
Will UUIDv7 replace UUIDv4?
UUIDv7 is progressively displacing UUIDv4 in all database and state-storage applications. UUIDv4 will remain in use in areas where the creation time of the identifier must deliberately be hidden.
Why does the canonical UUID form have 36 characters?
The 128-bit structure maps to 32 hexadecimal digits. Separating them with 4 hyphens in the standard 8-4-4-4-12 format gives a total length of 36 ASCII characters.
Is ULID better than UUID?
No, not since RFC 9562 was published. ULID and UUIDv7 offer comparable technical parameters. The advantage of UUIDv7 is official IETF standardization and native support in databases and programming language runtimes.
When should numeric IDs be used instead of UUID?
Numeric identifiers (e.g., BIGINT) remain the better choice in closed, single-instance databases with very high load, where index size is critical, data is not exposed externally through APIs, and there is no need to generate keys on independent distributed nodes.
References
- RFC 9562 โ Universally Unique IDentifiers (UUIDs) โ IETF (May 2024)
- RFC 4122 โ A Universally Unique IDentifier (UUID) URN Namespace โ IETF (2005)
- uuid-creator โ Java UUID Generator by Fabio Lima
- Guid.CreateVersion7() โ Microsoft .NET 9 API Reference
- uuid6-python โ Python module for RFC 9562 UUID versions 6, 7, 8
- google/uuid โ UUID library for Go
- uuid crate โ Rust UUID library documentation
- uuid npm โ UUID library for Node.js / TypeScript (v11+)
- UUIDv7 Comes to PostgreSQL 18 โ The Nile Blog
- A deeper look at UUIDv4 vs UUIDv7 in PostgreSQL 18 โ credativ
