# Serverless Workers

> For the complete documentation index, see [llms.txt](https://docs.lertha.com/llms.txt).
> Any documentation page is available as raw Markdown by appending `.md` to its URL.

> Let the orchestrator start Workers when work arrives on their Task Queue and stop them when it drains: on LAP, AWS Lambda or Google Cloud Run.

A Worker is normally a process you keep running, polling its Task Queue. With Serverless Workers
the orchestrator starts Workers when work arrives and stops them when the Task Queue drains, down
to zero when nothing is waiting.

You set it up per Worker Deployment in the UI: **Workers → Deployments → Create Worker
Deployment**. Choose a compute provider, point it at your Workers, and optionally tune scaling.

## Providers

| Provider | What the orchestrator scales | What you need |
| --- | --- | --- |
| **LAP** | a pool of identical Worker apps on LAP | the apps; nothing in a cloud account |
| **AWS Lambda** | Lambda functions, started once per burst of work | a function, and an IAM role the orchestrator may assume |
| **Google Cloud Run** | a Cloud Run worker pool's instance count | a worker pool, and a service account the orchestrator may impersonate |

The form marks a provider **Not set up** when this orchestrator has no credentials for it. See
[Turning providers on](#turning-providers-on).

## Your Workers

Every Serverless Worker must use **Worker Versioning** with the deployment name and Build ID you
enter in the form. The orchestrator routes work to a Worker Deployment Version, and only Workers
that declare that version receive it.

With the Kotlin SDK, set `LERTHA_DEPLOYMENT_NAME` and `LERTHA_BUILD_ID` on the Worker apps to the
same values; see [Worker Versioning](/develop/kotlin/configuration#worker-versioning).

## LAP pools

A pool is a list of LAP app ids. Every app runs the same Worker image; the orchestrator keeps the
first *N* of them running and stops the rest.

Set each app up once, then leave it stopped:

- on the **lertha** network, where the orchestrator is reachable as `lertha-flow:7233`
- no domain and no health check, since a Worker serves no HTTP
- `LERTHA_ADDRESS=lertha-flow:7233`, `LERTHA_NAMESPACE`, and `LERTHA_DEPLOYMENT_NAME` and
  `LERTHA_BUILD_ID` set to the deployment name and Build ID you enter in the form
- the image pinned to the build that Build ID names, rather than `latest`

- **A new version** gets one Worker straight away, so its Task Queues register with the
  orchestrator and work can be routed to it.
- **Work waiting or arriving** keeps at least one Worker running. A backlog that keeps waiting for
  15 seconds adds one more Worker, then another after 15 more seconds, up to the pool.
- **A quiet Task Queue** drops the pool back to its minimum after the quiet period (Scale-down
  Stabilization in the form, 90 seconds by default).

| Setting | Meaning |
| --- | --- |
| Worker Apps | LAP app ids, comma-separated, in the order they are started |
| Min Workers | how many stay running with no work; `0` scales to zero |
| Max Workers | the most to run; never more than the apps in the pool |
| Scale-down Stabilization | how long the Task Queues must be quiet before scaling down |

The orchestrator checks every pool every 10 seconds, so a Workflow started against an empty pool
begins within about 10 seconds plus the Worker's own start-up time.

A pool's settings are stored on its Worker Deployment Version, so deleting the version removes
the pool. Deleting a pool does not delete the LAP apps.

## AWS Lambda

The orchestrator assumes an IAM role in your account to invoke your function. The form shows the
AWS identity this orchestrator runs as; the role's trust policy must name it and require the
External ID you choose.

**Don't have a role yet?** in the form offers a CloudFormation template and a Terraform snippet,
both filled in with the orchestrator identity, External ID and function ARN you entered. The role
gets `lambda:GetFunction` and `lambda:InvokeFunction` on those functions only.

When you save, the orchestrator checks the function exists, that it can assume the role, and that
the trust policy really enforces the External ID.

## Google Cloud Run

The orchestrator impersonates a service account in your project to change your worker pool's
instance count. The form shows the Google Cloud identity this orchestrator runs as; the
Terraform snippet creates an invoker service account with `roles/run.developer` and lets the
orchestrator impersonate it. Paste its `invoker_email` output into the Service Account field.

## Reaching the orchestrator

Workers started on LAP run beside the orchestrator and reach it on the internal network. Workers
started in AWS or Google Cloud must reach the orchestrator's gRPC port from outside, which needs
frontend authentication configured first.

## Turning providers on

Operators enable providers with [configuration](/orchestrator/configuration):

| Variable | Effect |
| --- | --- |
| `LERTHA_FLOW_LAP_API_URL`, `LERTHA_FLOW_LAP_API_TOKEN` | both set: LAP is available |
| AWS credentials (`AWS_ACCESS_KEY_ID` and friends, or a role) | AWS Lambda is available |
| `GOOGLE_APPLICATION_CREDENTIALS` | Google Cloud Run is available |
| `LERTHA_FLOW_SERVERLESS_PROVIDERS` | overrides detection: `lap`, `aws-lambda`, `gcp-cloud-run`, comma-separated, or `none` |
