Skip to content
snowflake

snowflake

snowflake : Snowflake-style 64-bit ID generator and sequence utilities for PostgreSQL

Overview

ID Extension Package Version Category License Language
4590
snowflake
snowflake
2.5.0
FUNC
PostgreSQL
C
Attribute Has Binary Has Library Need Load Has DDL Relocatable Trusted
--s-d--
No
Yes
No
Yes
no
no
Relationships
Schemas snowflake
See Also
spock
lolor

works on pgedge kernel fork. Set snowflake.node (1..1023) before using snowflake.nextval().

Packages

Type Repo Version PG Major Compatibility Package Pattern Dependencies
EXT
PIGSTY
2.5.0
18
17
16
15
14
snowflake -
RPM
PIGSTY
18.4
18
17
16
15
14
pgedge-$v -
DEB
PIGSTY
18.4
18
17
16
15
14
pgedge-$v -
Linux / PG PG18 PG17 PG16 PG15 PG14
el8.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
el8.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
el9.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
el9.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
el10.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
el10.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
d12.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
d12.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
d13.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
d13.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u22.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u22.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u24.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u24.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u26.x86_64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
u26.aarch64
PIGSTY 18.4
PIGSTY 17.10
PIGSTY 16.14
PIGSTY 15.18
N/A
Package Version OS ORG SIZE File URL
pgedge-18 18.4 el8.x86_64 pigsty 13.2 MiB pgedge-18-18.4-1PIGSTY.el8.x86_64.rpm
pgedge-18 18.4 el8.aarch64 pigsty 12.8 MiB pgedge-18-18.4-1PIGSTY.el8.aarch64.rpm
pgedge-18 18.4 el9.x86_64 pigsty 12.1 MiB pgedge-18-18.4-1PIGSTY.el9.x86_64.rpm
pgedge-18 18.4 el9.aarch64 pigsty 11.8 MiB pgedge-18-18.4-1PIGSTY.el9.aarch64.rpm
pgedge-18 18.4 el10.x86_64 pigsty 12.2 MiB pgedge-18-18.4-1PIGSTY.el10.x86_64.rpm
pgedge-18 18.4 el10.aarch64 pigsty 12.0 MiB pgedge-18-18.4-1PIGSTY.el10.aarch64.rpm
pgedge-18 18.4 d12.x86_64 pigsty 10.5 MiB pgedge-18_18.4-1PIGSTY~bookworm_amd64.deb
pgedge-18 18.4 d12.aarch64 pigsty 10.0 MiB pgedge-18_18.4-1PIGSTY~bookworm_arm64.deb
pgedge-18 18.4 d13.x86_64 pigsty 10.5 MiB pgedge-18_18.4-1PIGSTY~trixie_amd64.deb
pgedge-18 18.4 d13.aarch64 pigsty 10.1 MiB pgedge-18_18.4-1PIGSTY~trixie_arm64.deb
pgedge-18 18.4 u22.x86_64 pigsty 11.9 MiB pgedge-18_18.4-1PIGSTY~jammy_amd64.deb
pgedge-18 18.4 u22.aarch64 pigsty 11.7 MiB pgedge-18_18.4-1PIGSTY~jammy_arm64.deb
pgedge-18 18.4 u24.x86_64 pigsty 11.7 MiB pgedge-18_18.4-1PIGSTY~noble_amd64.deb
pgedge-18 18.4 u24.aarch64 pigsty 11.6 MiB pgedge-18_18.4-1PIGSTY~noble_arm64.deb
pgedge-18 18.4 u26.x86_64 pigsty 11.8 MiB pgedge-18_18.4-1PIGSTY~resolute_amd64.deb
pgedge-18 18.4 u26.aarch64 pigsty 11.5 MiB pgedge-18_18.4-1PIGSTY~resolute_arm64.deb

Source

pig build pkg snowflake;		# build rpm/deb

Install

Make sure PGDG and PIGSTY repo available:

pig repo add pgsql -u   # add both repo and update cache

Install this extension with pig:

pig install snowflake;		# install via package name, for the active PG version

pig install snowflake -v 18;   # install for PG 18
pig install snowflake -v 17;   # install for PG 17
pig install snowflake -v 16;   # install for PG 16
pig install snowflake -v 15;   # install for PG 15

Create this extension with:

CREATE EXTENSION snowflake;

Usage

Sources:

snowflake generates distributed bigint identifiers from a timestamp, a per-node identifier, and an in-millisecond counter. Existing PostgreSQL sequences can be converted so table defaults continue using nextval(...) while producing Snowflake IDs.

CREATE EXTENSION snowflake;

Configuration

Assign every writable node a distinct identifier in postgresql.conf, then reload PostgreSQL:

snowflake.node = 1

Reusing a node identifier on concurrently writable servers can generate duplicate IDs.

Convert a Sequence

Create a normal PostgreSQL sequence, then convert its definition. Existing values in referencing columns are not rewritten.

CREATE TABLE orders (
  id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  payload jsonb NOT NULL
);

SELECT snowflake.convert_sequence_to_snowflake(
  pg_get_serial_sequence('orders', 'id')::regclass
);

INSERT INTO orders (payload) VALUES ('{"status":"new"}');
SELECT id, snowflake.format(id) FROM orders;

Functions

Function Description
snowflake.nextval([sequence regclass]) Generate the next Snowflake ID (uses internal sequence if none specified)
snowflake.currval([sequence regclass]) Return the current value of the sequence
snowflake.get_epoch(snowflake int8) Extract the timestamp as epoch (seconds since 2023-01-01)
snowflake.get_count(snowflake int8) Extract the count part (resets per millisecond)
snowflake.get_node(snowflake int8) Extract the node identifier
snowflake.format(snowflake int8) Return a JSONB with node, ts, and count fields

Examples

-- Generate a snowflake ID
SELECT snowflake.nextval();
-- 136169504773242881

-- Use an already converted named sequence
SELECT snowflake.nextval('orders_id_seq'::regclass);

-- Extract components
SELECT snowflake.get_epoch(136169504773242881);
-- 1704996539.845

SELECT to_timestamp(snowflake.get_epoch(136169504773242881));
-- 2024-01-11 13:08:59.845-05

SELECT snowflake.get_node(136169504773242881);
-- 1

SELECT snowflake.format(136169504773242881);
-- {"id": 1, "ts": "2024-01-11 13:08:59.845-05", "count": 0}

-- Use as default column
CREATE TABLE direct_ids (
  id int8 DEFAULT snowflake.nextval() PRIMARY KEY,
  data text
);

Review and Upgrade

Review converted table defaults with psql \d+ or the PostgreSQL catalogs. They should call snowflake.nextval(...) rather than the original nextval(...):

SELECT table_schema, table_name, column_name, column_default
FROM information_schema.columns
WHERE column_default LIKE 'snowflake.nextval(%';

Version 2.5.0 fixes dump/restore of converted sequences whose MAXVALUE was left at the normal bigint maximum. It also repairs conversion SQL for affected sequences and adds PostgreSQL 18 support.

Caveats

  • Conversion changes the sequence definition, not IDs already stored in table rows.
  • A Snowflake generator can emit at most 4096 counter values per millisecond. Do not configure a sequence increment above 4096.
  • Keep the node identifier stable and unique for the lifetime of concurrent writers; record it as part of cluster provisioning and failover procedures.
  • Install the same extension version on every node before logical replication or rolling changes involving converted sequence definitions.
Last updated on