SHA Hashing
dataset splitting
machine learning
data preprocessing
cryptographic hash functions

SHA Hashing for training/validation/testing set split

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Using a SHA hash to split data into train, validation, and test sets is a good way to make the split deterministic and reproducible. Instead of depending on row order or a random seed tied to one environment, you assign each example to a split based on a stable identifier and a hash threshold. This is especially useful when the dataset grows over time and you want old examples to stay in the same split.

Why Hash-Based Splits Are Useful

A random split with a seed is reproducible only as long as the dataset ordering stays the same. If you add rows, re-sort the file, or rebuild the dataset from another source, the split can drift.

Hash-based splitting avoids that by using a stable key such as:

  • customer ID
  • document ID
  • image filename
  • a composite business key

As long as the key is stable, the split assignment stays stable too.

The Core Idea

The algorithm is simple:

  1. choose a stable identifier for each example
  2. hash the identifier with SHA-256 or similar
  3. convert part of the hash to an integer or fraction
  4. map that value into train, validation, or test ranges

For example:

  • '0.00 to 0.80 -> train'
  • '0.80 to 0.90 -> validation'
  • '0.90 to 1.00 -> test'

Because SHA values are well distributed, the resulting split is usually close to the desired proportions.

Runnable Python Example

python
1import hashlib
2import pandas as pd
3
4
5def assign_split(key: str) -> str:
6    digest = hashlib.sha256(key.encode("utf-8")).hexdigest()
7    bucket = int(digest[:8], 16) / 0xFFFFFFFF
8
9    if bucket < 0.80:
10        return "train"
11    if bucket < 0.90:
12        return "validation"
13    return "test"
14
15
16df = pd.DataFrame(
17    {
18        "id": ["A001", "A002", "A003", "A004", "A005"],
19        "value": [10, 20, 30, 40, 50],
20    }
21)
22
23df["split"] = df["id"].apply(assign_split)
24print(df)

This code is deterministic. If you run it again tomorrow, or on another machine, the same IDs fall into the same splits.

Use the Right Identifier

The identifier matters more than the hash function choice. If you hash a row number, the split becomes fragile because row numbers change. If you hash a user ID, product ID, or another real business key, the split stays stable.

A composite key also works when one column is not unique.

python
1import hashlib
2
3
4def make_key(user_id: str, timestamp: str) -> str:
5    return f"{user_id}|{timestamp}"
6
7print(hashlib.sha256(make_key("u17", "2026-03-11").encode()).hexdigest())

Choose a key that represents the unit you want to keep together. If all rows for the same customer must stay in the same split, hash the customer identifier, not the individual record identifier.

Why This Helps With Evolving Datasets

Hash-based splits are especially valuable when new examples are appended regularly. New rows receive a split assignment without reshuffling the old dataset.

That is a major operational advantage in production ML pipelines because it keeps offline evaluation consistent over time.

It also helps when several teams or jobs need to reproduce the same split independently. No shared random seed state or saved index file is required as long as everyone hashes the same stable key with the same thresholds.

Common Pitfalls

  • Hashing unstable row numbers instead of stable identifiers.
  • Hashing per-record IDs when the real requirement is to keep a whole group together.
  • Changing the split thresholds later and expecting assignments to remain identical.
  • Assuming a cryptographic hash is needed for security here; the main benefit is determinism and good distribution.
  • Forgetting to document the exact key-building rule so other jobs reproduce the same split.

Summary

  • SHA-based splitting gives deterministic, reproducible dataset partitions.
  • The stability of the identifier is more important than the specific hash function.
  • Hashing is useful when datasets grow or are rebuilt over time.
  • Use group-level keys when related examples must remain in the same split.
  • Document the key format and thresholds so the split remains consistent across pipelines.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

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

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.