# Event Readiness

> Plan scheduled capacity changes for launches, sales, and load tests by driving cloud-native autoscaling groups (ASG, MIG, VMSS) to a larger size for the event window and rolling back when it ends.

Source: https://zop.dev/developer-docs/operations/event-readiness

---

Event Readiness plans scheduled capacity changes for an upcoming event — a marketing launch, a sale, a load-test window — by driving cloud-native autoscaling groups (AWS ASG, GCP MIG, Azure VMSS) to a larger min / max / desired for the duration of the event and rolling them back when the event ends. Each plan wraps one or more [autoscaler policies](https://zop.dev/docs/operations/vm-autoscaling) as targets.

**Info**

It is not a verdict / scoring system. There is no "ready", "needs-attention", or "not-ready" classification. A plan is a pre-scale + post-event rollback schedule that the executor dispatches against the cloud-provider autoscaling API.

## Create a Plan

### POST /event-readiness

Create a plan with one or more autoscaler-policy targets.

```bash title="Request"
curl -X POST https://zopnight.com/api/event-readiness \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Spring campaign launch",
    "description": "Marketing burst on checkout + web tiers",
    "eventStart": "2026-05-02T13:00:00Z",
    "eventEnd":   "2026-05-02T21:00:00Z",
    "preScaleMinutes": 30,
    "postEventMinutes": 30,
    "expectedMultiplier": 3.0,
    "timezone": "America/New_York",
    "targets": [
      { "policyId": "asp_checkout" },
      { "policyId": "asp_web" }
    ]
  }'
```

```json title="Response"
{
  "data": {
    "id": "evt_abc123",
    "orgId": "org_xyz",
    "name": "Spring campaign launch",
    "eventStart": "2026-05-02T13:00:00Z",
    "eventEnd":   "2026-05-02T21:00:00Z",
    "preScaleMinutes": 30,
    "postEventMinutes": 30,
    "expectedMultiplier": 3.0,
    "timezone": "America/New_York",
    "status": "draft",
    "targets": [
      { "policyId": "asp_checkout", "originalMin": 2, "originalMax": 10, "originalDesired": 2 },
      { "policyId": "asp_web",      "originalMin": 3, "originalMax": 12, "originalDesired": 3 }
    ],
    "createdAt": "2026-04-20T12:00:00Z"
  }
}
```

**Info**

Targets are autoscaler policies whose underlying resource is one of:

- `aws:asg` — EC2 Auto Scaling Group
- `gcp:mig` — Managed Instance Group
- `azure:vmss` — Virtual Machine Scale Set

Database targets (RDS, Aurora, Cosmos DB, SQL Managed Instance) are **not** in scope for Event Readiness — those use Start/Stop schedules instead.

## Calculate Scaled Capacity

### GET /event-readiness/calculate

Preview what min/max/desired ZopNight will drive a policy to, without persisting a plan. Used by the creation wizard.

#### Query Parameters

| Parameter | Type | Description |
|---|---|---|
| `policy_id` | string | Autoscaler policy to size (required) |
| `multiplier` | float | Explicit load multiplier — e.g. 3.0 for 3x current traffic |
| `expected_requests` | integer | Alternative to multiplier: expected peak RPS, derived against current activity-log signal |

```json title="Response"
{
  "data": {
    "scaledMin": 6,
    "scaledMax": 30,
    "scaledDesired": 12,
    "multiplier": 3.0,
    "method": "multiplier",
    "isEstimated": false
  }
}
```

`method` is either `multiplier` (when `multiplier` was supplied directly) or `absolute` (when the size was derived from `expected_requests`). When CPU metrics are unavailable the calculator falls back to conservative defaults (50% average, 70% target) and returns `isEstimated: true` with an `estimationReason`.

### GET /event-readiness/calculate-db

Variant of /calculate for database-style targets. Returns the recommended instance class step-up (e.g. db.r6g.large → db.r6g.2xlarge).

## Preview Before Save

The wizard's "Review" step calls `preview-readiness` to render an end-to-end snapshot — every target's current size, the calculated scaled size, and the timestamps the executor will use — before the plan is persisted.

### POST /event-readiness/preview-readiness

Preview the full plan without persisting it.

```bash title="Request"
curl -X POST https://zopnight.com/api/event-readiness/preview-readiness \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "eventStart": "2026-05-02T13:00:00Z",
    "eventEnd":   "2026-05-02T21:00:00Z",
    "preScaleMinutes": 30,
    "postEventMinutes": 30,
    "expectedMultiplier": 3.0,
    "targets": [{ "policyId": "asp_checkout" }]
  }'
```

### POST /event-readiness/cost-preview

Cost-only preview for an unsaved plan. Cheaper than preview-readiness when the wizard only needs the projected spend — skips capacity and executor-queue checks.

```bash title="Request"
curl -X POST https://zopnight.com/api/event-readiness/cost-preview \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "eventStart": "2026-05-02T13:00:00Z",
    "eventEnd":   "2026-05-02T21:00:00Z",
    "expectedMultiplier": 3.0,
    "targets": [{ "policyId": "asp_checkout" }]
  }'
```

## DB Impact & Cost Estimate

On the saved plan, two further endpoints surface estimated impact for the review screen and the audit trail.

### GET /event-readiness/{eventID}/db-impact

Per-target estimate of the database tier change (CPU, RAM, IOPS deltas). Returns empty when the plan has no DB-style targets.

### GET /event-readiness/{eventID}/cost-estimate

Estimated extra cost incurred by the plan, derived from per-target hours scaled multiplied by the on-demand price for the scaled-up size.

```json title="Response"
{
  "data": {
    "currency": "USD",
    "estimatedExtraCost": 142.30,
    "perTarget": [
      { "policyId": "asp_checkout", "extraCost": 92.10 },
      { "policyId": "asp_web",      "extraCost": 50.20 }
    ]
  }
}
```

### GET /event-readiness/{eventID}/readiness-check

On-demand readiness check that re-validates target capacity, credentials, and the executor queue. Used by the dashboard to surface red/green chips on each plan.

## Schedule & Cancel

### POST /event-readiness/{eventID}/schedule

Dispatch the plan. Intents are pushed to the executor, which calls the cloud-native scaling API at eventStart - preScaleMinutes and rolls back at eventEnd + postEventMinutes.

```json title="Response"
{
  "message": "event scheduled",
  "eventId": "evt_abc123"
}
```

### POST /event-readiness/{eventID}/cancel

Cancel an active event and push cancel intents to the executor. Any scale-ups already applied are rolled back to the stored original min/max/desired.

## Status Lifecycle

The plan moves through a well-defined state machine as the executor reports progress via an internal status callback.

| Status | Meaning |
|---|---|
| `draft` | Plan created but not scheduled yet. Fully editable. |
| `scheduling` | schedule endpoint called; intents being pushed to executor. |
| `scheduled` | Executor has accepted the intents and registered the timed actions. |
| `scaling_up` | Pre-scale window hit; executor is calling the cloud scaling API. |
| `active` | Event window in progress; targets are held at scaled min/max/desired. |
| `scaling_down` | Post-event window hit; executor is restoring original capacity. |
| `completed` | Rollback finished; plan is inert. |
| `cancelled` | Plan cancelled from any schedulable state. |
| `failed` | Executor or provider call failed. Retry by transitioning back to draft/scheduling. |

Valid transitions: `draft` → `scheduling` / `cancelled`; `scheduling` → `scheduled` / `failed` / `cancelled`; `scheduled` → `scaling_up` / `cancelled` / `failed`; `scaling_up` → `active` / `failed` / `cancelled`; `active` → `scaling_down` / `failed` / `cancelled`; `scaling_down` → `completed` / `failed` / `cancelled`; `failed` → `draft` / `scheduling` / `cancelled`; `completed` → `draft` / `cancelled`.

## List & Inspect

### GET /event-readiness

List plans with status/search filters and pagination (page, limit ≤ 100).

### GET /event-readiness/count

Count plans (supports status and search filters).

### GET /event-readiness/filters

Distinct filter values (statuses) for building UIs.

### GET /event-readiness/{eventID}

Get a single plan with full target detail.

### PUT /event-readiness/{eventID}

Update a plan (partial update). Only safe while the plan is still schedulable.

### DELETE /event-readiness/{eventID}

Soft-delete a plan. If the plan is in a schedulable state, a cancel is pushed to the executor first.

### GET /event-readiness/{eventID}/logs

Paginated audit log of status transitions and executor callbacks for this plan.

Scaling intents are dispatched by the same executor that handles Start/Stop schedules — see [Schedules](https://zop.dev/docs/core-concepts/schedules) for how the executor queue and retry semantics work.
