> ## Documentation Index
> Fetch the complete documentation index at: https://docs.livepeer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway Architecture

> How gateways fit into the Livepeer stack - layer position, internal components, request flow, system interactions, and the dual video/AI pipeline.

export const ScrollableDiagram = ({children, title = '', maxHeight = '500px', minWidth = '100%', showControls = false, className = '', style = {}, ...rest}) => {
  const buildDiagramKey = (currentTitle = '', currentClassName = '') => {
    const source = `${currentTitle}|${currentClassName}|scrollable-diagram`;
    let hash = 0;
    for (let index = 0; index < source.length; index += 1) {
      hash = hash * 31 + source.charCodeAt(index) >>> 0;
    }
    return `docs-diagram-${hash.toString(36)}`;
  };
  const diagramKey = buildDiagramKey(title, className);
  const zoomName = `${diagramKey}-zoom`;
  const zoomLevels = [{
    label: '75%',
    value: 0.75
  }, {
    label: '100%',
    value: 1
  }, {
    label: '125%',
    value: 1.25
  }, {
    label: '150%',
    value: 1.5
  }];
  const containerStyle = {
    overflow: 'auto',
    maxHeight,
    border: '1px solid var(--lp-color-border-default)',
    borderRadius: "8px",
    padding: "var(--lp-spacing-4)",
    background: 'var(--lp-color-bg-card)',
    position: 'relative'
  };
  return <div className={className} style={{
    position: 'relative',
    marginBottom: "var(--lp-spacing-4)",
    ...style
  }} {...rest}>
      {title && <p style={{
    textAlign: 'center',
    fontStyle: 'italic',
    color: 'var(--lp-color-text-secondary)',
    marginBottom: "var(--lp-spacing-2)",
    fontSize: '0.875rem'
  }}>
          {title}
        </p>}

      {showControls ? <style>{`
          [data-docs-diagram-key="${diagramKey}"] [data-docs-diagram-content] {
            transform: scale(1);
            transform-origin: top left;
            width: max-content;
          }
          ${zoomLevels.map(zoomLevel => `
          #${diagramKey}-${zoomLevel.label.replace('%', '')}:checked ~ [data-docs-diagram-shell] [data-docs-diagram-content] {
            transform: scale(${zoomLevel.value});
          }
          #${diagramKey}-${zoomLevel.label.replace('%', '')}:checked ~ [data-docs-diagram-controls] label[for="${diagramKey}-${zoomLevel.label.replace('%', '')}"] {
            background: var(--lp-color-accent);
            color: var(--lp-color-on-accent);
            border-color: var(--lp-color-accent);
          }`).join('\n')}
        `}</style> : null}

      {showControls ? zoomLevels.map(zoomLevel => {
    const inputId = `${diagramKey}-${zoomLevel.label.replace('%', '')}`;
    return <input key={inputId} id={inputId} type="radio" name={zoomName} defaultChecked={zoomLevel.value === 1} style={{
      position: 'absolute',
      opacity: 0,
      pointerEvents: 'none'
    }} />;
  }) : null}

      <div data-docs-diagram-key={diagramKey} data-docs-diagram-shell style={containerStyle}>
        <div data-docs-diagram-content style={{
    minWidth,
    transformOrigin: 'top left',
    width: 'max-content'
  }}>
          {children}
        </div>
      </div>

      {showControls ? <div data-docs-diagram-controls style={{
    display: 'flex',
    justifyContent: 'flex-end',
    alignItems: 'center',
    gap: "var(--lp-spacing-2)",
    marginTop: "var(--lp-spacing-2)",
    flexWrap: 'wrap'
  }}>
          <span style={{
    fontSize: "0.75rem",
    color: 'var(--lp-color-text-muted)',
    marginRight: 'auto'
  }}>
            Scroll to pan
          </span>
          {zoomLevels.map(zoomLevel => {
    const inputId = `${diagramKey}-${zoomLevel.label.replace('%', '')}`;
    return <label key={inputId} htmlFor={inputId} style={{
      background: 'transparent',
      color: 'var(--lp-color-text-secondary)',
      border: '1px solid var(--lp-color-border-default)',
      borderRadius: "4px",
      padding: '4px 10px',
      cursor: 'pointer',
      fontSize: "0.75rem",
      fontWeight: '600'
    }}>
                {zoomLevel.label}
              </label>;
  })}
        </div> : null}
    </div>;
};

