Going to Production

[Edit this page](https://github.com/ClickHouse/clickhouse-docs/blob/main/docs/use-cases/observability/clickstack/managing/production.md)

When deploying ClickStack in production, there are several additional considerations to ensure security, stability, and correct configuration. These vary depending on the distribution - Open Source or Managed - being used.

- Managed ClickStack- ClickStack Open Source

For production deployments, [Managed ClickStack](/docs/use-cases/observability/clickstack/getting-started/managed) is recommended. It applies industry-standard [security practices](/docs/cloud/security) by default - including enhanced encryption, authentication and connectivity, and managed access controls, as well as providing the following benefits:

- Automatic scaling of compute independent of storage
- Low-cost and effectively unlimited retention based on object storage
- The ability to independently isolate read and write workloads with Warehouses.
- Integrated authentication
- Automated [backups](/docs/cloud/features/backups)
- Seamless upgrades

**Follow these [best practices](/docs/cloud/guides/production-readiness) for ClickHouse Cloud when using Managed ClickStack.**

### Secure ingestion[​](#secure-ingestion-managed "Direct link to Secure ingestion")

By default, the ClickStack OpenTelemetry Collector isn't secured when deployed outside of the Open Source distributions and doesn't require authentication on its OTLP ports.

To secure ingestion, specify an authentication token when deploying the collector using the `OTLP_AUTH_TOKEN` environment variable. See ["Securing the collector"](/docs/use-cases/observability/clickstack/ingesting-data/otel-collector#securing-the-collector) for further details.

#### Create an ingestion user[​](#create-a-database-ingestion-user-managed "Direct link to Create an ingestion user")

It's recommended to create a dedicated user for the OTel collector for ingestion into Managed ClickHouse and ensuring ingestion is sent to a specific database e.g. `otel`. See ["Creating an ingestion user"](/docs/use-cases/observability/clickstack/ingesting-data/otel-collector#creating-an-ingestion-user) for further details.

### Configure Time To Live (TTL)[​](#configure-ttl-managed "Direct link to Configure Time To Live (TTL)")

Ensure the [Time To Live (TTL)](/docs/use-cases/observability/clickstack/ttl) has been [appropriately configured](/docs/use-cases/observability/clickstack/ttl#modifying-ttl) for your Managed ClickStack deployment. This controls how long data is retained for - the default of 3 days often needs to be modified.

### Estimating Resources[​](#estimating-resources "Direct link to Estimating Resources")

When deploying **Managed ClickStack**, it is important to provision sufficient compute resources to handle both ingestion and query workloads. The estimates below provide a **baseline starting point** based on the volume of observability data you plan to ingest.

|  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Monthly ingest volume Recommended compute|  |  |  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | < 10 TB / month 2 vCPU × 3 replicas|  |  |  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | --- | --- | | 10–50 TB / month 4 vCPU × 3 replicas|  |  |  |  |  |  | | --- | --- | --- | --- | --- | --- | | 50–100 TB / month 8 vCPU × 3 replicas|  |  |  |  | | --- | --- | --- | --- | | 100–500 TB / month 30 vCPU × 3 replicas|  |  | | --- | --- | | 1 PB+ / month 59 vCPU × 3 replicas | | | | | | | | | | | |

These recommendations are based on the following assumptions:

- Data volume refers to **uncompressed ingest volume** per month and applies to both logs and traces.
- Query patterns are typical for observability use cases, with most queries targeting **recent data**, usually the last 24 hours.
- Ingestion is relatively **uniform across the month**. If you expect bursty traffic or spikes, you should provision additional headroom.
- Storage is handled separately via ClickHouse Cloud object storage and isn't a limiting factor for retention. We assume data retained for longer periods is infrequently accessed.

More compute may be required for access patterns that regularly query longer time ranges, perform heavy aggregations, or support a high number of concurrent users.

Although two replicas can meet the CPU and memory requirements for a given ingestion throughput, we recommend using three replicas where possible to achieve the same total capacity and improve service redundancy.

Note

These values are **estimates only** and should be used as an initial baseline. Actual requirements depend on query complexity, concurrency, retention policies, and variance in ingestion throughput. Always monitor resource usage and scale as needed.

#### Isolating observability workloads[​](#isolating-workloads "Direct link to Isolating observability workloads")

If you're adding ClickStack to an **existing ClickHouse Cloud service** that already supports other workloads, such as real-time application analytics, isolating observability traffic is strongly recommended.

Use [**Managed Warehouses**](/docs/cloud/reference/warehouses) to create a **child service** dedicated to ClickStack. This allows you to:

- Isolate ingest and query load from existing applications
- Scale observability workloads independently
- Prevent observability queries from impacting production analytics
- Share the same underlying datasets across services when needed

This approach ensures your existing workloads remain unaffected while allowing ClickStack to scale independently as observability data grows.

For larger deployments or custom sizing guidance, please contact support for a more precise estimate.

### Network and port security[​](#network-security "Direct link to Network and port security")

By default, Docker Compose exposes ports on the host, making them accessible from outside the container - even if tools like `ufw` (Uncomplicated Firewall) are enabled. This behavior is due to the Docker networking stack, which can bypass host-level firewall rules unless explicitly configured.

**Recommendation:**

Only expose ports that are necessary for production use. Typically the OTLP endpoints, API server, and frontend.

For example, remove or comment out unnecessary port mappings in your `docker-compose.yml` file:

```
ports:
  - "4317:4317"  # OTLP gRPC
  - "4318:4318"  # OTLP HTTP
  - "8080:8080"  # Only if needed for the API
# Avoid exposing internal ports like ClickHouse 8123 or MongoDB 27017.
```

Refer to the [Docker networking documentation](https://docs.docker.com/network/) for details on isolating containers and hardening access.

### Session secret configuration[​](#session-secret "Direct link to Session secret configuration")

In production, you must set a strong, random value for the `EXPRESS_SESSION_SECRET` environment variable for ClickStack UI (HyperDX) - to protect session data and prevent tampering.

Here's how to add it to your `docker-compose.yml` file for the app service:

```
  app:
    image: ${IMAGE_NAME_HDX}:${IMAGE_VERSION}
    ports:
      - ${HYPERDX_API_PORT}:${HYPERDX_API_PORT}
      - ${HYPERDX_APP_PORT}:${HYPERDX_APP_PORT}
    environment:
      FRONTEND_URL: ${HYPERDX_APP_URL}:${HYPERDX_APP_PORT}
      HYPERDX_API_KEY: ${HYPERDX_API_KEY}
      HYPERDX_API_PORT: ${HYPERDX_API_PORT}
      HYPERDX_APP_PORT: ${HYPERDX_APP_PORT}
      HYPERDX_APP_URL: ${HYPERDX_APP_URL}
      HYPERDX_LOG_LEVEL: ${HYPERDX_LOG_LEVEL}
      MINER_API_URL: 'http://miner:5123'
      MONGO_URI: 'mongodb://db:27017/hyperdx'
      NEXT_PUBLIC_SERVER_URL: http://127.0.0.1:${HYPERDX_API_PORT}
      OTEL_SERVICE_NAME: 'hdx-oss-api'
      USAGE_STATS_ENABLED: ${USAGE_STATS_ENABLED:-true}
      EXPRESS_SESSION_SECRET: "super-secure-random-string"
    networks:
      - internal
    depends_on:
      - ch-server
      - db1
```

You can generate a strong secret using `openssl`:

```
openssl rand -hex 32
```