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

# Deployment

> Deploy Bridge Hub to production: Docker, Kubernetes, configuration, and troubleshooting.

## Prerequisites

### Infrastructure requirements

Each Bridge Hub component has specific compute requirements:

| Component  | CPU     | RAM  | Notes           |
| ---------- | ------- | ---- | --------------- |
| API        | 2+ vCPU | 4 GB | Per instance    |
| Consumer   | 2+ vCPU | 4 GB | Per network     |
| Auto-Claim | 1+ vCPU | 2 GB | Per destination |

You also need a MongoDB instance (version 4.4 or later). A 3-node replica set is recommended for production, with at least 100 GB of storage that can grow with transaction volume.

### Software requirements

* **Bun** >= 1.0.0
* **MongoDB** >= 4.4
* **Docker** (optional; for containerized deployment)
* **Kubernetes** (optional; for orchestrated deployment)

### External services

* **Bridge Service API** access for each network you plan to index.
* **Blockchain RPC endpoints** from a reliable provider.
* **Sentry account** (optional) for error tracking.

## Build

From the repository root, install dependencies and create production builds:

```bash theme={null}
bun install
bun run build
```

This outputs production artifacts to `packages/api/dist/`, `packages/consumer/dist/`, and `packages/auto-claim/dist/`.

## Docker deployment

The repository includes production-ready Dockerfiles for each service:

* `Dockerfile.api`:API service (exposes port 3001)
* `Dockerfile.consumer`:Consumer service
* `Dockerfile.autoclaim`:Auto-Claim service

Each Dockerfile uses `oven/bun:1.2-alpine` with multi-stage builds and runs as a non-root user (`bunuser`).

### Build images

```bash theme={null}
docker build -f Dockerfile.api -t bridge-hub-api:latest .
docker build -f Dockerfile.consumer -t bridge-hub-consumer:latest .
docker build -f Dockerfile.autoclaim -t bridge-hub-autoclaim:latest .
```

### Docker Compose

Create a `docker-compose.yml` in the repository root:

```yaml theme={null}
version: "3.8"

services:
    mongodb:
        image: mongo:7
        volumes:
            - mongo-data:/data/db
        environment:
            MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
            MONGO_INITDB_ROOT_PASSWORD: ${MONGO_PASSWORD}
        ports:
            - "27017:27017"
        restart: unless-stopped
        networks:
            - bridge-hub

    api:
        build:
            context: .
            dockerfile: Dockerfile.api
        ports:
            - "3001:3001"
        environment:
            NODE_ENV: production
            MONGODB_CONNECTION_URI: ${MONGODB_CONNECTION_URI}
            MONGODB_DB_NAME: ${MONGODB_DB_NAME}
            PROOF_CONFIG: ${PROOF_CONFIG}
            RPC_CONFIG: ${RPC_CONFIG}
            SENTRY_DSN: ${SENTRY_DSN}
        depends_on:
            - mongodb
        restart: unless-stopped
        networks:
            - bridge-hub

    consumer-net1:
        build:
            context: .
            dockerfile: Dockerfile.consumer
        environment:
            NODE_ENV: production
            NETWORK_ID: ${CONSUMER_NETWORK_ID}
            NETWORK: ${CONSUMER_NETWORK}
            BRIDGE_SERVICE_URL: ${BRIDGE_SERVICE_URL}
            BRIDGE_CONTRACT_ADDRESS: ${BRIDGE_CONTRACT_ADDRESS}
            MONGODB_CONNECTION_URI: ${MONGODB_CONNECTION_URI}
            MONGODB_DB_NAME: ${MONGODB_DB_NAME}
            SENTRY_DSN: ${SENTRY_DSN}
        depends_on:
            - mongodb
        restart: unless-stopped
        networks:
            - bridge-hub

    autoclaim:
        build:
            context: .
            dockerfile: Dockerfile.autoclaim
        environment:
            NODE_ENV: production
            BRIDGE_HUB_API_URL: http://api:3001
            SOURCE_NETWORKS: ${SOURCE_NETWORKS}
            DESTINATION_NETWORK: ${DESTINATION_NETWORK}
            DESTINATION_NETWORK_CHAINID: ${DESTINATION_NETWORK_CHAINID}
            BRIDGE_CONTRACT: ${BRIDGE_CONTRACT}
            PRIVATE_KEY: ${PRIVATE_KEY}
            RPC_CONFIG: ${RPC_CONFIG}
            SENTRY_DSN: ${SENTRY_DSN}
        depends_on:
            - api
        restart: unless-stopped
        networks:
            - bridge-hub

volumes:
    mongo-data:

networks:
    bridge-hub:
        driver: bridge
```

