# Serverless Containers

DanubeData Serverless Containers lets you deploy containerized applications with automatic scaling, scale-to-zero, and pay-per-use pricing — powered by Knative on Kubernetes with zero infrastructure management.

## Key features

- **Three deployment methods** — Pull a Docker image, connect a Git repository, or upload a ZIP file
- **Switch source anytime** — Move an existing container between Docker image, Git repository, and ZIP upload from its Edit page, without recreating it
- **Scale to zero** — Containers automatically scale down to zero replicas when idle, so you only pay for actual usage
- **Automatic scaling** — Scales up instantly based on incoming traffic (requests per second or concurrency)
- **Custom domains** — Bring your own domain with DNS verification and automatic TLS via Let's Encrypt
- **Git auto-build** — Push to GitHub, GitLab, or Bitbucket and your container builds and deploys automatically
- **Buildpacks** — Auto-detect your runtime (Node.js, Python, Go, Java, Ruby, PHP, .NET, Rust) without writing a Dockerfile
- **Real-time metrics** — Monitor requests, latency, error rate, and replica count in the dashboard
- **Environment variables** — Configure secrets and settings without rebuilding your container
- **Traffic splitting** — Route traffic between revisions for canary deployments and A/B testing
- **Scheduled scaling** — Pre-scale containers on a schedule for predictable traffic patterns
- **Internal networking** — Access your team's databases and caches via internal cluster DNS
- **EU data residency** — All data stored in Falkenstein, Germany (GDPR-compliant)

## Deployment methods

### Docker image

Deploy a pre-built container image from any supported registry. Best for teams with existing CI/CD pipelines or pre-built images.

**Supported registries:**

| Registry | Host |
|----------|------|
| Docker Hub | `docker.io` |
| GitHub Container Registry | `ghcr.io` |
| Google Container Registry | `gcr.io` |
| GitLab Container Registry | `registry.gitlab.com` |
| Red Hat Quay | `quay.io` |
| AWS Public ECR | `public.ecr.aws` |
| Microsoft Container Registry | `mcr.microsoft.com` |

**How it works:**

1. Enter your image URL and tag (e.g., `docker.io/myorg/myapp:v1.2`)
2. DanubeData validates the image exists and is pullable
3. The image is deployed as a Knative Service in your team's namespace
4. Your container is accessible at its auto-generated URL

### Git repository

Connect a GitHub, GitLab, or Bitbucket repository for automatic builds and deployments. Each push to your configured branch triggers a new build.

- **Supported providers** — GitHub, GitLab, Bitbucket
- **Authentication** — Public repos need no credentials. Private repos support SSH keys or access tokens.
- **Auto-deploy** — Builds trigger automatically on push via webhooks
- **Branch selection** — Deploy from any branch (defaults to `main`)

**Build methods:**

| Method | Description |
|--------|-------------|
| **Buildpacks** | Auto-detect your runtime and build without a Dockerfile. Supports Node.js, Python, Go, Java, Ruby, PHP, .NET, and Rust. |
| **Dockerfile** | Use your own Dockerfile for full control over the build process. Configurable Dockerfile path and build context. |

**Available buildpack builders:**

| Builder | Runtimes |
|---------|----------|
| Paketo Base | Java, Node.js, Python, Go, Ruby, .NET |
| Paketo Full | Extended language support |
| Paketo Tiny | Go (minimal images) |
| Google Cloud Buildpacks | Node.js, Python, Go, Java |
| Heroku Builder 22 | Node.js, Python, Ruby, PHP, Go, Java |

**Runtime auto-detection:**

| File present | Detected runtime |
|-------------|-----------------|
| `package.json` | Node.js |
| `requirements.txt`, `setup.py`, `pyproject.toml`, `Pipfile` | Python |
| `go.mod` | Go |
| `pom.xml`, `build.gradle` | Java |
| `Gemfile` | Ruby |
| `composer.json` | PHP |
| `*.csproj`, `*.sln` | .NET |
| `Cargo.toml` | Rust |

