# Deployment

When you run `sinch functions deploy`, the CLI packages your source code and uploads it to the Sinch platform. The platform builds, deploys, and rolls out your function. You get a stable HTTPS URL.

This page walks through what happens during a deploy, what the CLI decides vs what the platform decides, and what your options are.

## The end-to-end flow

1. **Validation.** The CLI makes sure your project is healthy before uploading anything.
  - **Node:** typecheck (if `tsconfig.json` is present), bundle with `tsup`, lint if configured. The CLI also confirms a `.env` file exists — without one the deployed function has no configuration and will not run, so the deploy is aborted with `sinch env init` as the suggested fix. This is a hard error, not one of the warnings described below, so `--force` does not bypass it.
  - **C#:** `dotnet build`, then start the function locally and hit `GET /health` to confirm it boots. If the build fails or the health check times out, the deploy is aborted.
2. **Documentation prompt.** The CLI may offer to generate or update `README.md`. Skip with `--no-docs`.
3. **Packaging.** The CLI zips your source directory. These are excluded automatically: `node_modules/`, `bin/`, `obj/`, `.git/`, `.env`, `.vscode/`, `.idea/`, `.vs/`.
4. **Configuration resolution.** The CLI reads `sinch.json` (variables) and your `.env` keys (secrets). Empty values trigger a keychain lookup to pull the secret from your OS keychain, and the resolved set is sent alongside the source. The CLI prints each variable name with a `(secret)` or `(plain)` tag before uploading — values are never printed.
5. **Access-level choice.** Public (internet-accessible) or private (internal to Sinch services only). The CLI asks **once** — on your first deploy — and saves the choice as the project default (`accessLevel` in `sinch.json`). Every later deploy reuses it silently, so there's no repeated prompt and no way to flip it by accident. Override any time with `--public` or `--private`, which also updates the saved default; combine with `--non-interactive` for CI. If nothing is saved and no flag is given in non-interactive mode, the default is public.
6. **Upload.** The CLI streams the ZIP and the config to the Sinch platform over HTTPS.
7. **Build and roll out (platform-side).** The platform builds your function. Builds are deterministic — if an identical build already exists, it's reused and this step finishes in seconds. Otherwise a fresh build runs. On success, the new version is rolled out and traffic is routed to it.
8. **Callback URL updates.** If your `sinch.json` binds the function to a Voice App or Conversation App, the CLI updates that app's callback URL to point at the new function URL (`https://<subdomain>.fn.sinch.com`, where `<subdomain>` is the host the platform assigns to your function).
9. **Wait for completion.** The CLI streams build and deploy progress in real time until the rollout is finished.


## Usage

```bash
sinch functions deploy                   # interactive
sinch functions deploy --non-interactive # CI/CD mode: defaults to public, auto-generates docs
sinch functions deploy --no-wait         # submit and exit immediately
sinch functions deploy --private         # internal access only
sinch functions deploy --no-docs         # skip README generation
```

## Deployment statuses

The CLI surfaces these as the rollout progresses:

| Status | Meaning |
|  --- | --- |
| `Pending` | Queued, waiting for a build slot. |
| `Building` | Your function is being built. |
| `Running` | Function is live and serving traffic. |
| `Failed` | Build or deploy failed — check `sinch functions logs`. |


## What you get after a successful deploy

- **A stable URL.** `https://<subdomain>.fn.sinch.com` (public) or `https://<subdomain>.private.fn.sinch.com` (private). The platform assigns the subdomain on first deploy and it doesn't change on later deploys.
- **A function ID** written back to your `sinch.json` so subsequent CLI commands know what to target.
- **A `GET /health` endpoint** provided by the runtime, used by the platform for liveness checks. You don't implement it.
- **Callback URLs pointed at the new function** (if `sinch.json` configures a Voice App or Conversation App binding).


## Determinism and rebuilds

Builds are keyed on a hash of your source + dependencies + runtime version. If you redeploy with no changes, the platform skips the build step and reuses the existing image — deploys in this mode take seconds. If anything has changed, a fresh build runs.

This means you can safely redeploy as a "force rollout" — the build cost is paid only when the source actually changes.

## The rollback question

There is no `sinch functions rollback` today. The supported pattern is:

1. Keep the last-known-good version in source control (tag it).
2. If a bad deploy breaks things, check out the tag and run `sinch functions deploy` again.
3. The deterministic build cache usually makes this take only a few seconds.


## Related

- [Local vs production](/docs/functions/functions/concepts/local-vs-prod) — what changes between dev and deployed
- [`sinch functions` commands](/docs/functions/cli/commands/functions) — full CLI reference for functions-related commands
- [Monitoring](/docs/functions/functions/monitoring) — how to stream logs and debug failed deploys
- [Architecture](/docs/functions/concepts/architecture) — end-to-end view of how your function reaches production