RTB Architecture
Prebid Server on AWS and Docker: A Reference Setup for ECS and EKS
Published · Last updated
Next scheduled review:
To run Prebid Server on AWS, package it as a container, put it behind an Application Load Balancer and run replicas on ECS Fargate or EKS. Keep state outside the container: Prebid Cache, the stored-request database and metrics. PBS-Go ships an official Docker image, PBS-Java publishes images on GitHub, and AWS maintains an open-source reference deployment.
Key terms on this page: Prebid Server · stored request · QPS · p99 latency · timeout · data residency
Contents
Key facts
- Official images exist for both builds. PBS-Go publishes
prebid/prebid-serveron Docker Hub, with tagv4.11.1pushed on 2 November 2026 for amd64 only (Docker Hub, accessed 9 November 2026). PBS-Java has published images on GitHub Packages since version 3.11.0 (PBS-Java README). - The ports differ. PBS-Go listens on 8000 with an admin port on 6060; PBS-Java uses 8080 and 8060 (PBS-Go Dockerfile; PBS-Java Dockerfile, both accessed 9 November 2026).
- AWS publishes a reference deployment. Version 1.4.0 of the Guidance for Deploying a Prebid Server on AWS was released on 12 June 2026. It runs PBS-Java 3.43.0 on ECS Fargate in 2 vCPU, 4 GB tasks behind CloudFront, AWS WAF and an ALB (AWS changelog; stack_constants.py).
- Containers start slowly. AWS measured an average PBS-Java startup of 55.74 seconds and a p95 of 69.54 seconds in its logs, and set a 100-second scale-in cooldown from that (stack_constants.py).
- Default health checks fail. With no status message configured,
/statusreturns HTTP 204 in both builds, while an ALB target group expects 200 by default (status.go; PBS-Java config-app.md; AWS ALB health checks).
Definition
Containerised Prebid Server deployment: a setup in which Prebid Server runs as identical, stateless container replicas behind a load balancer. Everything that must persist, such as stored requests, account settings, cached bids and metrics, lives in services outside the container. Instances can then be added, replaced or rolled back without losing data.
Prebid's hosting guide describes the same split in hardware terms: load balancers, Prebid Server nodes, Prebid Cache nodes, a NoSQL cluster, a replicated database and a metrics system (Prebid Server hosting, accessed 9 November 2026). The decision to host at all, the multi-region layout and the cost worksheet are in our Prebid Server self-hosting guide. This page is the container and AWS layer underneath it.
Why owning that layer matters is argued on our publisher independence hub. The build-or-rent trade-off is summarised in the self-hosted Prebid Server profile, and the rental side in the profiles of Magnite Prebid Server and PubMatic OpenWrap. Where the server sits in a header bidding setup is explained in header bidding explained.
Pick an image
7 of 7 rows
Registry | Docker Hub | GHCR | Docker Hub |
Latest tag (date) |
|
|
|
Base image |
|
| n/d |
App and admin ports | 8000, 6060 | 8080, 8060 | 2424, 2525 |
Runs as | non-root user | n/d in Dockerfile | n/d |
Config | env vars | Spring Boot: | env vars |
Architectures published | amd64 | n/d | amd64 |
Registry
- PBS-Go
Docker Hub
prebid/prebid-server- PBS-Java
GHCR
prebid-server-java,prebid-server-java-bundle(with modules)- Prebid Cache (Go)
Docker Hub
prebid/prebid-cache
Latest tag (date)
- PBS-Go
v4.11.1(2 Nov 2026)- PBS-Java
4.5.0release (4 Nov 2026)- Prebid Cache (Go)
v0.30.0(8 May 2025)
Base image
- PBS-Go
ubuntu:22.04- PBS-Java
amazoncorretto:25.0.5-al2023-headless- Prebid Cache (Go)
n/d
App and admin ports
- PBS-Go
8000, 6060
- PBS-Java
8080, 8060
- Prebid Cache (Go)
2424, 2525
Runs as
- PBS-Go
non-root user
prebid(UID 1001)- PBS-Java
n/d in Dockerfile
- Prebid Cache (Go)
n/d
Config
- PBS-Go
env vars
PBS_*, thenpbs.json, thenpbs.yaml, from the app directory or/etc/config- PBS-Java
Spring Boot:
application.yamlin/app/prebid-server/conf/, or--spring.config.additional-location- Prebid Cache (Go)
env vars
PBC_*orconfig.yaml
Architectures published
- PBS-Go
amd64
- PBS-Java
n/d
- Prebid Cache (Go)
amd64
Table by AdSovereign, CC BY 4.0.
Sources: PBS-Go Dockerfile, configuration.md, PBS-Java Dockerfile and README, Prebid Cache README, and Docker Hub tag data, all accessed 9 November 2026.
Two details catch teams out. The PBS-Go image needs its static/ directory at startup, which the official image already contains (PBS-Go README). And the PBS-Go Dockerfile downloads an amd64 Go toolchain, while the README builds with --platform linux/amd64. Running on AWS Graviton (arm64) therefore needs a build you change and test yourself.
Run the stack locally with Docker Compose
This Compose file starts PBS-Go, Prebid Cache and Redis for development. Prebid Cache's default in-memory backend has no TTL expiry and is not meant for production, so the file switches it to Redis (Prebid Cache README).
# compose.yaml: local reference stack (not for production)
services:
pbs:
image: prebid/prebid-server:v4.11.1
platform: linux/amd64
ports:
- "8000:8000" # auction, /cookie_sync, /setuid, /status
- "6060:6060" # admin port; never expose publicly
environment:
PBS_EXTERNAL_URL: "http://localhost:8000"
PBS_STATUS_RESPONSE: "ok" # /status returns 200 "ok" instead of 204
PBS_GDPR_DEFAULT_VALUE: "1" # required; no default
PBS_CACHE_SCHEME: "http"
PBS_CACHE_HOST: "localhost:2424" # the address browsers will use for cached bids
PBS_CACHE_QUERY: "uuid=%PBS_CACHE_UUID%"
PBS_STORED_REQUESTS_FILESYSTEM_ENABLED: "true"
volumes:
- ./stored_requests:/usr/local/bin/stored_requests/data/by_id:ro
depends_on:
- prebid-cache
prebid-cache:
image: prebid/prebid-cache:v0.30.0
platform: linux/amd64
ports:
- "2424:2424"
environment:
PBC_BACKEND_TYPE: "redis"
PBC_BACKEND_REDIS_HOST: "redis"
PBC_BACKEND_REDIS_PORT: "6379"
PBC_BACKEND_REDIS_EXPIRATION: "10" # minutes
depends_on:
- redis
redis:
image: redis:6.2-alpineThe environment names follow each project's rule: a prefix, then the YAML path with dots turned into underscores (PBS-Go config.go; Prebid Cache config.go). The mounted folder must contain stored_requests/, stored_imps/ and accounts/ subfolders, as described in Prebid Server stored requests. Prebid's own sample, sample/docker-compose.yml, builds the image from source instead and serves a test page at /static/pbjs.html?pbjs_debug=true (PBS-Go sample). The page side of that test is explained in our Prebid.js guide.
For PBS-Java, mount a config file and pass its path. The README's example is docker run --rm -v ./sample:/app/prebid-server/sample:ro -p 8060:8060 -p 8080:8080 ghcr.io/prebid/prebid-server-java:latest --spring.config.additional-location=sample/configs/prebid-config.yaml (PBS-Java README). In production, pin a version tag instead of latest.
A reference topology on ECS Fargate
ECS on Fargate is the shortest path on AWS: no nodes to patch, per-task networking and native ALB integration. It is also what AWS chose for its own guidance. The topology below keeps AWS's front door and swaps in the parts a production publisher usually needs.
The ALB rule split comes straight from Prebid's guidance: requests for /cache go to Prebid Cache, everything else to Prebid Server (Prebid Server hosting). Prebid also says neither service is meant to hold an SSL certificate, so terminate TLS at the load balancer. PBS-Java does offer server.ssl with a Java keystore, and AWS's guidance uses HTTPS on port 8443 between the ALB and its containers (config-app.md; stack_constants.py).
An annotated ECS task definition
This task definition runs PBS-Go on Fargate with secrets from AWS Secrets Manager. Account IDs, ARNs and hostnames are placeholders. The field names follow the ECS task definition reference (AWS, task definition parameters; AWS, passing secrets).
{
"family": "prebid-server",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "2048",
"memory": "4096",
"runtimePlatform": { "cpuArchitecture": "X86_64", "operatingSystemFamily": "LINUX" },
"executionRoleArn": "arn:aws:iam::123456789012:role/pbsTaskExecutionRole",
"containerDefinitions": [
{
"name": "prebid-server",
"image": "123456789012.dkr.ecr.eu-west-1.amazonaws.com/prebid-server:v4.11.1",
"essential": true,
"portMappings": [
{ "containerPort": 8000, "protocol": "tcp" },
{ "containerPort": 9100, "protocol": "tcp" }
],
"environment": [
{ "name": "PBS_EXTERNAL_URL", "value": "https://pbs.example.com" },
{ "name": "PBS_STATUS_RESPONSE", "value": "ok" },
{ "name": "PBS_GDPR_DEFAULT_VALUE", "value": "1" },
{ "name": "PBS_METRICS_PROMETHEUS_PORT", "value": "9100" },
{ "name": "PBS_CACHE_SCHEME", "value": "https" },
{ "name": "PBS_CACHE_HOST", "value": "pbs.example.com" },
{ "name": "PBS_CACHE_QUERY", "value": "uuid=%PBS_CACHE_UUID%" },
{ "name": "PBS_STORED_REQUESTS_DATABASE_CONNECTION_DRIVER", "value": "postgres" },
{ "name": "PBS_STORED_REQUESTS_DATABASE_CONNECTION_HOST", "value": "pbs-db-replica.internal.example.com" },
{ "name": "PBS_STORED_REQUESTS_DATABASE_CONNECTION_DBNAME", "value": "pbs" },
{ "name": "PBS_STORED_REQUESTS_DATABASE_CONNECTION_USER", "value": "pbs_reader" }
],
"secrets": [
{
"name": "PBS_STORED_REQUESTS_DATABASE_CONNECTION_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:eu-west-1:123456789012:secret:pbs-db-reader"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/prebid-server",
"awslogs-region": "eu-west-1",
"awslogs-stream-prefix": "pbs"
}
},
"ulimits": [ { "name": "nofile", "softLimit": 65536, "hardLimit": 65536 } ]
}
]
}Read it top to bottom. X86_64 matches the published image. PBS_STATUS_RESPONSE makes /status return 200, so the default ALB matcher passes. The database password never appears in the task definition; ECS injects it from Secrets Manager at start. The SQL queries themselves are longer than environment variables handle well, so put them in a pbs.yaml baked into your image or mounted from a file. The query syntax is in our stored requests guide.
For the ECS service, point the ALB target group health check at /status and allow at least a minute before the first check, given the startup times AWS measured. AWS's guidance checks every 60 seconds with a 5-second timeout, scales on 66% CPU and 50% memory, and keeps between 2 and 300 tasks. It also mixes the FARGATE and FARGATE_SPOT capacity providers (stack_constants.py; ecs_service_construct.py). Measure your own startup time and request rate before you copy those numbers; our QPS, latency and bid performance guide explains what to measure.
The same service on EKS
On EKS, PBS-Go reads a config file mounted from a ConfigMap at /etc/config, which its README recommends for Kubernetes (PBS-Go README; Kubernetes ConfigMaps). Probes use /status, as described in the Kubernetes probe guide (Kubernetes probes).
apiVersion: v1
kind: ConfigMap
metadata:
name: pbs-config
data:
pbs.yaml: |
external_url: "https://pbs.example.com"
status_response: "ok"
gdpr:
default_value: "1"
metrics:
prometheus:
port: 9100
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prebid-server
spec:
replicas: 3
selector:
matchLabels:
app: prebid-server
template:
metadata:
labels:
app: prebid-server
spec:
securityContext:
runAsNonRoot: true # the image already runs as UID 1001
containers:
- name: prebid-server
image: prebid/prebid-server:v4.11.1
ports:
- containerPort: 8000
- containerPort: 9100
envFrom:
- secretRef:
name: pbs-db-secret # holds PBS_STORED_REQUESTS_DATABASE_CONNECTION_PASSWORD
volumeMounts:
- name: config
mountPath: /etc/config
readOnly: true
resources:
requests:
cpu: "2"
memory: 4Gi
limits:
memory: 4Gi
startupProbe:
httpGet:
path: /status
port: 8000
periodSeconds: 5
failureThreshold: 24 # allows two minutes to start
readinessProbe:
httpGet:
path: /status
port: 8000
periodSeconds: 10
volumes:
- name: config
configMap:
name: pbs-config
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: prebid-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: prebid-server
minReplicas: 3
maxReplicas: 60
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 65A Service of type ClusterIP and an Ingress managed by the AWS Load Balancer Controller then expose the pods through an ALB. The CPU request mirrors the task size in AWS's guidance; the replica counts are placeholders for your own load test. Our bidder capacity planner helps turn a measured request rate into a replica count.
6 of 6 rows
What you operate | Task definitions and services | A Kubernetes cluster, node groups or Fargate profiles, add-ons |
Config injection | Task | ConfigMap at |
Scaling | ECS service auto scaling (target tracking) | Horizontal Pod Autoscaler |
Used by AWS's guidance | Yes | No |
AWS RTB Fabric inbound endpoints | Not supported on Fargate, per AWS's README | Supported for EKS, per AWS's README |
Best fit | One team, few services, fast start | Existing Kubernetes platform, many services, multi-cloud portability |
What you operate
- ECS on Fargate
Task definitions and services
- EKS
A Kubernetes cluster, node groups or Fargate profiles, add-ons
Config injection
- ECS on Fargate
Task
environmentandsecrets- EKS
ConfigMap at
/etc/config, Secrets
Scaling
- ECS on Fargate
ECS service auto scaling (target tracking)
- EKS
Horizontal Pod Autoscaler
Used by AWS's guidance
- ECS on Fargate
Yes
- EKS
No
AWS RTB Fabric inbound endpoints
- ECS on Fargate
Not supported on Fargate, per AWS's README
- EKS
Supported for EKS, per AWS's README
Best fit
- ECS on Fargate
One team, few services, fast start
- EKS
Existing Kubernetes platform, many services, multi-cloud portability
Table by AdSovereign, CC BY 4.0.
Source for the RTB Fabric rows: AWS's guidance README. It says managed inbound endpoints "require EC2 Auto Scaling groups or EKS", which the Fargate-based guidance cannot use yet (README, accessed 9 November 2026).
What AWS's own guidance deploys
AWS has maintained the guidance since its first release on 28 May 2024 (releases). It is useful as a working reference, with some choices you may not want to copy.
7 of 7 rows
Prebid Server build | PBS-Java 3.43.0, upgraded from 3.28.0 to fix the June 2026 critical advisory; AWS says it has only been tested on PBS-Java |
Compute | ECS on Fargate, 2 vCPU and 4 GB per task, minimum 2 and maximum 300 tasks |
Front door | CloudFront with AWS WAF, then an ALB; an ALB-only mode needs your own certificate |
Cache | Amazon ElastiCache Serverless for bids and creatives |
Metrics and logs | CloudWatch for runtime logs; metrics files on Amazon EFS every 30 seconds, moved to S3 by AWS DataSync, catalogued by AWS Glue for Athena and QuickSight |
Bidder traffic | NAT gateways, or optionally AWS RTB Fabric for outbound requests |
Idle cost | About $241.50 a month in US East with no traffic (AWS estimate, "as of July 2023") |
Prebid Server build
- What the guidance does (v1.4.0)
PBS-Java 3.43.0, upgraded from 3.28.0 to fix the June 2026 critical advisory; AWS says it has only been tested on PBS-Java
Compute
- What the guidance does (v1.4.0)
ECS on Fargate, 2 vCPU and 4 GB per task, minimum 2 and maximum 300 tasks
Front door
- What the guidance does (v1.4.0)
CloudFront with AWS WAF, then an ALB; an ALB-only mode needs your own certificate
Cache
- What the guidance does (v1.4.0)
Amazon ElastiCache Serverless for bids and creatives
Metrics and logs
- What the guidance does (v1.4.0)
CloudWatch for runtime logs; metrics files on Amazon EFS every 30 seconds, moved to S3 by AWS DataSync, catalogued by AWS Glue for Athena and QuickSight
Bidder traffic
- What the guidance does (v1.4.0)
NAT gateways, or optionally AWS RTB Fabric for outbound requests
Idle cost
- What the guidance does (v1.4.0)
About $241.50 a month in US East with no traffic (AWS estimate, "as of July 2023")
Table by AdSovereign, CC BY 4.0.
Sources: README, CHANGELOG, stack_constants.py and the AWS guidance page, all accessed 9 November 2026. The README also says the design is "documented up to 100,000 RPS" (company claim).
The version gap is the main thing to note. PBS-Java 4.0.0 shipped on 6 August 2026 and 4.5.0 on 4 November 2026, so the guidance trails the current major version (PBS-Java releases). Treat it as infrastructure code and pin your own Prebid Server release. For the Java and Go differences that matter when you pick a release, see Prebid Server Go vs Java.
Common mistakes
- Health checks that never pass. Both builds answer
/statuswith 204 unless a status message is set, and the ALB default success code is 200. Setstatus_response(Go) orstatus-response(Java), or widen the matcher to200-299. - Treating
/statusas a deep check. The PBS-Go handler notes that "the app always considers itself ready". It does not test the database or bidders, so alarm on metrics too (status.go). - Exposing the admin port. Ports 6060 (Go) and 8060 (Java) serve admin endpoints, and the Go admin port includes
pprofprofiling (admin.go). Keep them off the load balancer and out of public security groups. - Running
latest. Pin image tags. The June 2026 advisories affected PBS-Go before 4.4.0 and PBS-Java before 3.43.0 (GHSA-4p3g-4hcj-wpvx; GHSA-fr2c-g2f8-qchg). - A container health check with
curl. The PBS-Go image installsca-certificates,mtrandlibatomic1, but notcurl. Use the load balancer or a Kubernetes HTTP probe instead. - Pricing Graviton for an amd64 image. The official images are amd64. Arm64 needs your own build and a test run before it can carry traffic.
- Leaving
external_urlon localhost. User syncs and event URLs are built from it, so a wrong value breaks cookie sync silently. See Prebid Server cookie sync. - Scaling in too fast. A replica that takes a minute to start cannot absorb a spike that lasts thirty seconds. Keep a warm minimum and a scale-in cooldown longer than your p95 startup time.
- Shipping every adapter enabled. PBS-Go turns most adapters on by default; disable the ones you do not buy from, as shown in Prebid Server bidder adapters.
- No way to see inside an auction. Expose the Prometheus port to your scraper only, and keep the debug flags in Prebid Server analytics and debugging at hand for the first week.
FAQ
Is there an official Prebid Server Docker image?
prebid/prebid-server on Docker Hub, tagged per release, and PBS-Java publishes prebid-server-java and prebid-server-java-bundle on GitHub Packages (Docker Hub; PBS-Java README).Can I run Prebid Server on AWS Fargate?
Should I use ECS or EKS for Prebid Server?
Does Prebid Server handle TLS itself?
server.ssl, which AWS's guidance uses between the ALB and containers.Does the Prebid Server image run on AWS Graviton?
What does the AWS Prebid Server guidance deploy?
How this works on owned infrastructure
This page assumes your Prebid Server runs in an AWS account you control, which already keeps the bid stream, logs and stored requests out of a vendor's systems. The same containers can also run in a sovereign cloud region or in your own data centre if residency rules or cost point that way, as discussed in our EU sovereign ad tech stack analysis. AdSovereign packages Prebid Server with its exchange, cache, configuration store and monitoring as one deployable stack for any of those targets, with the same health checks and pinned releases described above. The architecture page shows the full component map, and the pilot page describes a first deployment beside an existing setup.
Sources
- Prebid.org, "Hosting a Prebid Server Cluster" (accessed 9 November 2026). https://docs.prebid.org/prebid-server/hosting/pbs-hosting.html
- Prebid.org, "Prebid Server FAQ" (accessed 9 November 2026). https://docs.prebid.org/faq/prebid-server-faq.html
- GitHub, prebid/prebid-server, README,
Dockerfile,docs/developers/configuration.md,config/config.go,endpoints/status.go,sample/docker-compose.yml(master, accessed 9 November 2026). https://github.com/prebid/prebid-server - GitHub, prebid/prebid-server-java, README,
Dockerfile,docs/config-app.md(master, accessed 9 November 2026). https://github.com/prebid/prebid-server-java - GitHub, prebid/prebid-cache, README,
config.yaml,config/config.go(master, accessed 9 November 2026). https://github.com/prebid/prebid-cache - Docker Hub,
prebid/prebid-serverandprebid/prebid-cachetags (accessed 9 November 2026). https://hub.docker.com/r/prebid/prebid-server - AWS, "Guidance for Deploying a Prebid Server on AWS", repository README, CHANGELOG (v1.4.0, 9 June 2026; release 12 June 2026) and infrastructure source (accessed 9 November 2026). https://github.com/aws-solutions-library-samples/prebid-server-deployment-on-aws
- AWS, "Guidance for Deploying a Prebid Server on AWS" landing page (accessed 9 November 2026). https://aws.amazon.com/solutions/guidance/deploying-a-prebid-server-on-aws/
- AWS, "Amazon ECS task definition parameters" (accessed 9 November 2026). https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html
- AWS, "Pass sensitive data to an Amazon ECS container" (accessed 9 November 2026). https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data-secrets.html
More sources (4)
- AWS, "Health checks for Application Load Balancer target groups" (accessed 9 November 2026). https://docs.aws.amazon.com/elasticloadbalancing/latest/application/target-group-health-checks.html
- Kubernetes, "Configure a Pod to Use a ConfigMap" and "Configure Liveness, Readiness and Startup Probes" (accessed 9 November 2026). https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
- GitHub Security Advisories GHSA-4p3g-4hcj-wpvx (PBS-Go) and GHSA-fr2c-g2f8-qchg (PBS-Java), 8 June 2026. https://github.com/prebid/prebid-server/security/advisories/GHSA-4p3g-4hcj-wpvx
- GitHub, prebid/prebid-server-java release 4.5.0 (4 November 2026). https://github.com/prebid/prebid-server-java/releases/tag/4.5.0