### ZIP upload

Upload your source code as a ZIP file via the API. DanubeData builds and deploys it using Buildpacks or your Dockerfile.

- Maximum upload size: 500 MB
- Supports both Buildpacks and Dockerfile builds
- Ideal for CI/CD integration without Git provider webhooks
- **Single-folder ZIPs are auto-unwrapped** — if you ran `zip -r app.zip myproject/` and everything sits inside one wrapper folder, DanubeData looks inside it automatically, so your `Dockerfile` or manifest files are still found. If a manifest is genuinely missing, the build error points you to the wrapper-folder fix.
- **Editable build configuration** — after the first upload you can change the build settings from the Edit page: switch between Buildpacks and Dockerfile, change the Dockerfile path, the source subdirectory, or the buildpack builder. Saving rebuilds from your last uploaded ZIP.
- **Your upload is retained** — the ZIP is stored so manual rebuilds and **Retry** don't require re-uploading the archive.

```bash
curl -X POST \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "file=@source.zip" \
  https://api.danubedata.ro/api/v1/serverless/{container-id}/deploy
```

After an upload starts building, the form is replaced with **Follow build** and **Cancel build** controls so it's clear a build is in progress.

## Changing the deployment source

You are not locked into the deployment method you picked at creation. From a container's **Edit** page you can switch its source between **Docker image**, **Git repository**, and **ZIP upload** at any time — for example, start from a pre-built image and later connect a Git repo for auto-builds, or the other way around.

- Your **cost baseline and deployment history carry over** cleanly across the switch — you keep the same container, URL, environment variables, custom domains, and usage record.
- Switching **away** from a Git-connected source automatically stops that repository's push-to-deploy webhook from triggering new builds, so old pushes won't deploy over your new source.
- After saving the new source, deploy as usual — the change takes effect on the next deployment.

## How it works

### Deployment pipeline

```
Docker Image / Git Push / ZIP Upload
         |
         v
   Build Queued (Git/ZIP only)
         |
         v
   Image Built (Tekton Pipeline)
         |
         v
   Pushed to Registry
         |
         v
   GitOps Commit (Knative Service YAML)
         |
         v
   ArgoCD Sync
         |
         v
   Container Running
```

1. **Source** — You provide a Docker image, push to a Git repo, or upload a ZIP file
2. **Build** (Git/ZIP only) — A Tekton pipeline clones your code, builds an image using Buildpacks or Dockerfile, and pushes it to the DanubeData container registry
3. **Deploy** — The serverless deployment service generates a Knative Service manifest and commits it to the GitOps repository
4. **Sync** — ArgoCD detects the change and reconciles the Knative Service in your team's namespace
5. **Live** — Your container is accessible at its URL with automatic TLS and auto-scaling

### Container statuses

| Status | Description |
|--------|-------------|
| **Pending** | Container created, waiting for first deployment |
| **Deploying** | Deployment in progress via ArgoCD |
| **Running** | Container is live and serving traffic |
| **Stopped** | Container manually stopped (scaled to zero) |
| **Error** | Deployment or runtime failure — check the error details |
| **Degraded** | Container is partially operational |

Status changes are pushed to your dashboard in real time via WebSocket.

### Build statuses

| Status | Description |
|--------|-------------|
| **Pending** | Build queued, waiting for resources |
| **Cloning** | Fetching source code from the repository |
| **Building** | Building the container image |
| **Pushing** | Uploading the built image to the registry |
| **Succeeded** | Build completed, deployment starting |
| **Failed** | Build failed — check build logs for details |
| **Cancelled** | Build was cancelled before completion |

## Container access

Each container is accessible at an auto-generated URL:

```
https://{container-slug}-{team-name}.danubedata.run
```

The slug is derived from your container name. You can also add custom domains for branded URLs.