### Adding consumer instances for additional networks

To index more than one network, duplicate the `consumer-net1` block with a unique service name and network-specific environment variables. For example:

```yaml theme={null}
consumer-net137:
    build:
        context: .
        dockerfile: Dockerfile.consumer
    environment:
        NETWORK_ID: 137
        NETWORK: mainnet
        BRIDGE_SERVICE_URL: ${BRIDGE_SERVICE_URL_NET137}
        BRIDGE_CONTRACT_ADDRESS: ${BRIDGE_CONTRACT_ADDRESS_NET137}
        MONGODB_CONNECTION_URI: ${MONGODB_CONNECTION_URI}
        MONGODB_DB_NAME: ${MONGODB_DB_NAME}
    depends_on:
        - mongodb
    restart: unless-stopped
    networks:
        - bridge-hub
```

### Common Docker Compose commands

```bash theme={null}
# Start all services in the background
docker-compose up -d

# Follow logs from all services
docker-compose logs -f

# Follow logs from a specific service
docker-compose logs -f api

# Check service status
docker-compose ps

# Restart a single service
docker-compose restart api

# Stop all services
docker-compose down
```

## Kubernetes deployment

### Namespace and ConfigMap

```yaml theme={null}
apiVersion: v1
kind: Namespace
metadata:
    name: bridge-hub
---
apiVersion: v1
kind: ConfigMap
metadata:
    name: bridge-hub-config
    namespace: bridge-hub
data:
    MONGODB_DB_NAME: "bridge_hub"
    NODE_ENV: "production"
```

### API Deployment

```yaml theme={null}
apiVersion: apps/v1
kind: Deployment
metadata:
    name: bridge-hub-api
    namespace: bridge-hub
spec:
    replicas: 3
    selector:
        matchLabels:
            app: bridge-hub-api
    template:
        metadata:
            labels:
                app: bridge-hub-api
        spec:
            containers:
                - name: api
                  image: bridge-hub-api:latest
                  ports:
                      - containerPort: 3000
                  env:
                      - name: MONGODB_CONNECTION_URI
                        valueFrom:
                            secretKeyRef:
                                name: bridge-hub-secrets
                                key: mongodb-uri
                      - name: MONGODB_DB_NAME
                        valueFrom:
                            configMapKeyRef:
                                name: bridge-hub-config
                                key: MONGODB_DB_NAME
                  resources:
                      requests:
                          memory: "2Gi"
                          cpu: "1000m"
                      limits:
                          memory: "4Gi"
                          cpu: "2000m"
                  livenessProbe:
                      httpGet:
                          path: /health
                          port: 3000
                      initialDelaySeconds: 30
                      periodSeconds: 10
                  readinessProbe:
                      httpGet:
                          path: /health
                          port: 3000
                      initialDelaySeconds: 5
                      periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
    name: bridge-hub-api
    namespace: bridge-hub
spec:
    selector:
        app: bridge-hub-api
    ports:
        - port: 80
          targetPort: 3000
    type: LoadBalancer
```

### Apply and manage resources

```bash theme={null}
# Apply all manifests
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secrets.yaml
kubectl apply -f k8s/api-deployment.yaml
kubectl apply -f k8s/consumer-deployment.yaml
kubectl apply -f k8s/auto-claim-deployment.yaml

# Check pod status
kubectl get pods -n bridge-hub

# Follow API logs
kubectl logs -f -n bridge-hub deployment/bridge-hub-api

# Scale the API horizontally
kubectl scale deployment bridge-hub-api --replicas=5 -n bridge-hub
```

## Configuration reference

<Warning>
  Never commit secrets to the repository. Use a secret management system such as AWS Secrets Manager, HashiCorp Vault, or Kubernetes Secrets.
</Warning>

### API package

| Variable                 | Required | Example                           | Description                |
| ------------------------ | -------- | --------------------------------- | -------------------------- |
| `MONGODB_CONNECTION_URI` | Yes      | `mongodb://user:pass@host:27017`  | MongoDB connection string  |
| `MONGODB_DB_NAME`        | Yes      | `bridge_hub`                      | Database name              |
| `RPC_CONFIG`             | Yes      | `{"mainnet":{"1":"https://..."}}` | RPC endpoints by network   |
| `PROOF_CONFIG`           | Yes      | `{"mainnet":{"1":"https://..."}}` | Proof generation endpoints |
| `PORT`                   | No       | `3000`                            | HTTP port (default: 3000)  |
| `NODE_ENV`               | No       | `production`                      | Environment mode           |
| `SENTRY_DSN`             | No       | `https://...@sentry.io/...`       | Error tracking DSN         |

