This repository was archived by the owner on Jul 9, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathdraft-peabody-dispatch-new-uuid-format-04.xml
1208 lines (1147 loc) · 66.8 KB
/
draft-peabody-dispatch-new-uuid-format-04.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="US-ASCII"?>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> <!-- used by XSLT processors -->
<!-- OPTIONS, known as processing instructions (PIs) go here. -->
<!-- For a complete list and description of PIs,
please see http://xml.resource.org/authoring/README.html. -->
<!-- Below are generally applicable PIs that most I-Ds might want to use. -->
<?rfc strict="yes" ?> <!-- give errors regarding ID-nits and DTD validation -->
<!-- control the table of contents (ToC): -->
<?rfc toc="yes"?> <!-- generate a ToC -->
<?rfc tocdepth="3"?> <!-- the number of levels of subsections in ToC. default: 3 -->
<!-- control references: -->
<?rfc symrefs="yes"?> <!-- use symbolic references tags, i.e, [RFC2119] instead of [1] -->
<?rfc sortrefs="yes" ?> <!-- sort the reference entries alphabetically -->
<!-- control vertical white space:
(using these PIs as follows is recommended by the RFC Editor) -->
<!-- end of popular PIs -->
<rfc version="3" category="std" updates="4122" submissionType="IETF" consensus="true" ipr="trust200902" docName="draft-peabody-dispatch-new-uuid-format-04">
<front>
<title abbrev="new-uuid-format">New UUID Formats</title>
<seriesInfo name="Internet-Draft" value="draft-peabody-dispatch-new-uuid-format-04" stream="IETF"/>
<author fullname="Brad G. Peabody" initials="BGP" surname="Peabody">
<address>
<email>[email protected]</email>
</address>
</author>
<author fullname="Kyzer R. Davis" initials="K" surname="Davis">
<address>
<email>[email protected]</email>
</address>
</author>
<date year="2022" />
<area>ART</area>
<workgroup>dispatch</workgroup>
<keyword>uuid</keyword>
<abstract>
<t>
This document presents new Universally Unique Identifier (UUID) formats for use in modern applications and databases.
</t>
</abstract>
</front>
<middle>
<section anchor="Background" title="Introduction">
<t>
Many things have changed in the time since UUIDs were originally created.
Modern applications have a need to create and utilize UUIDs as the primary
identifier for a variety of different items in complex computational systems,
including but not limited to database keys, file names, machine or system names, and identifiers for event-driven transactions.
</t>
<t>
One area UUIDs have gained popularity is as database keys.
This stems from the increasingly distributed nature of modern applications.
In such cases, "auto increment" schemes often used by databases do not work well, as the effort required to coordinate unique numeric identifiers across a network can easily become a burden.
The fact that UUIDs can be used to create unique, reasonably short values in distributed systems without requiring synchronization makes them a good alternative, but UUID versions 1-5 lack certain other desirable characteristics:
</t>
<ol>
<li><t>Non-time-ordered UUID versions such as UUIDv4 have poor database index locality.
Meaning new values created in succession are not close to each other in the index and thus require
inserts to be performed at random locations. The negative performance effects of which on
common structures used for this (B-tree and its variants) can be dramatic.
</t></li>
<li><t>
The 100-nanosecond, Gregorian epoch used in UUIDv1 timestamps is uncommon and difficult to represent accurately using a standard number format such as <xref target="IEEE754"/>.
</t></li>
<li><t>
Introspection/parsing is required to order by time sequence; as opposed to being able to perform a simple byte-by-byte comparison.
</t></li>
<li><t>
Privacy and network security issues arise from using a MAC address in the node field of Version 1 UUIDs.
Exposed MAC addresses can be used as an attack surface to locate machines and reveal various other
information about such machines (minimally manufacturer, potentially other details). Additionally, with the advent of virtual machines and containers, MAC address uniqueness is no longer guaranteed.
</t></li>
<li><t>
Many of the implementation details specified in <xref target="RFC4122"/> involve trade offs that are neither possible to specify for all applications nor necessary to produce interoperable implementations.
</t></li>
<li><t>
<xref target="RFC4122"/> does not distinguish between the requirements for generation of a UUID versus an application which simply stores one, which are often different.
</t></li>
</ol>
<t>
Due to the aforementioned issue, many widely distributed database applications
and large application vendors have sought to solve the problem of creating a better
time-based, sortable unique identifier for use as a database key. This has lead to numerous implementations
over the past 10+ years solving the same problem in slightly different ways.
</t>
<t>
While preparing this specification the following 16 different implementations were analyzed for trends in total ID length, bit Layout, lexical formatting/encoding, timestamp type, timestamp format, timestamp accuracy, node format/components, collision handling and multi-timestamp tick generation sequencing.
</t>
<ol spacing="compact">
<li><t><xref target="ULID"/> by A. Feerasta</t></li>
<li><t><xref target="LexicalUUID"/> by Twitter</t></li>
<li><t><xref target="Snowflake"/> by Twitter</t></li>
<li><t><xref target="Flake"/> by Boundary</t></li>
<li><t><xref target="ShardingID"/> by Instagram</t></li>
<li><t><xref target="KSUID"/> by Segment</t></li>
<li><t><xref target="Elasticflake"/> by P. Pearcy</t></li>
<li><t><xref target="FlakeID"/> by T. Pawlak</t></li>
<li><t><xref target="Sonyflake"/> by Sony</t></li>
<li><t><xref target="orderedUuid"/> by IT. Cabrera</t></li>
<li><t><xref target="COMBGUID"/> by R. Tallent</t></li>
<li><t><xref target="SID"/> by A. Chilton</t></li>
<li><t><xref target="pushID"/> by Google</t></li>
<li><t><xref target="XID"/> by O. Poitrey</t></li>
<li><t><xref target="ObjectID"/> by MongoDB</t></li>
<li><t><xref target="CUID"/> by E. Elliott</t></li>
</ol>
<t>
An inspection of these implementations and the issues described above has led to this document which attempts to adapt UUIDs to address these issues.
</t>
</section>
<section title="Terminology">
<section anchor="requirements_language" title="Requirements Language">
<t>
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.
</t>
</section>
<section anchor="acronyms" title="Abbreviations">
<t>The following abbreviations are used in this document: </t>
<dl newline="false" spacing="normal" indent="14" pn="section-2.2-2">
<dt>UUID</dt><dd>Universally Unique Identifier <xref target="RFC4122"/></dd>
<dt>CSPRNG</dt><dd>Cryptographically Secure Pseudo-Random Number Generator</dd>
<dt>MAC</dt><dd>Media Access Control</dd>
<dt>MSB</dt><dd>Most Significant Bit</dd>
<dt>DBMS</dt><dd>Database Management System</dd>
</dl>
</section>
</section>
<section anchor="Changes" title="Summary of Changes">
<t>
The following UUIDs are hereby introduced:
</t>
<dl newline="true">
<dt>UUID version 6 (UUIDv6)</dt>
<dd>A re-ordering of UUID version 1 so it is sortable as an opaque sequence of bytes. Easy to implement given an existing UUIDv1 implementation. See <xref target="uuidv6"/></dd>
<dt>UUID version 7 (UUIDv7)</dt>
<dd>An entirely new time-based UUID bit layout sourced from the widely implemented and well known Unix Epoch timestamp source. See <xref target="v7"/></dd>
<dt>UUID version 8 (UUIDv8)</dt>
<dd>A free-form UUID format which has no explicit requirements except maintaining backward compatibility. See <xref target="v8"/></dd>
<dt>Max UUID</dt>
<dd>A specialized UUID which is the inverse of <xref target="RFC4122" sectionFormat="comma" section="4.1.7"/> See <xref target="maxuuid"/></dd>
</dl>
<section anchor="changelog" title="changelog">
<t>RFC EDITOR PLEASE DELETE THIS SECTION.</t>
<t>draft-04</t>
<ul spacing="compact" empty="true">
<li><t>- Fixed bad title in IEEE754 Normative Reference</t></li>
<li><t>- Fixed bad GMT offset in Test Vector Appendix</t></li>
<li><t>- Removed MAY in Counters section</t></li>
<li><t>- Condensed Counter Type into Counter Methods to reduce text</t></li>
<li><t>- Removed option for random increment along with fixed-length counter</t></li>
<li><t>- Described how to handle scenario where New UUID less than Old UUID</t></li>
<li><t>- Allow timestamp increment if counter overflows</t></li>
<li><t>- Replaced UUIDv8 C code snippet with full generation example</t></li>
<li><t>- Fixed RFC4086 Reference link</t></li>
<li><t>- Describe reseeding best practice for CSPRNG</t></li>
<li><t>- Changed MUST to SHOULD removing requirement for absolute monotonicity</t></li>
</ul>
<t>draft-03</t>
<ul spacing="compact" empty="true">
<li><t>- Reworked the draft body to make the content more concise</t></li>
<li><t>- UUIDv6 section reworked to just the reorder of the timestamp</t></li>
<li><t>- UUIDv7 changed to simplify timestamp mechanism to just millisecond Unix timestamp</t></li>
<li><t>- UUIDv8 relaxed to be custom in all elements except version and variant</t></li>
<li><t>- Introduced Max UUID.</t></li>
<li><t>- Added C code samples in Appendix.</t></li>
<li><t>- Added test vectors in Appendix.</t></li>
<li><t>- Version and Variant section combined into one section.</t></li>
<li><t>- Changed from pseudo-random number generators to cryptographically secure pseudo-random number generator (CSPRNG).</t></li>
<li><t>- Combined redundant topics from all UUIDs into sections such as Timestamp granularity, Monotonicity and Counters, Collision Resistance, Sorting, and Unguessability, etc.</t></li>
<li><t>- Split Encoding and Storage into Opacity and DBMS and Database Considerations</t></li>
<li><t>- Reworked Global Uniqueness under new section Global and Local Uniqueness</t></li>
<li><t>- Node verbiage only used in UUIDv6 all others reference random/rand instead</t></li>
<li><t>- Clock sequence verbiage changed simply to counter in any section other than UUIDv6</t></li>
<li><t>- Added Abbreviations section</t></li>
<li><t>- Updated IETF Draft XML Layout</t></li>
<li><t>- Added information about little-endian UUIDs</t></li>
</ul>
<t>draft-02</t>
<ul spacing="compact" empty="true">
<li><t>- Added Changelog</t></li>
<li><t>- Fixed misc. grammatical errors</t></li>
<li><t>- Fixed section numbering issue</t></li>
<li><t>- Fixed some UUIDvX reference issues</t></li>
<li><t>- Changed all instances of "motonic" to "monotonic"</t></li>
<li><t>- Changed all instances of "#-bit" to "# bit"</t></li>
<li><t>- Changed "proceeding" verbiage to "after" in section 7</t></li>
<li><t>- Added details on how to pad 32 bit Unix timestamp to 36 bits in UUIDv7</t></li>
<li><t>- Added details on how to truncate 64 bit Unix timestamp to 36 bits in UUIDv7</t></li>
<li><t>- Added forward reference and bullet to UUIDv8 if truncating 64 bit Unix Epoch is not an option.</t></li>
<li><t>- Fixed bad reference to non-existent "time_or_node" in section 4.5.4</t></li>
</ul>
<t>draft-01</t>
<ul spacing="compact" empty="true">
<li><t>- Complete rewrite of entire document.</t></li>
<li><t>- The format, flow and verbiage used in the specification has been reworked to mirror the original RFC 4122 and current IETF standards.</t></li>
<li><t>- Removed the topics of UUID length modification, alternate UUID text formats, and alternate UUID encoding techniques.</t></li>
<li><t>- Research into 16 different historical and current implementations of time-based universal identifiers was completed at the end of 2020 in attempt to identify trends which have directly influenced design decisions in this draft document (https://github.com/uuid6/uuid6-ietf-draft/tree/master/research)</t></li>
<li><t>- Prototype implementation have been completed for UUIDv6, UUIDv7, and UUIDv8 in various languages by many GitHub community members. (https://github.com/uuid6/prototypes)</t></li>
</ul>
</section>
</section>
<section anchor="variant_and_version_fields" title="Variant and Version Fields">
<t>
The variant bits utilized by UUIDs in this specification
remain in the same octet as originally defined by <xref target="RFC4122" sectionFormat="comma" section="4.1.1"/>.
</t>
<t>
The next table details Variant 10xx (8/9/A/B) and the new versions defined by this specification.
A complete guide to all versions within this variant has been includes in <xref target="old_var_table"/>.
</t>
<table>
<name>New UUID variant 10xx (8/9/A/B) versions defined by this specification</name>
<thead>
<tr><td>Msb0</td><td>Msb1</td><td>Msb2</td><td>Msb3</td><td>Version</td><td>Description</td></tr>
</thead>
<tbody>
<tr><td>0</td><td>1</td><td>1</td><td>0</td><td>6</td><td>Reordered Gregorian time-based UUID specified in this document.</td></tr>
<tr><td>0</td><td>1</td><td>1</td><td>1</td><td>7</td><td>Unix Epoch time-based UUID specified in this document.</td></tr>
<tr><td>1</td><td>0</td><td>0</td><td>0</td><td>8</td><td>Reserved for custom UUID formats specified in this document</td></tr>
</tbody>
</table>
<t>
For UUID version 6, 7 and 8 the variant field placement from <xref target="RFC4122"/> are unchanged.
An example version/variant layout for UUIDv6 follows the table where M is the version and N is the variant.
</t>
<figure>
<name>UUIDv6 Variant Examples</name>
<artwork><![CDATA[
00000000-0000-6000-8000-000000000000
00000000-0000-6000-9000-000000000000
00000000-0000-6000-A000-000000000000
00000000-0000-6000-B000-000000000000
xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
]]></artwork>
</figure>
</section>
<section anchor="format" title="New Formats">
<t>
The UUID format is 16 octets; the variant bits in conjunction with the version bits described in the next section in determine finer structure.
</t>
<section anchor="uuidv6" title="UUID Version 6">
<t>
UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality.
It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs.
Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead.
</t>
<t>
Instead of splitting the timestamp into the low, mid and high sections from UUIDv1, UUIDv6 changes this sequence so timestamp bytes are stored from most to least significant.
That is, given a 60 bit timestamp value as specified for UUIDv1 in <xref target="RFC4122" sectionFormat="comma" section="4.1.4"/>,
for UUIDv6, the first 48 most significant bits are stored
first, followed by the 4 bit version (same position), followed by the remaining 12 bits of the original 60 bit timestamp.
</t>
<t>
The clock sequence bits remain unchanged from their usage and position in <xref target="RFC4122" sectionFormat="comma" section="4.1.5"/>.
</t>
<t>
The 48 bit node SHOULD be set to a pseudo-random value however implementations MAY choose to retain the old MAC address behavior from <xref target="RFC4122" sectionFormat="comma" section="4.1.6"/> and <xref target="RFC4122" sectionFormat="comma" section="4.5"/>. For more information on MAC address usage within UUIDs see the <xref target="Security"/>
</t>
<t>
The format for the 16-byte, 128 bit UUIDv6 is shown in Figure 1
</t>
<figure>
<name>UUIDv6 Field and Bit Layout</name>
<artwork>
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_high |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| time_mid | time_low_and_version |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|clk_seq_hi_res | clk_seq_low | node (0-1) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| node (2-5) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
</artwork>
</figure>
<dl newline="true">
<dt>time_high:</dt> <dd>The most significant 32 bits of the 60 bit starting timestamp.
Occupies bits 0 through 31 (octets 0-3)</dd>
<dt>time_mid:</dt> <dd>The middle 16 bits of the 60 bit starting timestamp.
Occupies bits 32 through 47 (octets 4-5)</dd>
<dt>time_low_and_version:</dt> <dd>The first four most significant bits MUST contain
the UUIDv6 version (0110) while the remaining 12 bits will contain
the least significant 12 bits from the 60 bit starting timestamp.
Occupies bits 48 through 63 (octets 6-7)</dd>
<dt>clk_seq_hi_res:</dt> <dd>The first two bits MUST be set to the UUID variant (10)
The remaining 6 bits contain the high portion of the clock sequence.
Occupies bits 64 through 71 (octet 8)</dd>
<dt>clock_seq_low:</dt> <dd>The 8 bit low portion of the clock sequence.
Occupies bits 72 through 79 (octet 9)</dd>
<dt>node:</dt> <dd>48 bit spatially unique identifier
Occupies bits 80 through 127 (octets 10-15)</dd>
</dl>
<t>
With UUIDv6 the steps for splitting the timestamp into time_high and time_mid are OPTIONAL
since the 48 bits of time_high and time_mid will remain in the same order.
An extra step of splitting the first 48 bits of the timestamp into the most significant
32 bits and least significant 16 bits proves useful when reusing an existing UUIDv1 implementation.
</t>
</section>
<section anchor="v7" title="UUID Version 7">
<t>
UUID version 7 features a time-ordered value field derived from the widely implemented and well known Unix Epoch timestamp source, the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded.
As well as improved entropy characteristics over versions 1 or 6.
</t>
<t>
Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible.
</t>
<figure>
<name>UUIDv7 Field and Bit Layout</name>
<artwork><![CDATA[
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| unix_ts_ms | ver | rand_a |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rand_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>
</figure>
<dl newline="true">
<dt>unix_ts_ms:</dt> <dd>48 bit big-endian unsigned number of Unix epoch timestamp as per <xref target="timestamp_granularity"/>.</dd>
<dt>ver:</dt> <dd>4 bit UUIDv7 version set as per <xref target="variant_and_version_fields"/></dd>
<dt>rand_a:</dt> <dd>12 bits pseudo-random data to provide uniqueness as per <xref target="monotonicity_counters"/> and <xref target="unguessability"/>.</dd>
<dt>var:</dt> <dd>The 2 bit variant defined by <xref target="variant_and_version_fields"/>.</dd>
<dt>rand_b:</dt> <dd>The final 62 bits of pseudo-random data to provide uniqueness as per <xref target="monotonicity_counters"/> and <xref target="unguessability"/>.</dd>
</dl>
</section>
<section anchor="v8" title="UUID Version 8">
<t>
UUID version 8 provides an RFC-compatible format for experimental or vendor-specific use cases.
The only requirement is that the variant and version bits MUST be set as defined in <xref target="variant_and_version_fields"/>.
UUIDv8's uniqueness will be implementation-specific and SHOULD NOT be assumed.
</t>
<t>
The only explicitly defined bits are the Version and Variant leaving 122 bits
for implementation specific time-based UUIDs. To be clear:
UUIDv8 is not a replacement for UUIDv4 where all 122 extra bits are
filled with random data.
</t>
<t>
Some example situations in which UUIDv8 usage could occur:
</t>
<ul>
<li><t>An implementation would like to embed extra information
within the UUID other than what is defined in this document.</t></li>
<li><t>An implementation has other application/language restrictions which
inhibit the use of one of the current UUIDs.</t></li>
</ul>
<figure>
<name>UUIDv8 Field and Bit Layout</name>
<artwork><![CDATA[
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| custom_a |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| custom_a | ver | custom_b |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|var| custom_c |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| custom_c |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
]]></artwork>
</figure>
<dl newline="true">
<dt>custom_a:</dt> <dd>The first 48 bits of the layout that can be filled as an implementation sees fit.</dd>
<dt>ver:</dt> <dd>The 4 bit version field as defined by <xref target="variant_and_version_fields"/></dd>
<dt>custom_b:</dt> <dd>12 more bits of the layout that can be filled as an implementation sees fit.</dd>
<dt>var:</dt> <dd>The 2 bit variant field as defined by <xref target="variant_and_version_fields"/>.</dd>
<dt>custom_c:</dt> <dd>The final 62 bits of the layout immediatly following the var field to be filled as an implementation sees fit.</dd>
</dl>
</section>
<section anchor="maxuuid" title="Max UUID">
<t>The Max UUID is special form of UUID that is specified to have all 128 bits set to 1. This UUID can be thought of as the inverse of Nil UUID defined in <xref target="RFC4122" sectionFormat="comma" section="4.1.7"/></t>
<figure>
<name>Max UUID Format</name>
<artwork><![CDATA[
FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF
]]></artwork>
</figure>
</section>
</section>
<section anchor="uuid_best_practices" title="UUID Best Practices">
<t>
The minimum requirements for generating UUIDs are
described in this document for each version.
Everything else is an implementation detail and
up to the implementer to decide what is appropriate for a given
implementation. That being said, various relevant factors are covered
below to help guide an implementer through the different trade-offs among differing UUID implementations.
</t>
<section anchor="timestamp_granularity" title="Timestamp Granularity">
<t>
UUID timestamp source, precision and length was the topic of great debate while creating this specification. As such choosing the right timestamp for your application is a very important topic. This section will detail some of the most common points on this topic.
</t>
<dl newline="true">
<dt>Reliability:</dt>
<dd>Implementations SHOULD use the current timestamp from a reliable source to provide values that are time-ordered and continually increasing.
Care SHOULD be taken to ensure that timestamp changes from the environment or operating system are handled in a way that is consistent with implementation requirements.
For example, if it is possible for the system clock to move backward due to either manual adjustment or corrections from a time synchronization protocol, implementations must decide how to handle such cases. (See Altering, Fuzzing, or Smearing bullet below.)
</dd>
<dt>Source:</dt>
<dd>UUID version 1 and 6 both utilize a Gregorian epoch timestamp while UUIDv7 utilizes a Unix Epoch timestamp. If other timestamp sources or a custom timestamp epoch are required UUIDv8 SHOULD be leveraged.</dd>
<dt>Sub-second Precision and Accuracy:</dt>
<dd>
Many levels of precision exist for timestamps: milliseconds, microseconds, nanoseconds, and beyond.
Additionally fractional representations of sub-second precision may be desired to mix various levels of precision in a time-ordered manner.
Furthermore, system clocks themselves have an underlying granularity and it is frequently less than the precision offered by the operating system.
With UUID version 1 and 6, 100-nanoseconds of precision are present while UUIDv7 features fixed millisecond level of precision within the Unix epoch that does not exceed the granularity capable in most modern systems.
For other levels of precision UUIDv8 SHOULD be utilized.
</dd>
<dt>Length:</dt>
<dd>The length of a given timestamp directly impacts how long a given UUID will be valid.
That is, how many timestamp ticks can be contained in a UUID before the maximum value for the timestamp field is reached.
Care should be given to ensure that the proper length is selected for a given timestamp.
UUID version 1 and 6 utilize a 60 bit timestamp and UUIDv7 features a 48 bit timestamp.</dd>
<dt>Altering, Fuzzing, or Smearing:</dt>
<dd>Implementations MAY alter the actual timestamp. Some examples included security considerations around providing a real clock value within a UUID, to correct inaccurate clocks or to handle leap seconds. This specification makes no requirement or guarantee about how close the clock value needs to be to actual time.</dd>
<dt>Padding:</dt>
<dd>When timestamp padding is required, implementations MUST pad the most significant bits (left-most) bits with zeros. An example is padding the most significant, left-most bits of a 32 bit Unix timestamp with zero's to fill out the 48 bit timestamp in UUIDv7.</dd>
<dt>Truncating:</dt>
<dd>Similarly, when timestamps need to be truncated: the lower, least significant bits MUST be used. An example would be truncating a 64 bit Unix timestamp to the least significant, right-most 48 bits for UUIDv7.</dd>
</dl>
</section>
<section anchor="monotonicity_counters" title="Monotonicity and Counters">
<t>
Monotonicity is the backbone of time-based sortable UUIDs. Naturally time-based UUIDs from this document will be monotonic due to an embedded timestamp however implementations can guarantee additional monotonicity via the concepts covered in this section.
</t>
<t>
Additionally, care SHOULD be taken to ensure UUIDs generated in batches are also monotonic. That is, if one-thousand UUIDs are generated for the same timestamp; there is sufficient logic for organizing the creation order of those one-thousand UUIDs.
For batch UUID creation implementions MAY utilize a monotonic counter which SHOULD increment for each UUID created during a given timestamp.
</t>
<t>
For single-node UUID implementations that do not need to create batches of UUIDs, the embedded timestamp within UUID version 1, 6, and 7 can provide sufficient monotonicity guarantees by simply ensuring that timestamp increments before creating a new UUID. For the topic of Distributed Nodes please refer to <xref target="distributed_shared_knowledge"/>
</t>
<t>
Implementations SHOULD choose one method for single-node UUID implementations that require batch UUID creation.
</t>
<dl newline="true">
<dt>Fixed-Length Dedicated Counter Bits (Method 1):</dt>
<dd>
This references the practice of allocating a specific number of bits in the UUID layout to the sole purpose of tallying the total number of UUIDs created during a given UUID timestamp tick.
Positioning of a fixed bit-length counter SHOULD be immediatly after the embedded timestamp. This promotes sortability and allows random data generation for each counter increment.
With this method rand_a section of UUIDv7 SHOULD be utilized as fixed-length dedicated counter bits that are incremented by one for every UUID generation.
The trailing random bits generated for each new UUID in rand_b can help produce unguessable UUIDs. In the event more counter bits are required the most significant, left-most, bits of rand_b MAY be leveraged as additional counter bits.
</dd>
<dt>Monotonic Random (Method 2):</dt>
<dd>
With this method the random data is extended to also double as a counter.
This monotonic random can be thought of as a "randomly seeded counter" which MUST be incremented in the least significant position for each UUID created on a given timestamp tick.
UUIDv7's rand_b section SHOULD be utilized with this method to handle batch UUID generation during a single timestamp tick.
The increment value for every UUID generation SHOULD be a random integer of any desired length larger than zero. It ensures the UUIDs retain the required level of unguessability characters provided by the underlying entropy.
The increment value MAY be one when the amount of UUIDs generated in a particular period of time is important and guessability is not an issue. However, it SHOULD NOT be used by implementations that favor unguessiblity, as the resulting values are easily guessable.
</dd>
</dl>
<t>
The following sub-topics cover topics related solely with creating reliable fixed-length dedicated counters:
</t>
<dl newline="true">
<dt>Fixed-Length Dedicated Counter Seeding:</dt>
<dd>
Implementations utilizing fixed-length counter method SHOULD randomly initialize the counter with each new timestamp tick.
However, when the timestamp has not incremented; the counter SHOULD be frozen and incremented via the desired increment logic.
When utilizing a randomly seeded counter alongside Method 1; the random MAY be regenerated with each counter increment without impacting sortability.
The downside is that Method 1 is prone to overflows if a counter of adequate length is not selected or the random data generated leaves little room for the required number of increments.
Implementations utilizing fixed-length counter method MAY also choose to randomly initialize a portion counter rather than the entire counter. For example, a 24 bit counter could have the 23 bits in least-significant, right-most, position randomly initialized. The remaining most significant, left-most counter bits are initialized as zero for the sole purpose of guarding against counter rollovers.
</dd>
<dt>Fixed-Length Dedicated Counter Length:</dt>
<dd>
Care MUST be taken to select a counter bit-length that can properly handle the level of timestamp precision in use.
For example, millisecond precision SHOULD require a larger counter than a timestamp with nanosecond precision.
General guidance is that the counter SHOULD be at least 12 bits but no longer than 42 bits.
Care SHOULD also be given to ensure that the counter length selected leaves room for sufficient entropy in the random portion of the UUID after the counter.
This entropy helps improve the unguessability characteristics of UUIDs created within the batch.
</dd>
</dl>
<t>
The following sub-topics cover rollover handling with either type of counter method:
</t>
<dl newline="true">
<dt>Counter Rollover Guards:</dt>
<dd>
The technique from Fixed-Length Dedicated Counter Seeding which describes allocating a segment of the fixed-length counter as a rollover guard is also helpful to mitigate counter rollover issues.
This same technique can be leveraged with Monotonic random counter methods by ensuring the total length of a possible increment in the least significant, right most position is less than the total length of the random being incremented.
As such the most significant, left-most, bits can be incremented as rollover guarding.
</dd>
<dt>Counter Rollover Handling:</dt>
<dd>
Counter rollovers SHOULD be handled by the application to avoid sorting issues.
The general guidance is that applications that care about absolute monotonicity and sortability SHOULD freeze the counter and wait for the timestamp to advance which ensures monotonicity is not broken.
Alternatively, implementations MAY increment the timestamp ahead of the actual time and reinitialize the counter.
</dd>
</dl>
<t>
Implementations MAY use the following logic to ensure UUIDs featuring embedded counters are monotonic in nature:
</t>
<ol spacing="compact">
<li><t>Compare the current timestamp against the previously stored timestamp.</t></li>
<li>
<t>If the current timestamp is equal to the previous timestamp; increment the counter according to the desired method.</t>
</li>
<li><t>If the current timestamp is greater than the previous timestamp; re-initialize the desired counter method to the new timestamp and generate new random bytes (if the bytes were frozen or being used as the seed for a monotonic counter).</t></li>
</ol>
<t>
Implementations SHOULD check if the the currently generated UUID is greater than the previously generated UUID. If this is not the case then any number of things could have occurred. Such as, but not limited to, clock rollbacks, leap second handling or counter rollovers. Applications SHOULD embed sufficient logic to catch these scenarios and correct the problem ensuring the next UUID generated is greater than the previous. To handle this scenario, the general guidance is that application MAY reuse the previous timestamp and increment the previous counter method.
</t>
</section>
<section anchor="distributed_shared_knowledge" title="Distributed UUID Generation">
<t>
Some implementations MAY desire to utilize multi-node, clustered, applications which involve two or more
nodes independently generating UUIDs that will be stored in a common location.
While UUIDs already feature sufficient entropy to ensure that the chances of collision are low as the total number of nodes increase; so does the likelihood of a collision.
This section will detail the approaches that MAY be utilized by multi-node UUID implementations in distributed environments.
</t>
<dl newline="true">
<dt>Centralized Registry:</dt>
<dd>With this method all nodes tasked with creating UUIDs consult a central registry and confirm the generated value is unique. As applications scale the communication with the central registry could become a bottleneck and impact UUID generation in a negative way. Utilization of shared knowledge schemes with central/global registries is outside the scope of this specification.</dd>
<dt>Node IDs:</dt>
<dd>
With this method, a pseudo-random Node ID value is placed within the UUID layout.
This identifier helps ensure the bit-space for a given node is unique, resulting in UUIDs that do not conflict with any other UUID created by another node with a different node id.
Implementations that choose to leverage an embedded node id SHOULD utilize UUIDv8.
The node id SHOULD NOT be an IEEE 802 MAC address as per <xref target="Security"/>.
The location and bit length are left to implementations and are outside the scope of this specification.
Furthermore, the creation and negotiation of unique node ids among nodes is also out of scope for this specification.
</dd>
</dl>
<t>
Utilization of either a Centralized Registry or Node ID are not required for implementing UUIDs in this specification. However implementations SHOULD utilize one of the two aforementioned methods if distributed UUID generation is a requirement.
</t>
</section>
<section anchor="collision_resistance" title="Collision Resistance">
<t>
Implementations SHOULD weigh the consequences of UUID collisions within their application and when deciding between UUID versions that use entropy (random) versus the other components such as <xref target="timestamp_granularity"/> and <xref target="monotonicity_counters"/>.
This is especially true for distributed node collision resistance as defined by <xref target="distributed_shared_knowledge"/>.
</t>
<t>
There are two example scenarios below which help illustrate the varying seriousness of a collision within an application.
</t>
<dl newline="true">
<dt>Low Impact</dt>
<dd>A UUID collision generated a duplicate log entry which results in incorrect statistics derived from the data. Implementations that are not negatively affected by collisions may continue with the entropy and uniqueness provided by the traditional UUID format.</dd>
<dt>High Impact:</dt>
<dd> A duplicate key causes an airplane to receive the wrong course which puts people's lives at risk. In this scenario there is no margin for error. Collisions MUST be avoided and failure is unacceptable. Applications dealing with this type of scenario MUST employ as much collision resistance as possible within the given application context.</dd>
</dl>
</section>
<section anchor="global_local_uniqueness" title="Global and Local Uniqueness">
<t>
UUIDs created by this specification MAY be used to provide local uniqueness guarantees.
For example, ensuring UUIDs created within a local application context are unique within a database MAY be sufficient for some implementations where global uniqueness outside of the application context, in other applications, or around the world is not required.
</t>
<t>
Although true global uniqueness is impossible to guarantee without a shared knowledge scheme; a shared knowledge scheme is not required by UUID to provide uniqueness guarantees.
Implementations MAY implement a shared knowledge scheme introduced in <xref target="distributed_shared_knowledge"/> as they see fit to extend the uniqueness guaranteed this specification and <xref target="RFC4122"/>.
</t>
</section>
<section anchor="unguessability" title="Unguessability">
<t>
Implementations SHOULD utilize a cryptographically secure pseudo-random number generator (CSPRNG) to provide values that are both difficult to predict ("unguessable") and have a low likelihood of collision ("unique").
Care SHOULD be taken to ensure the CSPRNG state is properly reseeded upon state changes, such as process forks, to ensure proper CSPRNG operation.
CSPRNG ensures the best of <xref target="collision_resistance"/> and <xref target="Security"/> are present in modern UUIDs.
</t>
<t>
Advice on generating cryptographic-quality random numbers can be found in <xref target="RFC4086"/>
</t>
</section>
<section anchor="sorting" title="Sorting">
<t>
UUIDv6 and UUIDv7 are designed so that implementations that require sorting (e.g. database indexes) SHOULD sort as opaque raw bytes, without need for parsing or introspection.
</t>
<t>
Time ordered monotonic UUIDs benefit from greater database index locality because the new values are near each other in the index.
As a result objects are more easily clustered together for better performance.
The real-world differences in this approach of index locality vs random data inserts can be quite large.
</t>
<t>
UUIDs formats created by this specification SHOULD be Lexicographically sortable while in the textual representation.
</t>
<t>
UUIDs created by this specification are crafted with big-ending byte order (network byte order) in mind. If Little-endian style is required a custom UUID format SHOULD be created using UUIDv8.
</t>
</section>
<section anchor="opacity" title="Opacity">
<t>
UUIDs SHOULD be treated as opaque values and implementations SHOULD NOT examine the bits in a UUID to whatever extent is possible. However, where necessary, inspectors should refer to <xref target="variant_and_version_fields"/> for more information on determining UUID version and variant.
</t>
</section>
<section anchor="database_considerations" title="DBMS and Database Considerations">
<t>
For many applications, such as databases, storing UUIDs as text is unnecessarily verbose, requiring 288 bits to represent 128 bit UUID values.
Thus, where feasible, UUIDs SHOULD be stored within database applications as the underlying 128 bit binary value.
</t>
<t>
For other systems, UUIDs MAY be stored in binary form or as text, as appropriate.
The trade-offs to both approaches are as such:
</t>
<ul spacing="compact">
<li><t>Storing as binary requires less space and may result in faster data access.</t></li>
<li><t>Storing as text requires more space but may require less translation if the resulting text form is to be used after retrieval and thus maybe simpler to implement.</t></li>
</ul>
<t>
DBMS vendors are encouraged to provide functionality to generate and store UUID formats defined by this specification for use as identifiers or left parts of identifiers such as, but not limited to, primary keys, surrogate keys for temporal databases, foreign keys included in polymorphic relationships, and keys for key-value pairs in JSON columns and key-value databases.
Applications using a monolithic database may find using database-generated UUIDs (as opposed to client-generate UUIDs) provides the best UUID monotonicity.
In addition to UUIDs, additional identifiers MAY be used to ensure integrity and feedback.
</t>
</section>
</section>
<section anchor="IANA" title="IANA Considerations">
<t>This document has no IANA actions.</t>
</section>
<section anchor="Security" title="Security Considerations">
<t>
MAC addresses pose inherent security risks and SHOULD not be used within a UUID.
Instead CSPRNG data SHOULD be selected from a source with sufficient entropy to ensure guaranteed
uniqueness among UUID generation. See <xref target="unguessability"/> for more information.
</t>
<t>
Timestamps embedded in the UUID do pose a very small attack surface. The timestamp in conjunction with
an embedded counter does signal the order of creation for a given UUID and it's corresponding data but
does not define anything about the data itself or the application as a whole. If UUIDs are required for
use with any security operation within an application context in any shape or form then <xref target="RFC4122"/> UUIDv4 SHOULD be utilized.
</t>
</section>
<section anchor="Acknowledgements" title="Acknowledgements">
<t>The authors gratefully acknowledge the contributions of
Ben Campbell,
Ben Ramsey,
Fabio Lima,
Gonzalo Salgueiro,
Martin Thomson,
Murray S. Kucherawy,
Rick van Rein,
Rob Wilton,
Sean Leonard,
Theodore Y. Ts'o.,
Robert Kieffer,
sergeyprokhorenko,
LiosK
As well as all of those in the IETF community and on GitHub to who contributed to the discussions which resulted in this document.
</t>
</section>
</middle>
<back>
<references title="Normative References">
<reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119" quoteTitle="true" derivedAnchor="RFC2119">
<front>
<title>Key words for use in RFCs to Indicate Requirement Levels</title>
<author initials="S." surname="Bradner" fullname="S. Bradner">
<organization showOnFrontPage="true"/>
</author>
<date year="1997" month="March"/>
<abstract>
<t indent="0">In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
</abstract>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="2119"/>
<seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>
<reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174" quoteTitle="true" derivedAnchor="RFC8174">
<front>
<title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
<author initials="B." surname="Leiba" fullname="B. Leiba">
<organization showOnFrontPage="true"/>
</author>
<date year="2017" month="May"/>
<abstract>
<t indent="0">RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
</abstract>
</front>
<seriesInfo name="BCP" value="14"/>
<seriesInfo name="RFC" value="8174"/>
<seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>
<reference anchor="RFC4122" target="https://www.rfc-editor.org/info/rfc4122">
<front>
<title>A Universally Unique IDentifier (UUID) URN Namespace</title>
<author initials="P." surname="Leach" fullname="P. Leach">
<organization/>
</author>
<author initials="M." surname="Mealling" fullname="M. Mealling">
<organization/>
</author>
<author initials="R." surname="Salz" fullname="R. Salz">
<organization/>
</author>
<date year="2005" month="July"/>
<abstract>
<t>This specification defines a Uniform Resource Name namespace for UUIDs (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDentifier). A UUID is 128 bits long, and can guarantee uniqueness across space and time. UUIDs were originally used in the Apollo Network Computing System and later in the Open Software Foundation\'s (OSF) Distributed Computing Environment (DCE), and then in Microsoft Windows platforms.</t>
<t>This specification is derived from the DCE specification with the kind permission of the OSF (now known as The Open Group). Information from earlier versions of the DCE specification have been incorporated into this document. [STANDARDS-TRACK]</t>
</abstract>
</front>
<seriesInfo name="RFC" value="4122"/>
<seriesInfo name="DOI" value="10.17487/RFC4122"/>
</reference>
<reference anchor="RFC4086" target="https://www.rfc-editor.org/info/rfc4086">
<front>
<title>Randomness Requirements for Security</title>
<author initials="D." surname="Eastlake 3rd" fullname="D. Eastlake 3rd">
<organization/>
</author>
<author initials="J." surname="Schiller" fullname="J. Schiller">
<organization/>
</author>
<author initials="S." surname="Crocker" fullname="S. Crocker">
<organization/>
</author>
<date year="2005" month="June"/>
<abstract>
<t>Security systems are built on strong cryptographic algorithms that foil pattern analysis attempts. However, the security of these systems is dependent on generating secret quantities for passwords, cryptographic keys, and similar quantities. The use of pseudo-random processes to generate secret quantities can result in pseudo-security. A sophisticated attacker may find it easier to reproduce the environment that produced the secret quantities and to search the resulting small set of possibilities than to locate the quantities in the whole of the potential number space.</t>
<t>Choosing random quantities to foil a resourceful and motivated adversary is surprisingly difficult. This document points out many pitfalls in using poor entropy sources or traditional pseudo-random number generation techniques for generating such quantities. It recommends the use of truly random hardware techniques and shows that the existing hardware on many systems can be used for this purpose. It provides suggestions to ameliorate the problem when a hardware solution is not available, and it gives examples of how large such quantities need to be for some applications. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
</abstract>
</front>
<seriesInfo name="RFC" value="4086"/>
<seriesInfo name="DOI" value="10.17487/RFC4086"/>
</reference>
</references>
<references title="Informative References">
<reference anchor="LexicalUUID" target="https://github.com/twitter-archive/cassie">
<front>
<title>A Scala client for Cassandra</title>
<author>
<organization showOnFrontPage="true">Twitter</organization>
</author>
<date month="November" year="2012" />
</front>
<seriesInfo name="commit" value="f6da4e0" />
</reference>
<reference anchor="Snowflake" target="https://github.com/twitter-archive/snowflake/releases/tag/snowflake-2010">
<front>
<title>Snowflake is a network service for generating unique ID numbers at high scale with some simple guarantees.</title>
<author>
<organization showOnFrontPage="true">Twitter</organization>
</author>
<date month="May" year="2014" />
</front>
<seriesInfo name="Commit" value="b3f6a3c" />
</reference>
<reference anchor="Flake" target="https://github.com/boundary/flake">
<front>
<title>Flake: A decentralized, k-ordered id generation service in Erlang</title>
<author>
<organization showOnFrontPage="true">Boundary</organization>
</author>
<date month="February" year="2017" />
</front>
<seriesInfo name="Commit" value="15c933a" />
</reference>
<reference anchor="ShardingID" target="https://instagram-engineering.com/sharding-ids-at-instagram-1cf5a71e5a5c">
<front>
<title>Sharding & IDs at Instagram</title>
<author>
<organization showOnFrontPage="true">Instagram Engineering</organization>
</author>
<date month="December" year="2012" />
</front>
</reference>
<reference anchor="KSUID" target="https://github.com/segmentio/ksuid">
<front>
<title>K-Sortable Globally Unique IDs</title>
<author>
<organization showOnFrontPage="true">Segment</organization>
</author>
<date month="July" year="2020" />
</front>
<seriesInfo name="Commit" value="bf376a7" />
</reference>
<reference anchor="Elasticflake" target="https://github.com/ppearcy/elasticflake">
<front>
<title>Sequential UUID / Flake ID generator pulled out of elasticsearch common</title>
<author initials="P" surname="Pearcy" fullname="Paul Pearcy">
<organization />
</author>
<date month="January" year="2015" />
</front>
<seriesInfo name="Commit" value="dd71c21" />
</reference>
<reference anchor="FlakeID" target="https://github.com/T-PWK/flake-idgen">
<front>
<title>Flake ID Generator</title>
<author initials="T" surname="Pawlak" fullname="Tom Pawlak">
<organization />
</author>
<date month="April" year="2020" />
</front>
<seriesInfo name="Commit" value="fcd6a2f" />
</reference>
<reference anchor="Sonyflake" target="https://github.com/sony/sonyflake">
<front>
<title>A distributed unique ID generator inspired by Twitter's Snowflake</title>
<author>
<organization showOnFrontPage="true">Sony</organization>
</author>
<date month="August" year="2020" />
</front>
<seriesInfo name="Commit" value="848d664" />
</reference>
<reference anchor="orderedUuid" target="https://itnext.io/laravel-the-mysterious-ordered-uuid-29e7500b4f8">
<front>
<title>Laravel: The mysterious "Ordered UUID"</title>
<author initials="IT" surname="Cabrera" fullname="Italo Baeza Cabrera">
<organization />
</author>
<date month="January" year="2020" />
</front>
</reference>
<reference anchor="COMBGUID" target="https://github.com/richardtallent/RT.Comb">
<front>
<title>Creating sequential GUIDs in C# for MSSQL or PostgreSql</title>
<author initials="R" surname="Tallent" fullname="Richard Tallent">
<organization />
</author>
<date month="December" year="2020" />
</front>
<seriesInfo name="Commit" value="2759820" />
</reference>
<reference anchor="ULID" target="https://github.com/ulid/spec">
<front>
<title>Universally Unique Lexicographically Sortable Identifier</title>
<author initials="A" surname="Feerasta" fullname="Alizain Feerasta">
<organization />
</author>
<date month="May" year="2019" />
</front>
<seriesInfo name="Commit" value="d0c7170" />
</reference>
<reference anchor="SID" target="https://github.com/chilts/sid">
<front>
<title>sid : generate sortable identifiers</title>
<author initials="A" surname="Chilton" fullname="Andrew Chilton">
<organization />
</author>
<date month="June" year="2019" />
</front>
<seriesInfo name="Commit" value="660e947" />
</reference>
<reference anchor="pushID" target="https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html">
<front>
<title>The 2^120 Ways to Ensure Unique Identifiers</title>
<author>
<organization showOnFrontPage="true">Google</organization>
</author>
<date month="February" year="2015" />
</front>
</reference>
<reference anchor="XID" target="https://github.com/rs/xid">
<front>
<title>Globally Unique ID Generator</title>
<author initials="O" surname="Poitrey" fullname="Olivier Poitrey">
<organization />
</author>
<date month="October" year="2020" />
</front>
<seriesInfo name="Commit" value="efa678f" />
</reference>
<reference anchor="ObjectID" target="https://docs.mongodb.com/manual/reference/method/ObjectId/">
<front>
<title>ObjectId - MongoDB Manual</title>
<author>
<organization showOnFrontPage="true">MongoDB</organization>
</author>
</front>
</reference>
<reference anchor="CUID" target="https://github.com/ericelliott/cuid">
<front>
<title>Collision-resistant ids optimized for horizontal scaling and performance.</title>
<author initials="E" surname="Elliott" fullname="Eric Elliott">
<organization />
</author>
<date month="October" year="2020" />
</front>
<seriesInfo name="Commit" value="215b27b" />
</reference>
<reference anchor="IEEE754" target="https://standards.ieee.org/ieee/754/6210/">
<front>
<title>IEEE Standard for Floating-Point Arithmetic.</title>
<author>
<organization showOnFrontPage="true">IEEE</organization>
</author>
<date month="July" year="2019" />
</front>
<seriesInfo name="Series" value="754-2019" />
</reference>
</references>
<section anchor="example_code" title="Example Code">
<section anchor="creating_a_uuidv6_value" title="Creating a UUIDv6 Value">
<t>This section details a function in C which converts from a UUID version 1 to version 6:
</t>
<figure>
<name>UUIDv6 Function in C</name>
<artwork><![CDATA[
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <arpa/inet.h>
#include <uuid/uuid.h>
/* Converts UUID version 1 to version 6 in place. */
void uuidv1tov6(uuid_t u) {
uint64_t ut;
unsigned char *up = (unsigned char *)u;
// load ut with the first 64 bits of the UUID
ut = ((uint64_t)ntohl(*((uint32_t*)up))) << 32;
ut |= ((uint64_t)ntohl(*((uint32_t*)&up[4])));
// dance the bit-shift...
ut =
((ut >> 32) & 0x0FFF) | // 12 least significant bits
(0x6000) | // version number
((ut >> 28) & 0x0000000FFFFF0000) | // next 20 bits
((ut << 20) & 0x000FFFF000000000) | // next 16 bits
(ut << 52); // 12 most significant bits
// store back in UUID
*((uint32_t*)up) = htonl((uint32_t)(ut >> 32));
*((uint32_t*)&up[4]) = htonl((uint32_t)(ut));
}
]]></artwork>
</figure>
</section>
<section anchor="creating_a_uuidv7_value" title="Creating a UUIDv7 Value">
<figure>
<name>UUIDv7 Function in C</name>
<artwork><![CDATA[
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
// ...
// csprng data source
FILE *rndf;
rndf = fopen("/dev/urandom", "r");
if (rndf == 0) {
printf("fopen /dev/urandom error\n");
return 1;
}
// ...
// generate one UUIDv7E
uint8_t u[16];
struct timespec ts;
int ret;
ret = clock_gettime(CLOCK_REALTIME, &ts);
if (ret != 0) {
printf("clock_gettime error: %d\n", ret);
return 1;
}
uint64_t tms;
tms = ((uint64_t)ts.tv_sec) * 1000;
tms += ((uint64_t)ts.tv_nsec) / 1000000;
memset(u, 0, 16);
fread(&u[6], 10, 1, rndf); // fill everything after the timestamp with random bytes