## Resource profiles

| Profile | vCPU (request - limit) | Memory (request - limit) | Best for |
|---------|----------------------|-------------------------|----------|
| **Free** | 0.01 - 0.1 | 64 - 128 MB | Trying the platform, webhooks (max 3 replicas) |
| **Small** | 0.5 - 1 | 256 - 512 MB | Standard APIs, workers |
| **Medium** | 1 - 2 | 512 MB - 1 GB | Data processing, batch jobs |
| **Large** | 2 - 4 | 1 - 2 GB | Heavy compute workloads |

Profiles have no fixed monthly fee — you pay only for what you use (see Pricing below).

## Pricing

Serverless containers use pay-per-use pricing. You are billed for actual compute time, not idle time.

| Metric | Price |
|--------|-------|
| **vCPU-second** | EUR 0.000015 (~EUR 0.054/vCPU-hour) |
| **Memory (GiB)-second** | EUR 0.0000025 |
| **Requests** | EUR 0.15 per million |
| **Egress traffic** | EUR 0.09 per GB |
| **Minimum billing increment** | 100 ms |

### Free tier

Every account includes a generous free tier:

| Metric | Free allowance |
|--------|---------------|
| **Requests** | 2,000,000 per month |
| **vCPU-seconds** | 250,000 per month (~69 vCPU-hours) |
| **Memory (GiB)-seconds** | 500,000 per month (~139 GiB-hours) |
| **Egress** | 5 GB per month |

Billing is recorded every 5 minutes based on actual resource consumption. Monthly invoices are generated on the 1st of each month, and your free allowances reset at the same time.

Going over a free allowance **never suspends or throttles your container** — usage simply becomes billable at the pay-per-use rates above. The usage meters in the dashboard are there for visibility, not enforcement. The **Usage & Billing** tab on each container shows your included allowances alongside a clear Used / Billable / Charge breakdown, so you can see at a glance whether anything is billable this month.

## Scaling

### Auto-scaling

Containers scale automatically based on incoming traffic. Two scaling metrics are available:

| Metric | Description | Default target |
|--------|-------------|---------------|
| **RPS** (requests per second) | Scales based on throughput per pod. Recommended for most workloads. | 100 RPS/pod |
| **Concurrency** | Scales based on simultaneous in-flight requests per pod. | 100 concurrent/pod |

**Scaling parameters:**

