A PostgreSQL extension that provides a flexible implementation of Snowflake IDs with customisable bit widths for the timestamp, type ID, and counter components.
Snowflake IDs are unique 64-bit identifiers commonly used in distributed systems. They are composed of:
- Timestamp bits: Representing the time when the ID was generated
- Type/Node bits: Identifying the type of entity or the node that generated the ID
- Counter bits: A sequence number ensuring uniqueness for a given timestamp/type combination
- Customisable bit allocation for timestamp, type ID, and counter
- Custom epoch start date support
- Multiple snowflake types support
- Generation and extraction functions for each type
make
sudo make installYou should have Postgresql development files installed on your system.
- Register a new Snowflake ID type:
First, a new snowflake type should be registered:
-- Register with default settings (41 timestamp bits, 10 type bits, 12 counter bits)
CALL snowflake.register('user_id');
-- Register with custom bit allocation
CALL snowflake.register('order_id', 42, 8, 13);
-- Register with custom epoch
CALL snowflake.register('session_id', 41, 10, 12, '2022-01-01 00:00:00 UTC');- Generate a Snowflake ID:
Once registered with register('type_name'), the generate_<type_name> function is created that can be used to generate snowflakes:
-- Generate a user ID
SELECT snowflake.generate_user_id(now(), 1, 1);
-- Generate an order ID with specific type and counter
SELECT snowflake.generate_order_id('2023-12-01 10:30:00 UTC', 5, 1000);- Extract components from a Snowflake ID:
All the fields can be extracted using the extract_<type_name> function:
SELECT ts,type_id,counter FROM snowflake.extract_user_id(snowflake.generate_user_id(now(), 1, 1)::snowflake.user_id);- Use in table definitions:
CREATE TABLE users (
id snowflake.user_id PRIMARY KEY,
name text NOT NULL,
created_at timestamptz DEFAULT now()
);
INSERT INTO users (id, name)
VALUES (snowflake.generate_user_id(now(), 1, 1), 'John Doe');- Cleanup
When no longer needed, snowflake type can be removed using unregister function:
CALL snowflake.unregister('user_id');This will drop the snowflake type and all associated functions.
Registers a new Snowflake ID type.
Parameters:
type_name(text): The name of the type to be created. It must start with a letter and contain only alphanumeric characters and underscorestimestamp_bits(bigint, default: 41): The number of bits for the timestamptype_bits(bigint, default: 10): The number of bits for the type IDcounter_bits(bigint, default: 12): The number of bits for counterstart_date(timestamptz, default: '2020-01-01 00:00:00 UTC'): Epoch start date
Constraints:
- The total number of bits must not exceed 63
- All bit parameters must be positive
- The type name must be a valid identifier
Unregisters a Snowflake ID type and drops all associated objects.
Parameters:
type_name(text): Name of the type registered bysnowflake.register
For each registered type_name, the following functions are created:
Generates a Snowflake ID.
Parameters:
ts(timestamptz): Timestamp for the IDtype_id(bigint): Type identifiercounter(bigint): Counter value
Returns: snowflake.<type_name>
Extracts components from a Snowflake ID.
Parameters:
id(snowflake.<type_name>): The Snowflake ID to extract from
Returns: Table with columns ts, type_id, counter
- Maximum total bits used: 63 (due to PostgreSQL bigint limitation)
- Timestamps have second-level precision only
- No built-in distributed coordination (each node should use unique type IDs)