Contextualising identifiers in a system
Tags: systemdesign, architecture, watercooler
Published: 2023-08-02 06:42:06

## Introduction

At least two unique identifiers exist even in the most rudimentary authentication systems: user ID and session ID. It is hard to keep track of different identifiers in a system. These identifiers are logged to files, reported to Sentry, sent to the frontend, passed around to developers in Slack in bug reports, and, most importantly, shared with non-programmers in the team.

![first](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1mip0f441ghgme8c98b.png)

In no time, the `user.Id` is propagated as just 507f1f77bcf86cd799439011, which is then, for example, shared on Slack by customer support to report a bug. The developers then have to make sense out of this random ID and try to map it to an actual database record. The backtracking becomes a nuisance when the context is unclear.

## The missing jigsaw piece

The identifier may propagate to a log file, Slack message, Sentry report, CMS dashboard or Google Analytics. The root cause of the problem is the loss of context from the identifier. The problem seems trivial if the system is not large enough. In systems with myriad unique identifiers, each representing an essential entity, issues related to backtracking or context retention can escalate rapidly.

But what if the context is attached to the identifier itself? That will solve the problem. The identifier may reach the end of the universe, but the relevant context will travel with it.

That is where identifier prefixing comes in.

## Expounding the argument

Most modern systems have identifiers like TXN_507f1f77bcf86cd799439011. Here, the prefix “TX_” contextualises the identifier. For example, the given identifier can be guessed as a transaction ID without additional information.

The idea is to attach meaningful prefixes to critical identifiers. That will ensure these identifiers easily differentiate from the noise outside the system. The prefix is carrying relevant information about the identifier itself.

## Getting down to business

Here is an example to demonstrate the implementation.

A program uses UUID strings to assign unique IDs to its database records. The program MUST respect the UUID formatting during retrieval and modification of the database documents. But it may ignore the formatting elsewhere.

![second](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g73r5lsavzbpafm2fw64.png)

In such a system, all the entity modules can implement `toUUID` and `fromUUID` functions. Role of these functions, implemented internally, will be to convert a *(prefix)_ID* to ID and vice-versa, respectively. These functions can translate prefixed identifiers to UUID formatted strings before the database query construction. Attachment of prefix to the returning value of identifiers from the entity modules can also be guaranteed.

The type of the IDs returned from the modules may only be asserted as a string (as opposed to a valid UUID). It is one of the caveats of the implementation: only the entity module can assert the UUID formatting. Everyone else may treat the ID as any other string.

The prefixed identifier may now be sent to Sentry or logged to AWS S3, but it will always carry the context of the identifier with it. Even the non-programmers will recognise a transaction ID from the CMS dashboard. What a relief!

## Conclusion

The idea is simple enough to explain without code. It just need two functions to convert an ID to a prefixed ID and vice-versa. But the value addition is massive.

Identifier contextualising is not a new concept. People have been doing it for years now.