| Parameter | Default | Range | Description |
|-----------|---------|-------|-------------|
| Min replicas | 0 | 0 - 100 | Minimum running instances. Set to 0 for scale-to-zero. |
| Max replicas | 10 | 1 - 100 | Maximum instances during traffic spikes. |
| Scaling target | 100 | 1+ | Target value for the selected scaling metric. |
| Idle timeout | 5 min | Fixed | Time before scaling to zero after last request. |
| Cooldown period (scale-down delay) | 5 min | 0s - 1h, per container | How long a revision keeps its instances after losing traffic. See [Startup work and rollouts](#startup-work-and-rollouts). |
| Initial scale | Platform default (effectively 1) | 0 - max replicas, per container | Instances a new revision starts with before it counts as ready. See [Startup work and rollouts](#startup-work-and-rollouts). |

### Scale-to-zero

When min replicas is set to 0 (the default), your container scales to zero after 5 minutes of inactivity. This means:

- No compute charges during idle periods
- First request after idle triggers a cold start (typically 1-5 seconds)
- Set min replicas to 1 or higher to avoid cold starts

### Scheduled scaling

Configure time-based scaling rules for predictable traffic patterns. For example, scale up during business hours and back down at night.

Each schedule defines:
- **Days of week** — Which days the schedule applies
- **Start and end time** — When the scaling rule is active (HH:MM format)
- **Minimum replicas** — The minimum replica count during this window
- **Timezone** — Any IANA timezone (e.g., `Europe/Berlin`)

Overnight schedules (e.g., 22:00 to 06:00) are supported.

## Custom domains

Add up to 10 custom domains per container with automatic TLS.

### Adding a domain

1. Navigate to the container detail page
2. Click **Manage Domains** from the Actions dropdown
3. Click **Add Domain**
4. Enter your domain (e.g., `api.example.com`)

### Domain verification

After adding a domain, verify ownership by creating a DNS TXT record:

- **Record name** — `_danubedata-verify.your-domain.com`
- **Record value** — The verification token shown in the dashboard

DNS propagation may take a few minutes. Click **Verify** to check.

### Connecting your domain

After verification, create a CNAME record pointing to your container URL:

```
api.example.com  CNAME  my-api-acme.danubedata.run
```

A TLS certificate is provisioned automatically via Let's Encrypt once the CNAME is in place.

### Domain statuses

**Verification:**

| Status | Description |
|--------|-------------|
| **Pending** | Awaiting DNS TXT record |
| **Verifying** | DNS check in progress |
| **Verified** | Domain ownership confirmed |
| **Failed** | Verification failed — check DNS records |

**TLS:**

| Status | Description |
|--------|-------------|
| **Pending** | Awaiting certificate provisioning |
| **Provisioning** | Certificate being generated |
| **Active** | HTTPS active with valid certificate |
| **Failed** | Certificate provisioning failed |

**Deployment:**

| Status | Description |
|--------|-------------|
| **Pending** | Domain not yet deployed to the container |
| **Deploying** | Domain being added to the Knative Service |
| **Active** | Domain is live and routing traffic |
| **Removing** | Domain being removed |
| **Failed** | Domain deployment failed |

### Setting a primary domain

Designate any verified domain as the primary domain. The primary domain is used as the canonical URL for your container.

## Environment variables

Configure your container with environment variables for secrets, connection strings, and application settings.

- Maximum 100 variables per container
- Maximum key length: 256 characters
- Maximum value length: 10,000 characters
- Maximum total size: 100 KB
- Variables are encrypted at rest and injected at container startup

**Adding variables:**

1. Navigate to the container **Edit** page
2. Scroll to **Environment Variables**
3. Add key-value pairs
4. Save and redeploy

Values are masked by default in the editor; authorized users can reveal and edit
them. Each container has its own runtime environment, so use separate containers
for development and production secrets. Build-time configuration is separate.

Rapids does not automatically scrub values that your application or build scripts
print. Avoid logging secrets, request bodies, patient details or sensitive query
parameters, and keep credentials out of image layers and frontend bundles.

## Git webhooks

When using Git repository deployment, DanubeData generates a webhook URL and secret for automatic builds.

### Setting up webhooks

1. Navigate to the container detail page
2. Go to the **Activity** tab
3. Copy the **Webhook URL** and **Webhook Secret**
4. In your Git provider settings, add a webhook:
   - **URL** — The webhook URL from the dashboard
   - **Secret** — The webhook secret from the dashboard
   - **Events** — Push events only

### Webhook verification

| Provider | Signature header | Method |
|----------|-----------------|--------|
| **GitHub** | `X-Hub-Signature-256` | HMAC-SHA256 |
| **GitLab** | `X-Gitlab-Token` | Token comparison |
| **Bitbucket** | `X-Hub-Signature` | HMAC-SHA256 |

### Auto-build on push

When enabled, every push to the configured branch triggers a build and deployment automatically. Disable auto-build from the container edit page if you prefer manual deployments.

## Deployments and rollbacks

Every deployment creates a new revision. Your deployment history shows all revisions with their status, image, and sync state. A rollout that gets stuck times out and resolves on its own instead of hanging indefinitely — the failed revision is marked, and your previously healthy version keeps serving.

### Viewing deployments

Builds and deployments share a single **Activity** tab on the container detail page. Navigate to the container detail page and click the **Activity** tab.

Each deployment shows:
- Revision name (e.g., `my-api-00007`)
- Container image
- ArgoCD sync and health status
- Creation and sync timestamps
- Traffic percentage

### Rolling back

To revert to a previous deployment:

1. Open the **Activity** tab
2. Find the revision you want to restore
3. Click **Route traffic here** and confirm the request

Rapids checks that the retained revision is ready, then requests 100% of traffic
for that revision. The request remains pending until the platform observes the
new traffic destination; it does not mark the revision current merely because the
request was submitted. No rebuild or new revision is needed. A missing or unready
revision cannot be selected.

This changes traffic routing. It does not restore database contents or previous
secret values. For a new rollout from an earlier image using current settings,
use **Redeploy** on a retained successful build instead. A subsequent normal
deployment resumes routing to its new ready revision.

### Traffic splitting

Split traffic between multiple revisions for canary deployments or A/B testing. Navigate to the container detail page to view the current traffic distribution across revisions.

### Startup work and rollouts

By default, a rollout briefly runs two revisions at once: your new revision starts an instance and has up to five minutes to become ready, while the previous revision keeps its own instances running for five minutes after it stops receiving traffic. For most containers this overlap is invisible. It matters if your container does work on startup — running database migrations, warming a cache — because that work then runs on **both** revisions, including right after a deployment that also changes **Minimum Replicas** from 1 back down to 0.

Two settings on the **Edit** page (and the API) give you control over that overlap:

| Setting | What it controls | Default | Trade-off |
|---------|-------------------|---------|-----------|
| **Initial Scale** (`initial_scale`) | How many instances a new revision starts with before it counts as ready. The platform uses whichever is larger, Initial Scale or Minimum Replicas. | Platform default (effectively 1) | Set to **0** together with **Minimum Replicas 0** and a revision can become ready without ever starting an instance — cold start moves to the first request instead of the rollout. If your image is broken, you find out on that first request rather than immediately after deploying. |
| **Scale-Down Delay** (`scale_down_delay_seconds`) | How long the previous revision keeps its instances after the new one takes over traffic. | 5 minutes | Set to **0** and the old revision's instances are released as soon as the new one takes traffic, instead of five minutes later. |

**For a container that runs migrations or other startup work and scales to zero**, set Initial Scale to `0` and Scale-Down Delay to `0`. The old revision releases its instances as soon as the new one takes over, and the new revision does not start an instance — and does not run your startup work — until its first request arrives, so the two revisions' startup work never overlaps.

Leave both unset to keep the platform defaults described above.

## Builds

For Git and ZIP deployments, builds are executed via Tekton pipelines in a dedicated build namespace.

### Build configuration

| Setting | Default | Description |
|---------|---------|-------------|
| **Build timeout** | 30 minutes | Maximum build duration |
| **Max concurrent builds** | 3 per team | Parallel builds allowed |
| **Max builds per day** | 50 per team | Daily build limit |
| **Build log access** | 10 days after completion | History metadata is separate from log output |

### Build actions

- **Trigger build** — Start a new build manually from the Actions dropdown
- **Cancel build** — Stop an in-progress build
- **Retry build** — Retry a failed build with the same configuration
- **Redeploy build** — Deploy a previously successful build without rebuilding

### Build logs

Build logs stream live from the **Activity** tab as your container builds and refresh on their own — no manual reload. You get the **full build output** (there is no 500-line cap). Logs include the clone, build, and push stages.

Completed build output expires after ten days. Stored build text is removed by
hourly cleanup; build history metadata remains. See [Logs](https://docs.danubedata.ro/monitoring-logs)
for the scope of the retention policy.

### Deploy failure reasons

When a deploy fails, the container shows a plain-language reason instead of a raw error, each with a hint on how to fix it. Common reasons:

| Reason | What it usually means |
|--------|----------------------|
| **Architecture mismatch** | The image was built for the wrong CPU architecture (e.g. `arm64` from an Apple Silicon Mac). Rebuild for `linux/amd64`. |
| **Image or tag not found** | The referenced image or tag doesn't exist or isn't pullable — check the spelling and that the push finished. |
| **Out of memory** | The container exceeded its memory limit at startup — move up a resource profile or reduce memory use. |
| **Startup timed out** | The application didn't become ready in time — make sure it listens on the configured port and starts promptly. |

## Monitoring

### Real-time metrics

The container detail page shows live metrics:

- **Total requests** — Cumulative request count with sparkline trend
- **Current replicas** — Active pod count vs. max scale
- **Average latency** — Response time in milliseconds
- **Error rate** — Percentage of 5xx responses

### Historical charts

The Overview tab includes time-series charts for:
- Request rate
- Average latency
- Replica count
- Error rate

### Usage summary

Monthly usage tracked per container:
- Average CPU (millicores)
- Average memory (MB)
- Total requests
- Total compute seconds
- Total cost

## Deploy failure alerts

DanubeData continuously watches your running containers — not just the first rollout. If a new revision fails to deploy while your last healthy version keeps serving, the container is flagged **Degraded** and your team is notified so a bad deploy never goes unnoticed.

- **Email alerts** — your team gets an email the moment a container runs into trouble, with the failure reason and a link to investigate.
- **Auto-recovery** — a container that recovers on its own (for example, a later revision succeeds) clears automatically back to healthy; no action needed.
- **`serverless.build_failed` webhook** — if you have webhooks enabled, build failures are also delivered to your own tooling so you can wire them into your existing alerting.

Because your previously healthy revision keeps serving throughout, a failed deploy does not take your container offline.

## Networking

### Internal services

Serverless containers can access your team's databases and caches using internal cluster DNS:

```
{service-name}.tenant-{team-name}.svc.cluster.local
```

For example:
```
my-database.tenant-acme.svc.cluster.local:3306   # MySQL
my-cache.tenant-acme.svc.cluster.local:6379       # Redis
```

Pass connection strings as environment variables.

### Allowed outbound connections

| Port | Service |
|------|---------|
| 80 | HTTP |
| 443 | HTTPS |
| 3306 | MySQL |
| 5432 | PostgreSQL |
| 6379 | Redis |
| 27017 | MongoDB |

### Security

Containers run with strict security policies:

- Non-root execution (UID 1000)
- Read-only root filesystem
- No privilege escalation
- All Linux capabilities dropped
- Seccomp profile: RuntimeDefault
- Blocked access to cloud metadata services
- Blocked access to Kubernetes API

## Container limits

| Limit | Value |
|-------|-------|
| **Containers per team** | 50 |
| **Containers per user** | 10 |
| **Max request body** | No platform-imposed limit (tested up to 500 MB; in practice bounded by your request timeout and upstream upload speed) |
| **Max response body** | No platform-imposed limit (streamed through the gateway; bounded by your request timeout) |
| **Request timeout** | 300 seconds (default); configurable per container up to 3600 seconds (1 hour) from the edit page |
| **Environment variables** | 100 per container, 100 KB total |
| **Custom domains** | 10 per container |
| **Revisions kept** | 50 per container |
| **Revision retention** | 90 days |
| **Ephemeral storage** | 1 GB per container |

## Recommended images

DanubeData provides pre-vetted images for common runtimes:

| Runtime | Image | Default port |
|---------|-------|-------------|
| **Node.js** | `docker.io/library/node:20-alpine` | 3000 |
| **Python** | `docker.io/library/python:3.12-slim` | 8000 |
| **Go** | `docker.io/library/golang:1.22-alpine` | 8080 |
| **Nginx** | `docker.io/library/nginx:alpine` | 80 |
| **PHP** | `docker.io/library/php:8.3-fpm-alpine` | 9000 |
| **Ruby** | `docker.io/library/ruby:3.3-slim` | 3000 |

## Reserved ports

The following ports are reserved by the platform's Knative queue-proxy sidecar. Do not configure your container to listen on any of these — your application will fail to start with `bind: address already in use`:

| Port | Used for |
|------|----------|
| 8012 | Knative queue-proxy readiness probe |
| 8013 | Knative queue-proxy serving |
| 8022 | Knative queue-proxy admin / profiling |
| 8112 | Knative queue-proxy serving (TLS) |
| 9090 | Knative queue-proxy Prometheus metrics |

We recommend `8080` (the default) for your application port.

## Container actions

| Action | Description | Available when |
|--------|-------------|---------------|
| **Start** | Start a stopped container | Status: stopped |
| **Stop** | Scale to zero and stop serving traffic | Status: running |
| **Restart** | Stop and start the container | Status: running |
| **Redeploy** | Pull latest image and create a new revision (Docker image only) | Status: running, stopped, error |
| **Build & Deploy** | Trigger a new build from source (Git only) | Any status |
| **Delete** | Permanently delete the container and all revisions | Any status |

Bulk operations (start, stop, delete) are available from the container list page for up to 25 containers at once.

## FAQ

### What types of applications can I deploy?

Any application that runs in a Docker container and listens on an HTTP port. This includes REST APIs, GraphQL servers, web applications, webhook receivers, background workers, and microservices.

### Do I need a Dockerfile?

No. If you use Git repository deployment with Buildpacks, DanubeData auto-detects your runtime and builds the image without a Dockerfile. Buildpacks support Node.js, Python, Go, Java, Ruby, PHP, .NET, and Rust.

### How fast is a cold start?

Cold start time depends on your image size and application startup time. Typical cold starts are 1-5 seconds. Use slim or Alpine base images and minimize initialization work to reduce cold start latency. Set min replicas to 1 to avoid cold starts entirely.

### Can I use a private container registry?

The platform supports pulling from Docker Hub, GitHub Container Registry, GitLab Registry, Quay, AWS ECR, and Google Container Registry. For Git deployments, images are built and stored in the DanubeData container registry automatically.

### How does billing work?

You are billed for actual compute time (vCPU-seconds and memory-GiB-seconds), requests, and egress traffic. When your container is scaled to zero, you incur no compute charges. The free tier covers 2M requests and ~69 vCPU-hours per month.

### Can I connect to my database from a serverless container?

Yes. Serverless containers can access databases and caches in your team's namespace using internal cluster DNS. Pass the connection string as an environment variable.

### Can I use a custom domain?

Yes. You can add up to 10 custom domains per container with automatic TLS via Let's Encrypt. Domain verification requires a DNS TXT record.

### How do rollbacks work?

Each deployment creates a revision. In the Activity tab, choose **Route traffic
here** on a retained ready revision. Rapids requests the traffic switch and
confirms it after observing the live destination. This requires no rebuild and
does not reverse database changes or restore previous secrets. Redeploying a
retained successful build is a separate action that creates a new rollout.

### What happens if my build fails?

Your current live deployment remains active. Failed builds do not affect the running container. Check the build logs for error details and retry.

### Is there a request size limit?

There is no platform-imposed body size limit today; uploads and downloads stream through the gateway and are bounded only by your request timeout and network speed. We have validated transfers up to 500 MB. The default request timeout is 300 seconds, configurable per container up to 3600 seconds (1 hour) from the edit page.

## Next steps

- [Invoking containers](https://docs.danubedata.ro/serverless-invoking) — Code examples in cURL, JavaScript, Python, PHP, and Go
- [Authentication](https://docs.danubedata.ro/serverless-authentication) — Secure your container endpoints
- [Custom domains](https://docs.danubedata.ro/serverless-domains) — DNS verification and TLS setup
- [Git deployments](https://docs.danubedata.ro/serverless-git) — Webhooks and auto-build

---

**Questions?** Contact support at support@danubedata.ro
