# Connection lifecycle

> How the protocol version is packed and checked, and the login-register handshake that authenticates a connection.

Rendered page: https://iggy.apache.org/docs/binary-protocol/connection-lifecycle/

Source: https://github.com/apache/iggy-website/blob/main/content/docs/binary-protocol/connection-lifecycle.mdx

## Protocol version

The protocol version is a semver packed into one u32, 10 bits per component (each must be below 1024):

```text
bits 31..30  reserved (zero)
bits 29..20  major
bits 19..10  minor
bits  9..0   patch
value = major << 20 | minor << 10 | patch
```

Integer order equals semver order. The value tracks the `iggy_binary_protocol` crate release. Under 0.x the compatibility gate is minor-scoped: the server accepts a client whose packed version is at least the server's minimum and whose `major.minor` is at most the server's. Patch releases never change the wire, so the upper bound ignores patch. Past 1.0.0 the gate follows strict semver (major bump = incompatible).

## Login-register

The only way to authenticate is the register handshake: command code **40** (`LOGIN_REGISTER`, username and password) or **45** (`LOGIN_REGISTER_WITH_PAT`, personal access token). Both ride `operation = 1` (`Register`) with `session = 0` and a freshly minted non-zero `client` id.

Both request bodies begin with the `ClientVersionInfo` prefix, so the server can gate on the version before touching credentials:

```text
[protocol_version: u32]
[sdk_name_len: u8][sdk_name: UTF-8, 1-255 bytes]
[sdk_version_len: u8][sdk_version: UTF-8, 1-255 bytes]
```

`protocol_version` is the packed version of the protocol the client was built against. `sdk_name` identifies the SDK (for example `rust-sdk`, `go-sdk`). `sdk_version` is the SDK's own build version.

After the prefix:

**`LOGIN_REGISTER` (code 40):**

```text
[ClientVersionInfo]
[username_len: u8][username: N]
[password_len: u8][password: N]
[context_len: u32][context: N, only when context_len > 0]
```

**`LOGIN_REGISTER_WITH_PAT` (code 45):**

```text
[ClientVersionInfo]
[token_len: u8][token: N]
[context_len: u32][context: N, only when context_len > 0]
```

An incompatible protocol version is answered with a 256-byte `Eviction` frame, reason `14` (`IncompatibleProtocol`), carrying the accepted window at bytes 144 (max) and 148 (min) as packed u32 versions. A body without a decodable `ClientVersionInfo` prefix gets reason `15` (`MalformedLogin`) with a zero window. Bad credentials get reasons 9-11. See [EvictionHeader](/docs/binary-protocol/framing#evictionheader) for the frame layout.

A successful login is a normal `Reply` whose body is:

```text
[user_id: u32]
[session: u64]
[server_protocol_version: u32]
[server_version_len: u8][server_version: N]
```

The client stores `session` and echoes it in every subsequent request header. Logout is command code **39** (`LOGOUT_USER`), `operation = 3` (`Logout`), empty body.

The legacy login commands **38** (`LOGIN_USER`) and **44** (`LOGIN_WITH_PERSONAL_ACCESS_TOKEN`) are refused: the server answers them with an `Eviction` frame, reason `15` (`MalformedLogin`). Only `PING` is accepted before login. Every other command on an unauthenticated connection is denied.
