README.md

# Snowflakex

Snowflakex (pronounced "snowflakes") is a service for generating unique ID
numbers at high scale with some simple guarantees.

It is directly modeled after Twitter's Snowflake specification.

## Requirements

### Performance

* Minimum 10k IDs per second per node
* Response rate <= 2ms

### Uncoordinated

For high availability within and across server application instances, nodes
generating IDs should not have to coordinate with each other.

### (Roughly) Time Ordered

We can guarantee, that the ID numbers will be k-sorted (references:
http://portal.acm.org/citation.cfm?id=70413.70419 and http://portal.acm.org/citation.cfm?id=110778.110783)
within a reasonable bound (we're promising 1s, but shooting for 10's of ms).

### Directly Sortable

The IDs should be sortable without loading the full objects that they represent.
This sorting should be the above ordering.

### Compact

There are many otherwise reasonable solutions to this problem that require
128-bit numbers. To accomodate most systems, we keep our IDs under 64 bits.

### Highly Available

The ID generation scheme should be at least as available as the related services.

## Solution

* The ID numbers are 64-bit integers composed of:
    * Unused sign bit kept at 0
    * Timestamp - 41 bits (millisecond precision with a custom epoch gives us 69 years)
    * Configured machine id - 10 bits - gives us up to 1024 machines
    * Sequence number - 12 bits - rolls over every 4096 per machine (with protection to avoid rollover in the same ms)

## System Clock Dependency

You should use NTP to keep your system clock accurate. Snowflakex protects from
non-monotonic clocks, i.e. clocks that run backwards. If your clock is running
fast and NTP tells it to repeat a few milliseconds, snowflakex will refuse to
generate ids until a time that is after the last time we generated an id. Even
better, run in a mode where ntp won't move the clock backwards. See
http://wiki.dovecot.org/TimeMovedBackwards#Time_synchronization
for tips on how to do this.

## Installation

The package can be installed as:

1. Add `snowflakex` to your list of dependencies in `mix.exs`:

  ```elixir
  def deps do
    [{:snowflakex, "~> 1.1.1"}]
  end
  ```

2. Configure the machine id through your `config.exs`:

  ```elixir
  config :snowflakex, machine_id: 123
  ```

## Usage

The library only offers two simple calls:

```elixir
Snowflakex.new()
```

This call either returns `{:ok, snowflake}` or `{:error, errormessage}` where
the latter only occurs when the system clock moved backwards.

```elixir
Snowflakex.new!()
```

This call will either return the snowflake directly or raise a Snowflakex.ClockError
with the error message and remaining time.