{"slug":"tutorial-cr-rapids-production","title":"Production-Ready: Domains, Secrets & Autoscaling","description":"Your hello Rapid is live and redeploys on every push. This tutorial takes it the rest of","section":"Features","url":"https://docs.danubedata.ro/tutorial-cr-rapids-production","markdown_url":"https://docs.danubedata.ro/tutorial-cr-rapids-production.md","breadcrumbs":[{"title":"Features","slug":null},{"title":"Rapids","slug":"serverless-overview"},{"title":"Deploy with CR: Production","slug":"tutorial-cr-rapids-production"}],"headings":[{"level":1,"title":"Production-Ready: Domains, Secrets & Autoscaling","id":"production-ready-domains-secrets-autoscaling"},{"level":2,"title":"1. Put your own domain in front","id":"1-put-your-own-domain-in-front"},{"level":2,"title":"2. Configuration and secrets","id":"2-configuration-and-secrets"},{"level":3,"title":"Talk to a managed database privately","id":"talk-to-a-managed-database-privately"},{"level":2,"title":"3. Scaling","id":"3-scaling"},{"level":3,"title":"Scale-to-zero vs. always-warm","id":"scale-to-zero-vs-always-warm"},{"level":3,"title":"Picking a resource profile","id":"picking-a-resource-profile"},{"level":2,"title":"4. A quick production checklist","id":"4-a-quick-production-checklist"},{"level":2,"title":"What's next","id":"whats-next"}],"format":"markdown","word_count":806,"content":"# Production-Ready: Domains, Secrets & Autoscaling\n\nYour `hello` Rapid is live and redeploys on every push. This tutorial takes it the rest of\nthe way to production: a custom domain with automatic TLS, configuration and secrets injected\nas environment variables (including a private connection to a managed database), and scaling\ntuned for your traffic shape.\n\nEach section shows both the dashboard and the `danube rapids` CLI — use whichever fits your\nworkflow. We continue with the `hello` container and team slug `acme`.\n\n## 1. Put your own domain in front\n\nBy default your container answers at `https://hello-acme.danubedata.run`. You can map up to\n**10 custom domains** per container, each with a TLS certificate provisioned automatically\nvia Let's Encrypt — no cert files, no renewals.\n\n1. In the Rapid's **Domains** tab, click **Add domain** and enter `api.example.com`.\n2. At your DNS provider, add the record Rapids shows you:\n\n   | Type | Name | Value |\n   |------|------|-------|\n   | CNAME | `api.example.com` | `hello-acme.danubedata.run` |\n\n3. Rapids validates the record and issues the certificate within a minute or two. Once it\n   shows **Active**, `https://api.example.com` serves your container.\n\nFor an apex/root domain (`example.com`) that can't take a CNAME, use an **ALIAS**, **ANAME**,\nor CNAME flattening to point at the same managed hostname. Do not pin the domain to an ingress\nIP. See [Custom Domains](https://docs.danubedata.ro/custom-domains) for apex setup, migration,\nand verification details.\n\n## 2. Configuration and secrets\n\nRapids injects configuration as **environment variables**. Set non-secret config and secrets\n(API keys, connection strings) the same way — values are stored encrypted and are never\nwritten to the GitOps repository in plain text.\n\n**Dashboard:** the Rapid's **Settings → Environment Variables** card.\n\n**CLI** (variables are merged with existing ones; changing them rolls a new revision):\n\n```bash\ndanube rapids update hello \\\n  --env NODE_ENV=production \\\n  --env FEATURE_SIGNUPS=on\n\n# remove one later:\ndanube rapids update hello --rm-env FEATURE_SIGNUPS\n```\n\n### Talk to a managed database privately\n\nIf you run a DanubeData managed database or cache, your Rapid can reach it over **internal\ncluster DNS** — the traffic never leaves the cluster, so there's no public exposure and no\negress charge. Inject the internal connection string as an env var:\n\n```bash\ndanube rapids update hello \\\n  --env DATABASE_URL='postgres://app:••••@my-db.acme.svc.cluster.local:5432/app'\n```\n\nRead it in your app like any other env var (`process.env.DATABASE_URL`, `os.environ[...]`,\n`os.Getenv(...)`). Find the internal hostname on your database's detail page.\n\n> **Secrets are revision-scoped.** A running revision keeps the values it started with;\n> updating an env var rolls a new revision with the new values. Rotate a secret by updating\n> the variable — the next revision picks it up.\n\n## 3. Scaling\n\nRapids scales on request load. The defaults (scale-to-zero, scale up on demand) are good for\nmost apps; tune these knobs when you have a specific need.\n\n| Setting | CLI flag | What it does |\n|---------|----------|--------------|\n| Min replicas | `--min-scale` | `0` = scale-to-zero (default). Set `1`+ to keep instances warm and avoid cold starts. |\n| Max replicas | `--max-scale` | Ceiling on instances under load. |\n| Scaling metric | `--scaling-metric` | `rps` (requests/sec) or `concurrency` (in-flight requests) per pod. |\n| Target | `--scaling-target` | The per-pod value of the metric Rapids aims to hold before adding a pod. |\n| Request timeout | `--timeout` | Max seconds for a single request (max `3600`). |\n\n### Scale-to-zero vs. always-warm\n\n- **Scale-to-zero (`--min-scale 0`)** — you pay nothing while idle; the first request after\n  idle pays a short cold start. Ideal for spiky or low-traffic services, internal tools, and\n  webhooks.\n- **Always-warm (`--min-scale 1`)** — one instance stays running so every request is fast,\n  at the cost of running 24/7. Use for latency-sensitive, steady-traffic APIs.\n\n```bash\n# Latency-sensitive API: always one warm instance, scale on concurrency, longer timeout\ndanube rapids update hello \\\n  --min-scale 1 \\\n  --max-scale 20 \\\n  --scaling-metric concurrency \\\n  --scaling-target 50 \\\n  --timeout 120\n```\n\n### Picking a resource profile\n\nStart on the **Free** profile (it includes the monthly free tier) and move up to a paid\nprofile or pay-per-use when you need more vCPU/memory per instance. Profiles and rates are on\nthe [pricing page](https://danubedata.ro/pricing).\n\n```bash\ndanube rapids update hello --profile small\n```\n\n## 4. A quick production checklist\n\n- **Listen on `$PORT`** and return `200` on a health path (e.g. `/healthz`) — Rapids only\n  sends traffic to a revision once it's ready.\n- **Log JSON to stdout/stderr** — logs are captured per revision and searchable in the\n  dashboard. (See [Invoking Containers](https://docs.danubedata.ro/serverless-invoking).)\n- **Pin immutable image tags** (commit SHA) so deploys and rollbacks are precise.\n- **Keep the container stateless** — anything that must survive a scale-to-zero belongs in a\n  managed database, cache, or object storage bucket, not the local filesystem.\n- **Lock down access** if it isn't a public API — see\n  [Authentication](https://docs.danubedata.ro/serverless-authentication).\n\n## What's next\n\n- **[Troubleshooting CR + Rapids](https://docs.danubedata.ro/tutorial-cr-rapids-troubleshooting)** —\n  diagnose `ImagePullBackOff`, cold starts, and stuck deploys.\n- **[Serverless overview](https://docs.danubedata.ro/serverless-overview)** — the full\n  reference for scaling, networking, and limits.\n\n---\n\n**Questions?** Contact support at support@danubedata.ro\n","prev":{"title":"Deploy with CR: CI/CD","slug":"tutorial-cr-rapids-cicd","url":"https://docs.danubedata.ro/tutorial-cr-rapids-cicd","markdown_url":"https://docs.danubedata.ro/tutorial-cr-rapids-cicd.md","json_url":"https://docs.danubedata.ro/tutorial-cr-rapids-cicd.json"},"next":{"title":"Deploy with CR: Troubleshooting","slug":"tutorial-cr-rapids-troubleshooting","url":"https://docs.danubedata.ro/tutorial-cr-rapids-troubleshooting","markdown_url":"https://docs.danubedata.ro/tutorial-cr-rapids-troubleshooting.md","json_url":"https://docs.danubedata.ro/tutorial-cr-rapids-troubleshooting.json"},"index_url":"https://docs.danubedata.ro/index.json"}