Unique ID generation
DateTime.Now.Ticks
Numeric IDs
C# programming
.NET development

Generating Unique Numeric IDs using DateTime.Now.Ticks

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Using DateTime.Now.Ticks to create numeric identifiers is attractive because it is simple and produces values that usually increase over time. The catch is that raw ticks are not a complete uniqueness strategy. They can collide under concurrency, and they are only meaningful inside the clock context of the current machine.

What a Tick Value Really Represents

In .NET, a tick is 100 nanoseconds. DateTime.Now.Ticks returns the number of ticks since the start of the Gregorian calendar used by DateTime. That gives you a large long value that changes frequently, which makes it a decent ingredient for an identifier.

However, there are two details to keep in mind:

  • 'Now uses local time, so daylight saving changes and clock adjustments can affect ordering.'
  • The system clock resolution is coarser than 100 nanoseconds, so multiple calls can still observe the same tick value.

For ID generation, DateTime.UtcNow.Ticks is usually a better base value because it avoids local-time ambiguity.

A Safer Tick-Based Generator

If you really need a numeric, roughly time-ordered ID inside one process, combine the current tick value with an atomic last-seen check. That guarantees monotonic growth even when several threads ask for IDs at the same moment.

csharp
1using System;
2using System.Threading;
3
4public static class TickIdGenerator
5{
6    private static long _lastIssued;
7
8    public static long NextId()
9    {
10        while (true)
11        {
12            long candidate = DateTime.UtcNow.Ticks;
13            long previous = Volatile.Read(ref _lastIssued);
14
15            if (candidate <= previous)
16            {
17                candidate = previous + 1;
18            }
19
20            long original = Interlocked.CompareExchange(
21                ref _lastIssued,
22                candidate,
23                previous);
24
25            if (original == previous)
26            {
27                return candidate;
28            }
29        }
30    }
31}
32
33for (int i = 0; i < 5; i++)
34{
35    Console.WriteLine(TickIdGenerator.NextId());
36}

This generator is still simple, but it solves the most obvious single-process collision problem. If two threads read the same clock value, one of them increments beyond the last issued number and retries safely.

When Tick-Based IDs Are Acceptable

This approach can work well for temporary file names, in-memory object identifiers, log correlation inside one service instance, or other local scenarios where numeric output is preferred and global uniqueness is not required.

It is less suitable for durable database keys, distributed systems, public identifiers, or anything security-sensitive. In those cases, the better tool is usually a database sequence, an identity column, a Snowflake-style generator, or a GUID and related modern variants if string output is acceptable.

Common Pitfalls

The biggest mistake is using raw DateTime.Now.Ticks directly and assuming it cannot repeat. In a fast loop or multithreaded code path, duplicate values are possible because the clock does not advance for every call.

Another issue is assuming tick-based IDs are globally unique. They are not. Two machines can generate the same value at roughly the same time, especially if their clocks are synchronized.

Do not ignore clock drift or manual clock changes. NTP corrections, VM resume events, and time configuration changes can all move the system clock. The atomic fallback in the example keeps IDs increasing inside one process, but it does not solve cross-process coordination.

Finally, think about information leakage. A tick-derived ID reveals timing information. If IDs are exposed externally, users may infer creation order or approximate event time, which is sometimes undesirable.

Summary

  • 'DateTime.Now.Ticks is a timestamp, not a full uniqueness guarantee.'
  • Prefer DateTime.UtcNow.Ticks if you build a time-based numeric ID.
  • Add atomic coordination such as Interlocked.CompareExchange to avoid same-process collisions.
  • Use tick-based IDs only for local, low-risk scenarios where rough ordering is useful.
  • For distributed or durable identifiers, prefer dedicated ID-generation strategies.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.