export const CustomDivider = ({color = "var(--lp-color-border-default)", middleText = "", spacing = "default", style = {}, className = "", ...rest}) => {
  const spacingPresets = {
    default: {
      margin: "24px 0"
    },
    overlap: {
      margin: "-1rem 0 -1rem 0"
    },
    tight: {
      margin: "0 0 -1rem 0"
    },
    section: {
      margin: "0 0 -2rem 0"
    },
    sectionOverlap: {
      margin: "-1rem 0 -2rem 0"
    },
    deepOverlap: {
      margin: "-1rem 0 -1.5rem 0"
    }
  };
  const spacingStyle = spacingPresets[spacing] || spacingPresets.default;
  return <div role="separator" aria-orientation="horizontal" className={className} style={{
    display: "flex",
    alignItems: "center",
    ...spacingStyle,
    fontSize: style?.fontSize || "16px",
    height: "fit-content",
    ...style
  }} {...rest}>
      <span style={{
    marginRight: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
      </span>
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      {middleText && <>
          <Icon icon="circle" size={2} />
          <span style={{
    margin: "0 8px",
    fontWeight: "bold",
    color: color,
    opacity: 0.7
  }}>
            {middleText}
          </span>
          <Icon icon="circle" size={2} />
        </>}
      <div style={{
    flex: 1,
    height: "1px",
    background: "var(--lp-color-border-default)",
    opacity: 0.4
  }}></div>
      <span style={{
    marginLeft: "var(--lp-spacing-px-8)",
    opacity: 0.2
  }}>
        <span style={{
    display: "inline-block",
    transform: "scaleX(-1)"
  }}>
          <Icon icon="/snippets/assets/logos/Livepeer-Logo-Symbol-Theme.svg" />
        </span>
      </span>
    </div>;
};

export const TableCell = ({children, align = "left", header = false, style = {}, className = "", ...rest}) => {
  const Component = header ? "th" : "td";
  return <Component className={className} style={{
    padding: "0.75rem 1rem",
    textAlign: align,
    border: header ? "none" : "1px solid var(--lp-color-border-default)",
    ...style
  }} {...rest}>
      {children}
    </Component>;
};

export const TableRow = ({children, header = false, hover = false, style = {}, className = "", ...rest}) => {
  const rowId = `table-row-${Math.random().toString(36).substr(2, 9)}`;
  return <>
      {hover && <style>{`
          #${rowId}:hover {
            background-color: var(--lp-color-bg-card);
          }
        `}</style>}
      <tr id={rowId} className={className} style={{
    ...header && ({
      backgroundColor: "var(--lp-color-accent-strong)",
      color: "var(--lp-color-on-accent)",
      fontWeight: "bold"
    }),
    ...style
  }} {...rest}>
        {children}
      </tr>
    </>;
};

export const StyledTable = ({children, variant = "default", style = {}, className = "", ...rest}) => {
  const wrapperVariants = {
    default: {
      border: "1px solid var(--lp-color-border-default)",
      backgroundColor: "var(--lp-color-bg-card)",
      overflow: "hidden"
    },
    bordered: {
      border: "2px solid var(--lp-color-accent)",
      backgroundColor: "var(--lp-color-bg-page)",
      overflow: "hidden"
    },
    minimal: {
      border: "none",
      backgroundColor: "transparent",
      overflow: "visible"
    }
  };
  return <div data-docs-styled-table-shell className={className} style={{
    width: "100%",
    padding: 0,
    margin: 0,
    ...wrapperVariants[variant],
    ...style
  }} {...rest}>
      <table data-docs-styled-table style={{
    width: "100%",
    borderCollapse: "collapse",
    borderSpacing: 0,
    margin: 0,
    backgroundColor: "transparent"
  }}>
        {children}
      </table>
    </div>;
};

export const LinkArrow = ({href, label, description, newline = true, borderColor, className = '', style = {}, ...rest}) => {
  const linkArrowStyle = {
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: "var(--lp-spacing-1)",
    width: 'fit-content',
    ...borderColor && ({
      borderColor
    })
  };
  return <span className={className} style={style} {...rest}>
      {newline && <br />}
      <span style={linkArrowStyle}>
        <a href={href} target="_blank" rel="noopener noreferrer">
          {label}
        </a>
        <Icon icon="arrow-up-right" size={14} color="var(--lp-color-accent)" />
      </span>
      {description && description}
      {description && <div style={{
    height: "var(--lp-spacing-3)"
  }} />}
    </span>;
};

Gateways sit at the application layer of Livepeer. They accept requests from apps, route them to Orchestrators, and coordinate payment and failover across the compute and protocol layers.

For what Gateways *do*, see [Capabilities](/v2/Gateways/concepts/capabilities). For why you would run one, see [Business Model](/v2/Gateways/concepts/business-model).

<CustomDivider />

## Gateway Layer Context

The Livepeer Network has three functional layers. Gateways operate at the **application layer**, bridging end-user applications and the compute layer where Orchestrators run GPU workloads.

<ScrollableDiagram title="Layered Architecture" maxHeight="600px">
  ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
  graph LR
      classDef default stroke-width:2px
      subgraph APP[Application Layer]
          X["User App<br/>Web, Mobile, TouchDesigner"]
      end
      subgraph GW[Gateway Layer]
          G1[Job Intake]
          G2[Capability Discovery]
          G3[Pricing & Selection]
          G4[Routing / Session Mgmt]
      end
      subgraph ORC[Orchestrator Layer]
          O1[GPU Worker]
          O2[AI Models / BYOC Containers]
          O3[Transcoder]
      end
      X --> G1
      G1 --> O1
      O1 --> G1
      G1 --> X
  ```
</ScrollableDiagram>

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell>Layer</TableCell>
    <TableCell>Participants</TableCell>
    <TableCell>Responsibility</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Application**</TableCell>
    <TableCell>Developers, end users, Gateways</TableCell>
    <TableCell>Ingest requests, route jobs, deliver results, manage pricing</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Compute**</TableCell>
    <TableCell>Orchestrators, transcoders, AI runners</TableCell>
    <TableCell>Execute video and AI work on GPUs</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Protocol**</TableCell>
    <TableCell>Arbitrum smart contracts</TableCell>
    <TableCell>Staking, payments, governance, Orchestrator registry</TableCell>
  </TableRow>
</StyledTable>

Gateways are the only demand-side participants that interact with both the compute layer (sending jobs to Orchestrators) and the protocol layer (payment tickets, Orchestrator discovery via the on-chain registry).

<CustomDivider />

## Gateway Interactions

A Gateway interacts with four categories of actors:

### Applications

Applications are the Gateway's customers. They send workloads and receive results.

* Video applications send RTMP streams (port 1935) and receive HLS/DASH output
* AI applications send HTTP requests (port 8935, enabled via `-httpIngest`) and receive JSON/binary inference results
* BYOC applications send custom payloads via HTTP and receive container output

The Gateway abstracts orchestration and protocol details for applications. Applications send workloads and receive results through Gateway interfaces.

### Orchestrators

Orchestrators are the supply side. The Gateway selects, negotiates with, and dispatches work to them.

* **Discovery** - on-chain Gateways query the ServiceRegistry contract on Arbitrum; off-chain Gateways receive Orchestrator lists from the remote signer
* **Negotiation** - the Gateway requests an Orchestrator's capabilities and price, then establishes a session with an acceptable Orchestrator
* **Dispatch** - video segments or AI requests are sent to the Orchestrator with an attached payment ticket
* **Failover** - on failure, the Gateway retries with the next-best option from its ranked list

### Remote Signer

In the **off-chain operational mode**, the Gateway delegates all payment operations to a **remote signer** service. The remote signer:

* Holds the ETH deposit and reserve
* Generates probabilistic micropayment tickets on the Gateway's behalf
* Provides Orchestrator discovery (list of known Orchestrators)
* Handles all on-chain interactions (ticket redemption is on the Orchestrator side)

This architecture allows Gateways to operate with zero crypto knowledge and zero ETH. See <LinkArrow href="/v2/gateways/guides/payments-and-pricing/remote-signers" label="Remote Signers" newline={false} /> for the full protocol.

### Arbitrum Protocol

In the **on-chain operational mode**, the Gateway interacts directly with Arbitrum smart contracts:

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell>Contract</TableCell>
    <TableCell>Gateway interaction</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**TicketBroker**</TableCell>
    <TableCell>Fund deposit and reserve; generate payment tickets for Orchestrators</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**ServiceRegistry**</TableCell>
    <TableCell>Query registered Orchestrators and their service URIs</TableCell>
  </TableRow>
</StyledTable>

<Note>
  Gateways interact with TicketBroker and ServiceRegistry. Orchestrators handle BondingManager, RoundsManager, and Governance interactions.
</Note>

<CustomDivider />

## Dual Pipeline Architecture

The Gateway node (`LivepeerNode` in go-livepeer) runs two independent session managers - one for video, one for AI. This allows a single Gateway to handle both workload types simultaneously without interference.

<ScrollableDiagram title="Dual Gateway Architecture: Video & AI Pipelines" maxHeight="800px">
  ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
  flowchart TB
      subgraph INPUT["Input Sources"]
          direction LR
          RTMP["RTMP Stream"]
          HTTP["HTTP Upload"]
          AI_REQ["AI Request"]
      end

      GATEWAY["Gateway Node<br/>LivepeerNode"]

      INPUT --> GATEWAY

      subgraph MANAGERS["Session Managers"]
          direction LR
          BSM["BroadcastSessionsManager<br/>Video Transcoding"]
          ASM["AISessionManager<br/>AI Processing"]
      end

      GATEWAY --> BSM
      GATEWAY --> ASM

      subgraph VIDEO["Video Pipeline"]
          SEG["Segment Processing"]
          ORCH_V["Orchestrators<br/>Transcoding"]
          HLS["HLS/DASH Output"]
      end

      subgraph AI["AI Pipeline"]
          PROC["AI Processing"]
          ORCH_AI["Orchestrators<br/>AI Models"]
          OUT_AI["AI Output<br/>Images/Video"]
      end

      BSM --> SEG --> ORCH_V --> HLS
      ASM --> PROC --> ORCH_AI --> OUT_AI

      subgraph PAYMENT["Payment"]
          direction LR
          PAY_SEG["Per Segment"]
          PAY_PIX["Per Pixel"]
      end

      ORCH_V --> PAY_SEG
      ORCH_AI --> PAY_PIX

      classDef default fill:#1a1a1a,color:#fff,stroke:#2d9a67,stroke-width:2px
      classDef video fill:#1a1a1a,color:#fff,stroke:#3b82f6,stroke-width:2px
      classDef ai fill:#1a1a1a,color:#fff,stroke:#a855f7,stroke-width:2px
      class RTMP,HTTP,BSM,SEG,ORCH_V,HLS,PAY_SEG video
      class AI_REQ,ASM,PROC,ORCH_AI,OUT_AI,PAY_PIX ai
      style INPUT fill:#0d0d0d,stroke:#2d9a67,stroke-width:1px
      style MANAGERS fill:#0d0d0d,stroke:#2d9a67,stroke-width:1px
      style VIDEO fill:#0d0d0d,stroke:#3b82f6,stroke-width:1px
      style AI fill:#0d0d0d,stroke:#a855f7,stroke-width:1px
      style PAYMENT fill:#0d0d0d,stroke:#2d9a67,stroke-width:1px
  ```
</ScrollableDiagram>

### Video vs AI Pipelines

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell>Aspect</TableCell>
    <TableCell>Video pipeline (blue)</TableCell>
    <TableCell>AI pipeline (purple)</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Session manager**</TableCell>
    <TableCell>`BroadcastSessionsManager`</TableCell>
    <TableCell>`AISessionManager`</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Input**</TableCell>
    <TableCell>RTMP stream segmented into chunks</TableCell>
    <TableCell>HTTP request with prompt/image/audio</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Orchestrator work**</TableCell>
    <TableCell>Transcode each segment to output profiles</TableCell>
    <TableCell>Run inference model, return result</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Output**</TableCell>
    <TableCell>HLS/DASH stream</TableCell>
    <TableCell>JSON (text), image, video clip, or audio</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Payment unit**</TableCell>
    <TableCell>Wei per pixel (per segment)</TableCell>
    <TableCell>Wei per pixel or per millisecond</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**Session duration**</TableCell>
    <TableCell>Long-lived (entire stream)</TableCell>
    <TableCell>Short-lived (single request or batch)</TableCell>
  </TableRow>
</StyledTable>

Both pipelines share the same Orchestrator selection logic, payment system, and failover behaviour. The separation is at the session management layer.

<CustomDivider />

## Job Lifecycle

This is what happens when an application sends a request to a Gateway, from intake through result delivery and payment.

<ScrollableDiagram title="Gateway Request Flow" maxHeight="600px">
  ```mermaid theme={"theme":{"light":"github-light","dark":"dark-plus"}}
  %%{init: {'theme': 'base', 'themeVariables': {'primaryColor': '#18794E', 'primaryTextColor': '#fff', 'primaryBorderColor': '#3CB540', 'lineColor': '#3CB540', 'mainBkg': '#18794E', 'nodeBorder': '#3CB540', 'clusterBkg': 'transparent', 'clusterBorder': '#3CB540', 'titleColor': '#3CB540', 'edgeLabelBackground': 'transparent', 'textColor': '#3CB540', 'nodeTextColor': '#fff'}}}%%
  graph TD
      classDef default stroke-width:2px
      A["Application<br/>Daydream, ComfyUI, BYOC"] -->|Job Request| B["Gateway<br/>Job Intake, Pricing, Capability Match"]
      B -->|Route Job| C["Orchestrator<br/>GPU Compute, AI Inference, Transcoding"]
      C -->|Results| B
      B -->|Response| A
  ```
</ScrollableDiagram>

### Lifecycle Steps

1. **Job arrives** - An application sends a video segment (RTMP) or AI request (HTTP) to the Gateway.
2. **Pipeline routing** - The Gateway routes the request to the appropriate session manager (`BroadcastSessionsManager` for video, `AISessionManager` for AI).
3. **Orchestrator selection** - The session manager selects the best Orchestrator from its pool based on capability, price, latency, and performance history.
4. **Payment ticket generation** - The Gateway (or remote signer in off-chain mode) generates a probabilistic micropayment ticket and attaches it to the job.
5. **Work dispatch** - The job + ticket are sent to the Orchestrator over HTTP.
6. **Execution** - The Orchestrator routes the work to its GPU worker (transcoder for video, AI Runner for inference) and returns the result.
7. **Result delivery** - The Gateway sends the processed output back to the application.
8. **Payment settlement** - The Orchestrator accumulates payment tickets and periodically redeems winning tickets on Arbitrum for ETH.

<CustomDivider />

## Software Components

### go-livepeer

The core node software. When started in Gateway mode (`-gateway`), it runs as the Gateway controller. Handles:

* Job intake (RTMP server + HTTP API server)
* Orchestrator discovery and session management
* Payment ticket generation (on-chain operational mode) or remote signer communication (off-chain operational mode)
* Prometheus metrics (port 7935)

Source: [github.com/livepeer/go-livepeer](https://github.com/livepeer/go-livepeer) - specifically [core/livepeernode.go](https://github.com/livepeer/go-livepeer/blob/5691cb48/core/livepeernode.go)

<Note>
  The Gateway was previously called the **broadcaster**. Legacy CLI flags still use `-broadcaster` in some contexts. The `-gateway` flag is the current standard.
</Note>

### livepeer\_cli

A command-line tool that connects to a running go-livepeer node. Used for:

* Setting broadcast configuration (max price, transcoding profiles)
* Funding the on-chain deposit and reserve
* Viewing node status and connected Orchestrators

### Remote Signer (off-chain)

A separate service that handles ETH custody and payment ticket signing for off-chain Gateways. It runs as a sidecar or external service alongside go-livepeer.

See <LinkArrow href="/v2/gateways/guides/payments-and-pricing/remote-signers" label="Remote Signers" newline={false} /> for architecture and configuration.

### Arbitrum Contracts (on-chain)

<StyledTable variant="bordered">
  <TableRow header>
    <TableCell>Contract</TableCell>
    <TableCell>Gateway use</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**TicketBroker**</TableCell>
    <TableCell>Deposit ETH, manage reserve, generate payment tickets</TableCell>
  </TableRow>

  <TableRow>
    <TableCell>**ServiceRegistry**</TableCell>
    <TableCell>Discover registered Orchestrators</TableCell>
  </TableRow>
</StyledTable>

See <LinkArrow href="/v2/gateways/resources/reference/technical/contract-addresses" label="Contract Addresses" newline={false} /> for deployed addresses.

<CustomDivider />

## Related Pages

<CardGroup cols={2}>
  <Card title="Gateway Role" icon="user-gear" href="/v2/gateways/concepts/role" arrow horizontal>
    What Gateways are and how the role has evolved.
  </Card>

  <Card title="Gateway Capabilities" icon="gears" href="/v2/gateways/concepts/capabilities" arrow horizontal>
    Workload types, Orchestrator selection, and session management.
  </Card>

  <Card title="Gateway Business Model" icon="chart-line" href="/v2/gateways/concepts/business-model" arrow horizontal>
    Revenue models, cost structures, and pricing.
  </Card>

  <Card title="Payment System" icon="credit-card" href="/v2/gateways/guides/payments-and-pricing/payment-guide" arrow horizontal>
    How Probabilistic Micropayments work.
  </Card>
</CardGroup>
