> For the complete documentation index, see [llms.txt](https://docs.console.zenlayer.com/welcome/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.console.zenlayer.com/welcome/elastic-compute/placement-group.md).

# Placement Group

A **Placement Group** controls how Zenlayer Elastic Compute (ZEC) lays out a set of instances across the **physical hosts** of a region. To manage placement groups, navigate to the [Placement Group](https://console.zenlayer.com/zec/placement-group) page in the console. Without one, the scheduler is free to land any two instances on the same host — so a single host failure can take down both replicas of your service. A placement group declares the opposite: the listed instances belong together as one fault-tolerant set, and the platform spreads them across **different underlying hosts** so that no single host failure can take more than a known share of them down.

***

## What a Placement Group Is

A placement group is a region-scoped object that pins a set of instances to **distinct physical hosts**. Two parameters shape it:

* **`partition_num`** — the maximum number of member instances the group can hold. The platform aims to put each member on its own host. Range 2–5, default 3.
* **`affinity`** — how many group members the platform is allowed to co-locate on the same host when full spread isn't achievable. It is a *tolerance*, not a target or a multiplier. Range 1 to `partition_num / 2`, default 1.

The group's **capacity is `partition_num`** instances. The platform's first choice is always full spread — one member per host. `affinity` only governs the fallback: if the region cannot give each member a distinct host, up to `affinity` members may share a host rather than fail the placement. Anything beyond `affinity` is refused.

The platform reports a `constraint_status` so you can confirm at a glance whether the spread is currently honored.

> A placement group lives entirely in **one region** (for example `asia-east-1`). It does not stretch across regions. To survive the loss of an entire region, run a separate placement group per region and replicate at the application layer.

> **Partition granularity is host-level today.**

***

## Why Use One

| Scenario                                                                 | Placement Group?  | Notes                                                                               |
| ------------------------------------------------------------------------ | ----------------- | ----------------------------------------------------------------------------------- |
| Distributed quorum (etcd, ZooKeeper, Consul) — odd-number cluster        | ✅ Yes             | Each member on its own host. A single host failure loses at most one quorum member. |
| Stateful replicas (DB primary + replicas, Kafka brokers, Cassandra ring) | ✅ Yes             | Co-locating replicas defeats the point of having them.                              |
| Stateless web tier with N>1 replicas behind a load balancer              | ✅ Yes             | Keeps a single host fault from taking out the whole tier behind the VIP.            |
| Cross-region HA — survive a full region outage                           | ❌ Not enough      | Use one placement group per region plus application-level replication.              |
| A single VM, no replicas                                                 | ❌ Overkill        | A group with one member adds nothing.                                               |
| HPC / latency-sensitive workloads that want VMs *closer*, not apart      | ❌ Wrong primitive | Placement groups enforce anti-affinity. There is no co-location mode today.         |

***

## How `partition_num` and `affinity` Work Together

![Each member ideally lands on its own physical host](/files/smrR0bRBMSY70qI7Fwjh)

`partition_num` and `affinity` express two different things:

* **`partition_num`** sets **how many members** the group can hold (and equivalently, how many distinct hosts the group prefers to span — one per member).
* **`affinity`** sets **how much co-location is tolerated** when free hosts are scarce. With `affinity=1`, no host may carry more than one member. With `affinity=2`, up to two members may share a host as a fallback — but never three.

Capacity is `partition_num`, period. `affinity` does not multiply it. The setting only controls how far the spread is allowed to degrade before the scheduler refuses an assignment (or marks the group *unsatisfied* after a recovery event lands two members back on one host).

### Two Worked Examples

**`partition_num=5, affinity=1`** — strict spread for a 5-node quorum. The group holds at most 5 members. All 5 must land on different hosts. The platform never co-locates two members. If no qualifying host is free, the assignment is rejected.

**`partition_num=5, affinity=2`** — fault-tolerant spread with a fallback. The group holds at most 5 members. The platform still tries to place all 5 on different hosts. If host capacity prevents that, up to 2 members may share one host — but never more. This keeps a majority of the group on distinct hosts, so a single host failure cannot take a quorum down at once.

In both cases `partition_num` caps the group at 5 members. `affinity` only changes how much spread can degrade before the platform refuses placement.

### Picking `partition_num`

Match `partition_num` to the size of the cluster you want to spread:

| Cluster shape                    | `partition_num` |
| -------------------------------- | --------------- |
| Primary + 1 replica              | 2               |
| Primary + 2 replicas             | 3               |
| 3-node quorum (etcd, ZK, Consul) | 3               |
| 5-node quorum                    | 5               |

To grow past `partition_num=5`, split the workload across multiple placement groups.

### Picking `affinity`

`affinity` is your tolerance for co-location when full spread isn't achievable. Leave it at the default `1` for the strictest "one-member-per-host" guarantee — the right choice for small quorums and stateful replicas, where any two replicas going down together is unacceptable. Raise it (within `partition_num / 2`) when you'd rather accept partial co-location than have an assignment refused during a host shortage. The cap of `partition_num / 2` exists so a single host failure can never bring down a majority of the group.

***

## Lifecycle

![Lifecycle: create the group, then assign instances one by one](/files/2L74yJ6VDfNFsVAKH1uK)

A placement group is created empty and populated by assigning instances to it one at a time. Membership is a separate operation from instance creation.

1. **Create** the group. `region_id` and the initial `partition_num` are set up front. The region is fixed for life; `partition_num` and `affinity` can be modified later.
2. **Assign an instance** to the group. The instance must be in the group's region. The platform picks a host that satisfies the spread.
3. **Remove an instance** at any time. Its slot in the group frees up.
4. **Modify** `partition_num` or `affinity` later. Decreasing `partition_num` below the current member count is rejected.
5. **Delete** the group once it has no members.

Membership is **exclusive**: an instance belongs to at most one placement group. Reassigning across groups is a single operation — the platform removes the instance from the old group and slots it into the new one.

> **Hard cap:** `instance_count ≤ partition_num`. Adding a member to a full group is rejected.

***

## Constraint Status

`constraint_status` reports whether the current placement still honors the spread:

| Status              | Meaning                                                                                                                 |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| Constraint met      | No host carries more than one member — full spread is in effect. Steady state.                                          |
| Constraint at risk  | Some host carries more than one member but no more than `affinity`. Within tolerance, but the safety margin is reduced. |
| Constraint violated | Some host carries more than `affinity` members. Rare; arises only under unusual recovery paths.                         |

The platform actively avoids placements that would violate the rule, so most groups stay *met* indefinitely.

***

## Working with Instances

### Adding an existing instance

You can move a running instance into a placement group as long as a slot is free and the instance is in the group's region. The platform applies the placement on the instance's next placement event — typically the next stop/start. Until then, the instance is associated with the group but its host does not change.

> If the instance is currently on a host that conflicts with the group, joining does **not** trigger a live migration. Schedule a stop/start so the platform can re-place it.

### Removing an instance

Removal is immediate at the membership level. The instance keeps running on its current host; only the anti-affinity bookkeeping changes.

### Replacing a failed member

Assign the replacement to the group as soon as it exists. The freed slot is reused.

***

## Limits

| Property                       | Value                                                    |
| ------------------------------ | -------------------------------------------------------- |
| Scope                          | One region (e.g. `asia-east-1`). No cross-region groups. |
| `partition_num`                | 2–5, default 3.                                          |
| Member instances per group     | ≤ `partition_num`.                                       |
| Group memberships per instance | At most 1.                                               |
| `affinity`                     | 1 to `partition_num / 2`, default 1.                     |
| Partition granularity          | Host-level                                               |

***

## Frequently Asked Questions

**Can a placement group span regions?** No. A placement group is bound to one region for life. For cross-region HA, run one group per region and replicate above.

**Can I add more instances than `partition_num`?** No. Raise `partition_num` (up to 5) or split the workload across multiple groups.

**Does raising `affinity` give me more capacity?** No. Capacity is always `partition_num`. `affinity` is the maximum number of members the scheduler may co-locate on a single host when full spread isn't possible — it controls how much the spread is allowed to degrade, not how many members the group holds.

**What happens during live migration of a member?** The destination host is chosen so the constraint still holds. Membership and `constraint_status` are preserved across the migration.

**Can I move an instance between two placement groups?** Yes. Re-assigning is one operation — the instance leaves the old group's slot and takes a free slot in the new one. Both groups must be in the instance's region.

**Does a placement group cost extra?** No. There is no per-group charge.

**Why was my assignment rejected?** Either the group is full (`instance_count == partition_num`) or no host in the region can satisfy the constraint at this `affinity` level. Raise `partition_num`, raise `affinity` (allow more co-location as a fallback), or pick a different region.

**Can I spread across racks or switches instead of hosts?** Not today — only host-level placement is exposed.

**How is a placement group different from a resource group?** A **resource group** is an organizational/billing boundary. A **placement group** is a *physical-placement* constraint — it controls where instances may run. They are independent.

***

## Learn More

* [**Instance Specification**](/welcome/elastic-compute/instance-specification.md) — pick the instance shape for each member.
* [**Network Interface**](/welcome/elastic-compute/networking/network-interface.md) — how vNICs follow instances across live migration.
