---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://ytsaurus.tech/docs/en/flow/go/examples/external_state_join.md
  - https://ytsaurus.tech/docs/ru/flow/go/examples/external_state_join.md
---
> **Documentation Index:** Fetch the complete configuration index at https://ytsaurus.tech/docs/en/llms.txt

<!-- source: en/_includes/flow/go/examples/external_state_join.md -->
# External State Join in YTsaurus Flow (Go)

An example of a [pipeline](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#pipeline) that enriches events from a queue with data from a read-only external [state](https://ytsaurus.tech/docs/en/flow/concepts/glossary.md#state). The reference table is attached through `TSimpleExternalStateJoiner`, and the Go computation looks a row up by the event key.

[Source code](https://github.com/ytsaurus/ytsaurus/tree/main/yt/yt/flow/examples/go/external_state_join)

## Structure {#structure}

- `event_reader` — a native queue source that publishes the `event` stream.
- `lookup_join` (`lookupJoin`) — a Go transform computation grouped by `key`. It reads `/reference` through `external_state_joiners` and publishes the enriched message to the `enriched` stream.
- A queue sink stores the messages from `enriched`.

The joiner path in the spec may point to a Cypress link. This lets you switch the reference data to a new version of the table atomically, without restarting the pipeline.

## `main.go` {#main-go}

The entry point registers the schemas of the input and output streams, adds the computation, and starts the pipeline.

[Source code: `main.go`](https://github.com/ytsaurus/ytsaurus/tree/main/yt/yt/flow/examples/go/external_state_join/main.go)

{% code '/yt/yt/flow/examples/go/external_state_join/main.go' lang='go' lines='[BEGIN main]-[END main]' %}

## `lookup_join.go` {#lookup-join-go}

The computation decodes the typed input message, reads the joined state row, and creates a typed output message.

[Source code: `lookup_join.go`](https://github.com/ytsaurus/ytsaurus/tree/main/yt/yt/flow/examples/go/external_state_join/lookup_join.go)

{% code '/yt/yt/flow/examples/go/external_state_join/lookup_join.go' lang='go' lines='[BEGIN lookup_join]-[END lookup_join]' %}

## Key patterns {#key-patterns}

- `flow.OpenJoinedExternalState(rt, referenceStateName, msg)` opens the read-only state for the key of the current message.
- `flow.ErrStateNotRead` means that there is no joined row for the key; in this case the example publishes no result.
- `ConvertTo` stays at the SDK boundary: the business logic works with `eventMessage`, `referenceState`, and `enrichedMessage` rather than with raw wire-protocol rows.
- The joined external state isn’t changed from the computation: the `ConvertFrom` method isn’t used for it.
<!-- endsource: en/_includes/flow/go/examples/external_state_join.md -->

<!-- source: en/_includes/flow/go/examples/external_state_join_also.md -->
## See also

- [External State (Go)](https://ytsaurus.tech/docs/en/flow/go/external-state.md)
- [State Accessor (Go)](https://ytsaurus.tech/docs/en/flow/go/state-accessor.md)
- [Static table](https://ytsaurus.tech/docs/en/flow/connectors/static-table.md)
<!-- endsource: en/_includes/flow/go/examples/external_state_join_also.md -->
