Functional Specifications
Functional specification for the ID Generator service — ID types, generation rules, filters, pool management, and exhaustion handling.
ID types
Each consuming application is assigned an ID type (e.g., farmer_id, household_id, national_id).
ID types are pre-configured via config file or Helm values — not created via API.
Each ID type has one configurable parameter: ID length (2–32 digits).
All filter rules are global (same across all ID types).
The same numeric ID may exist in multiple ID types — pools are fully independent.
Adding an ID type
Add the new ID type to the configuration (YAML config or Helm values).
Restart pods (rolling restart or Helm upgrade).
The service auto-creates the database table and fills the initial pool.
Existing ID type tables and their data are fully preserved.
Removing an ID type
Remove the ID type from the configuration and restart.
The service returns
IDG-003 Unknown ID typefor requests to the removed type.The database table is not automatically dropped — a safety measure against configuration typos.
A DBA can manually drop the orphaned table if storage reclaim is needed.
ID generation rules
Structure
Numeric only — no alphabets or special characters.
Length — configurable per ID type, maximum 32 digits.
Last digit — Verhoeff checksum. The generator produces
(length - 1)random digits and appends 1 checksum digit.Randomness — Python
secretsmodule (cryptographically secure).
Filters
Every generated ID must pass all 10 filters. These filter rules are inspired by MOSIP UIN generation filters.
1
Length
ID must be exactly the configured length for its ID type
Per-ID-type id_length
2
Not-Start-With
ID must not begin with specified digits (e.g., 0, 1)
not_start_with
3
Sequence
No ascending/descending sequences beyond limit (e.g., limit=3 → "123" rejected)
sequence_limit
4
Repeating Digit
No same digit repeating within N positions (e.g., limit=2 → "11" rejected)
repeating_limit
5
Repeating Block
No repeated digit blocks (e.g., limit=2 → "48xx48" rejected)
repeating_block_limit
6
Conjugative Even Digits
No N consecutive even digits (2,4,6,8) in a row
conjugative_even_digits_limit
7
First = Last
First N digits must not equal last N digits
digits_group_limit
8
First = Reverse(Last)
First N digits must not equal reverse of last N digits
reverse_digits_group_limit
9
Restricted Numbers
ID must not contain any blacklisted substrings
restricted_numbers
10
Cyclic Numbers
ID must not contain any of the 9 known mathematical cyclic number patterns
Hardcoded list
Cyclic numbers (hardcoded)
The following cyclic number patterns are banned:
14285705882352941176470526315789473684210434782608695652173913034482758620689655172413793102127659574468085106382978723404255319148936170169491525423728813559322033898305084745762711864406779661016393442622950819672131147540983606557377049180327868852459010309278350515463917525773195876288659793814432989690721649484536082474226804123711340206185567
Pool management
The service maintains a pre-generated pool of AVAILABLE IDs per ID type in PostgreSQL.
pool_min_threshold
Trigger replenishment when AVAILABLE count falls below
pool_generation_batch_size
Number of IDs to generate per replenishment cycle
pool_check_interval_seconds
How often to check pool levels (default: 30s)
exhaustion_max_attempts
Random attempts before declaring space exhausted
Background replenishment runs on every pod, coordinated via PostgreSQL advisory locks.
No archive table — at expected scale (up to 50M IDs per type), a single table with a status column is sufficient.
Uniqueness — every generated ID is checked against all existing IDs (AVAILABLE and TAKEN) before insertion.
ID space exhaustion
The effective ID space is significantly smaller than the raw numeric range due to filters:
Raw space:
8 × 10^(id_length - 2)(first digit restricted to 2–9, last digit is checksum)After filters: typically 15–60% of raw space, depending on ID length and filter parameters. An estimation of the effective space size after filters is available in the table below.
Estimated ID space by length (after filters)
These estimates were generated using scripts/space_estimator.py.
6
35,919
7
244,348
8
2,382,981
9
16,379,411
10
164,804,199
11
1,621,760,763
12
15,716,806,211
13
149,894,769,328
14
1,416,056,507,189
15
13,285,071,919,224
16
123,889,361,047,011
When the pool is empty and no more valid IDs can be generated:
The service returns
IDG-002(HTTP 410 Gone) — ID space permanently exhausted.This is distinct from
IDG-001(HTTP 503) — pool temporarily empty, replenishment in progress.
Configuration
Any setting can be overridden via environment variables using __ as the nested delimiter:
Database schema
One table per ID type, auto-created on startup:
API endpoints
For the complete API reference, see API Reference.
POST
/v1/idgenerator/{id_type}/id
Issue one ID from the pool
GET
/v1/idgenerator/{id_type}/id/validate/{id}
Validate an ID's structure
GET
/v1/idgenerator/health
Health check
GET
/v1/idgenerator/version
Service version and build info
GET
/v1/idgenerator/config
Active configuration
Reference
ID generation filters inspired by: MOSIP UIN Generator
Last updated
Was this helpful?

