---
id: flow--semaphore
title: "Semaphore"
summary: "Throttles parallelism: at most `Slots` records at a time may run through the components behind `Output`; further records wait until a slot is free. Use it in front of resources that must not be called by too many threads at once (APIs with rate limits, databases)."
audience: user
keywords: "input, output, slots, lock"
---
# Semaphore

Throttles parallelism: at most `Slots` records at a time may run through the components behind `Output`; further records wait until a slot is free. Use it in front of resources that must not be called by too many threads at once (APIs with rate limits, databases).

## Pins

| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | any | Record that requests a slot. |
| Output | output | same as input | Called with the same record and metadata while the slot is held. |

## Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `Slots` | integer (1-65535) | `4` | Required. Maximum number of records processed in parallel. Values below 1 are treated as 1. |
| `Lock` | string (max 256) | `Universal` | Name of the semaphore. Must not be empty. |

## Behaviour

- For each record the calling thread waits for a free slot of the semaphore named `Lock`, calls `Output` synchronously and releases the slot when the downstream branch has finished, also when it throws. Exceptions are passed back to the caller.
- The semaphore is created on start (or on first use for a `Lock` name computed by an expression) with the `Slots` value at that moment.
- Waiting is blocking and has no timeout.

## Notes

- Semaphores are per component: two Semaphore components with the same `Lock` name do **not** share slots. Use one Semaphore component in front of the protected branch.
- Within one component, different `Lock` values (set by an expression) get independent semaphores, which allows throttling per key (e.g. per customer).
- Changing `Slots` takes effect only after the flow is restarted.
- `Slots` = `1` serializes the branch (one record at a time).
- Only the synchronous part of the branch is protected; work handed to other threads (queues, async components) is not counted.
- An empty `Lock` makes the component fail when the flow starts.

## Example

```json
{ "Slots": 2, "Lock": "CrmApi" }
```

Queue → **Semaphore** → Http client → ...
