Dapr Placement control plane service overview

Overview of the Dapr Placement service

The Dapr Placement service is used to calculate and distribute distributed hash tables for the location of Dapr actors running in self-hosted mode or on Kubernetes. Grouped by namespace, the hash tables map actor types to pods or processes so a Dapr application can communicate with the actor. Anytime a Dapr application activates a Dapr actor, the Placement service updates the hash tables with the latest actor location.

Self-hosted mode

The Placement service Docker container is started automatically as part of dapr init, unless you initialize with dapr init --scheduler-placement, which has the Scheduler service serve actor placement instead. It can also be run manually as a process if you are running in slim-init mode.

Kubernetes mode

The Placement service is deployed as part of dapr init -k, or via the Dapr Helm charts. You can run Placement in high availability (HA) mode. Learn more about setting HA mode in your Kubernetes service.

Alternatively, actor placement can be served by the Scheduler service instead of the standalone Placement service. See Serving placement from the Scheduler service.

For more information on running Dapr on Kubernetes, visit the Kubernetes hosting page.

Serving placement from the Scheduler service

The Scheduler service can serve actor placement itself, so the standalone Placement service is not required to run.

In Kubernetes mode, set the Helm value:

global.scheduler.placement.enabled=true

With this setting, the Placement StatefulSet is not deployed and the Scheduler runs with --placement-enabled=true.

In self-hosted mode, initialize Dapr with dapr init --scheduler-placement (requires Dapr 1.19 or later). The Placement container is not started, and the CLI starts the Scheduler container with --placement-enabled=true for you. No further configuration is needed. The flag is not available with slim-init mode: dapr init --slim installs both the Placement and Scheduler binaries but does not run either of them, so you choose which one to run yourself, passing --placement-enabled=true if you run the Scheduler binary. Applications and sidecars need no configuration of their own: each sidecar takes actor placement from whichever service the control plane advertises, so the cluster always has exactly one placement authority. Toggling the setting in either direction requires no sidecar restarts.

The two services place actors with different algorithms: the Placement service uses a consistent hash ring, while the Scheduler uses rendezvous hashing. Both give the same guarantees (every sidecar deterministically agrees on a single host for each actor ID, and ownership spreads across hosts), but the resulting actor-to-host assignments differ. Switching the placement authority in either direction therefore reassigns actors once: affected actors are deactivated and reactivated on their new hosts with their state intact, as in any actor rebalance.

The Scheduler decides who the placement authority is by detecting whether a Placement service is deployed, so the switch is driven purely by deploying or removing the Placement service. In Kubernetes, the Scheduler watches for Placement pods and resolves the Placement service name; in every mode it also probes any Placement addresses the connected sidecars were configured with. Presence takes effect immediately, while absence must be confirmed by several consecutive checks: a Placement service that restarts or is briefly unreachable keeps the placement authority, and only removing it moves actor placement to the Scheduler.

The /placement/state API is only available from the standalone Placement service and is not served by the Scheduler.

Placement tables

There is an HTTP API /placement/state for Placement service that exposes placement table information. The API is exposed on the sidecar on the same port as the healthz. This is an unauthenticated endpoint, and is disabled by default. You need to set DAPR_PLACEMENT_METADATA_ENABLED environment or metadata-enabled command line args to true to enable it. If you are using helm you just need to set dapr_placement.metadataEnabled to true.

Usecase:

The placement table API can be used to retrieve the current placement table, which contains all the actors registered across all namespaces. This is helpful for debugging and allowing tools to extract and present information about actors.

HTTP Request

GET http://localhost:<healthzPort>/placement/state

HTTP Response Codes

CodeDescription
200Placement tables information returned
500Placement could not return the placement tables information

HTTP Response Body

Placement tables API Response Object

NameTypeDescription
tableVersionintThe placement table version
hostListActor Host Info[]A json array of registered actors host info.

Actor Host Info

NameTypeDescription
namestringThe host:port address of the actor.
appIdstringapp id.
actorTypesjson string arrayList of actor types it hosts.
updatedAttimestampTimestamp of the actor registered/updated.

Examples

 curl localhost:8080/placement/state
{
    "hostList": [{
            "name": "198.18.0.1:49347",
            "namespace": "ns1",
            "appId": "actor1",
            "actorTypes": ["testActorType1", "testActorType3"],
            "updatedAt": 1690274322325260000
        },
        {
            "name": "198.18.0.2:49347",
            "namespace": "ns2",
            "appId": "actor2",
            "actorTypes": ["testActorType2"],
            "updatedAt": 1690274322325260000
        },
        {
            "name": "198.18.0.3:49347",
            "namespace": "ns2",
            "appId": "actor2",
            "actorTypes": ["testActorType2"],
            "updatedAt": 1690274322325260000
        }
    ],
    "tableVersion": 1
}

Disabling the Placement service

The Placement service can be disabled with the following setting:

global.actors.enabled=false

The Placement service is not deployed with this setting in Kubernetes mode. This not only disables actor deployment, but also disables workflows, given that workflows use actors. This setting only applies in Kubernetes mode, however initializing Dapr with --slim excludes the Placement service from being deployed in self-hosted mode.

The Placement service is also not deployed when actor placement is served by the Scheduler service (global.scheduler.placement.enabled=true). Actors and workflows keep working in that case. See Serving placement from the Scheduler service.

For more information on running Dapr on Kubernetes, visit the Kubernetes hosting page.

Learn more about the Placement API.

Last modified October 2, 2026: pr feedback (8958ac055)