### Consumer package

| Variable                    | Required | Example                                 | Description                           |
| --------------------------- | -------- | --------------------------------------- | ------------------------------------- |
| `NETWORK_ID`                | Yes      | `1`                                     | Network identifier                    |
| `NETWORK`                   | Yes      | `mainnet`                               | Network name (mainnet/testnet/devnet) |
| `BRIDGE_SERVICE_URL`        | Yes      | `https://bridge-api.polygon.technology` | Bridge Service API URL                |
| `BRIDGE_CONTRACT_ADDRESS`   | Yes      | `0x...`                                 | Bridge contract address               |
| `MONGODB_CONNECTION_URI`    | Yes      | `mongodb://user:pass@host:27017`        | MongoDB connection string             |
| `MONGODB_DB_NAME`           | Yes      | `bridge_hub`                            | Database name                         |
| `ETROG_UPDATE_BLOCK_NUMBER` | No       | `0`                                     | Starting block for indexing           |
| `SENTRY_DSN`                | No       | `https://...@sentry.io/...`             | Error tracking DSN                    |

### Auto-Claim package

| Variable                      | Required | Example                     | Description                      |
| ----------------------------- | -------- | --------------------------- | -------------------------------- |
| `BRIDGE_HUB_API_URL`          | Yes      | `http://api:3000`           | Bridge Hub API URL               |
| `SOURCE_NETWORKS`             | Yes      | `[1,137]`                   | Source network IDs (JSON array)  |
| `DESTINATION_NETWORK`         | Yes      | `2442`                      | Destination network ID           |
| `DESTINATION_NETWORK_CHAINID` | Yes      | `2442`                      | Destination chain ID             |
| `BRIDGE_CONTRACT`             | Yes      | `0x...`                     | Bridge contract address          |
| `PRIVATE_KEY`                 | Yes      | `0x...`                     | Wallet private key for gas funds |
| `RPC_CONFIG`                  | Yes      | `{"2442":"https://..."}`    | RPC endpoints (JSON)             |
| `SENTRY_DSN`                  | No       | `https://...@sentry.io/...` | Error tracking DSN               |

## Adding a new network

<Steps>
  <Step title="Deploy a consumer instance">
    Start a new consumer with the network's configuration:

    ```bash theme={null}
    NETWORK_ID=42161 \
    NETWORK=mainnet \
    BRIDGE_CONTRACT_ADDRESS=0x... \
    BRIDGE_SERVICE_URL=https://aggkit-42161.example.com \
    MONGODB_CONNECTION_URI=mongodb://... \
    bun start
    ```

    In Docker Compose, add a new `consumer-net<id>` service block. In Kubernetes, create a new Consumer Deployment manifest.
  </Step>

  <Step title="Update API configuration">
    Add the new network's RPC endpoint to `RPC_CONFIG` and its proof endpoint to `PROOF_CONFIG`, then restart the API instances so they pick up the change.
  </Step>

  <Step title="Update Auto-Claim configuration">
    Append the new network ID to the `SOURCE_NETWORKS` JSON array, then restart Auto-Claim instances.
  </Step>

  <Step title="Verify data flow">
    Confirm the pipeline is working end to end:

    * **Consumer indexing**: Query the MongoDB metadata collection for the new network's checkpoint.
    * **API serving data**: Call `GET /transactions?sourceNetworkIds=42161` and confirm results appear.
    * **Auto-Claim detection**: Monitor Auto-Claim logs to verify it picks up new transactions.
  </Step>
</Steps>

## Troubleshooting

| Symptom                                       | Likely cause                                    | Solution                                                                                                                                                                                                     |
| --------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Services crash with MongoDB connection errors | MongoDB is unreachable or credentials are wrong | Verify MongoDB is running (`mongosh $MONGODB_CONNECTION_URI`). Check network connectivity with `telnet mongo-host 27017`. Review credentials in your environment variables.                                  |
| API queries return no data                    | Consumer is not running or has not indexed yet  | Confirm the Consumer process is active. Check that MongoDB contains documents (`db.transactions.count()`). Review API logs for errors and verify your query parameters.                                      |
| Transactions stuck in `READY_TO_CLAIM`        | Auto-Claim cannot submit transactions           | Check that the wallet has sufficient gas on the destination chain. Verify `BRIDGE_HUB_API_URL` is reachable from the Auto-Claim service. Test RPC endpoint connectivity. Confirm the private key is correct. |
| Excessive memory usage                        | Unbounded batch sizes or tight poll intervals   | Review Consumer batch size settings and increase poll intervals. Add memory limits in Docker or Kubernetes resource specs. Check logs for memory leak indicators.                                            |
