Before you begin: Complete Build a gRPC RTD service. Also read the Publisher request payload reference, and the DSP bid response payload reference if you are implementing bid shading, to understand which signals are available to your decisioning logic.
This topic covers packaging your gRPC service as a Docker container that meets Index Cloud's requirements. Read the constraints below carefully before making language or architecture decisions, particularly the no-egress requirement and security constraints, which have significant implications for how you structure your service.
Networking and security constraints
The following constraints are enforced by Index Cloud and cannot be changed. They affect both how you write your GetMutations implementation and how you package your container, so read them before writing any code.
No egress. Your container cannot make outbound network calls at runtime. Ingress to your container is only available within Index Cloud. All data (model weights, lookup tables, configuration) must be embedded in the image or mounted via config file at startup. Any architecture that relies on external API calls or database lookups during request handling will not work.
Read-only filesystem. Your container runs with a read-only filesystem.
Non-root execution. Containers run as user 1000, group 1000. Ensure your base image and entrypoint are compatible.
Vulnerability scanning. All images are scanned on download and on an ongoing basis. A CVSS score of 9 or higher blocks deployment. Choose base images carefully.
Cryptographically signed code. Containers run in isolated environments per partner.
Config files. These are mountable in TOML format at your preferred path.
Model data. This is mounted at
MODEL_PATH. See Environment variables.
Logging
Logs from your container should be written to STDOUT or STDERR, as appropriate. Index Exchange (Index) collects these logs and reserves the right to decide what log information to make available to you.
Note: Prefer metrics over verbose logging. Use metrics, not logs, to capture container performance.
Recommended base images
Choose a minimal base image to keep your image under 1 GiB and reduce vulnerability surface. Recommended options are gcr.io/distroless/base-nossl (Go, Rust) and alpine:latest. Avoid full OS images such as ubuntu or debian unless necessary, because these are more likely to contain packages with a CVSS score of 9 or higher that would block deployment. Ensure the base image is compatible with non-root execution (user 1000, group 1000) and x86 architecture.
Container resource profile
Your container must meet the following requirements:
| Requirement | Specification |
|---|---|
Architecture | x86 |
Max image size | 1 GiB |
Max model data size | 5 GiB |
Response SLA | 5ms (95th percentile) |
Max error rate | < 3% |
Required endpoints
Containers must expose the endpoints described below. GRPC_PORT is used for the gRPC service and the required gRPC healthcheck protocol. SERVER_PORT is used for the required HTTP metrics endpoint
A URL which is configured to interact with a server in a specific way..
Orchestration endpoints
Containers MUST implement the gRPC healthcheck protocol (grpc.health.v1.Health) on GRPC_PORT. Index and the testing tool probe this endpoint.
Liveness SHOULD report
SERVINGwhile the main thread is running, andNOT_SERVINGotherwise.Readiness SHOULD report
SERVINGonly once the application, including model load, is ready to serve traffic, andNOT_SERVINGotherwise.
Metrics endpoint
Containers MUST expose an HTTP metrics endpoint at /metrics, which provides runtime metrics in Prometheus format. See Validating and deploying your container for the required metric, permitted tags, and an example response.
Environment variables
Index sets the following environment variables in your container at runtime. Do not hardcode these values. Read them from the environment at startup.
| Variable | Description |
|---|---|
| Port for your container's HTTP metrics endpoint ( |
| Port your gRPC service listens on. Set by Index at container start. Default: 50051. |
| Directory where model data files are mounted. Your container reads model files from here at startup. Ensure this directory exists. Create it with |
Usage examples
The following examples show how to read these variables at startup.
Go
grpcPort := os.Getenv("GRPC_PORT")
if grpcPort == "" { grpcPort = "50051" }
serverPort := os.Getenv("SERVER_PORT")
modelPath := os.Getenv("MODEL_PATH")Rust
let grpc_port = std::env::var("GRPC_PORT").unwrap_or("50051".into());
let server_port = std::env::var("SERVER_PORT").expect("SERVER_PORT must be set");
let model_path = std::env::var("MODEL_PATH").unwrap_or("/models".into());Recommended languages
The following table summarizes how each language performs against the latency profile this integration requires:
| Language | Recommendation | Notes |
|---|---|---|
Rust | Recommended | Best raw throughput. No GC pauses, predictable latency. Maximizes QPS |
Go | Recommended | Strong concurrency model, excellent gRPC ecosystem. ARTF reference implementations are in Go and Rust. |
C++, Java | Use with care | Require more care around latency consistency. |
Python | Not recommended | Difficult to meet the 5ms latency requirement without offloading request processing to native code. |
The ARTF reference implementations are available at github.com/IABTechLab/agentic-rtb-framework.
Architectural patterns
Apply the following patterns when structuring your service.
Do
Pre-load at startup. All data should be integrated into the image or loaded from mounted files at boot. Only signal readiness once everything is fully loaded.
Cache aggressively. Use memory for lookup tables, model weights, and pre-computed decisions.
Minimize per-request allocation. Object pooling, pre-allocated buffers, and arena patterns reduce GC pressure (Go) and allocation overhead (Rust).
Keep the gRPC handler minimal. Deserialize, run logic, build mutations, return. Log and aggregate telemetry asynchronously.
Design for graceful restarts. Signal readiness only once the model is fully loaded.
Don't
Make external network calls during request handling.
Use heavy per-request logging. Use metrics counters instead.
Load models dynamically after startup.
Ship large images built from unnecessary dependencies.
Next: Continue to Validating and deploying your container to begin the deployment process.