Capacity Plans
Capacity Plans let you model available resource capacity by role and month, compare it against aggregated demand, and identify where hiring or reallocation is needed.
Overview
Resource capacity planning bridges the gap between what a transformation program needs (demand) and what the organization can supply (capacity). ProBeya capacity plans are structured as monthly grids: for each organizational role, you specify planned headcount and available hours per month across a planning horizon. The system then compares these figures against resource demands from active projects, calculating gaps and utilization rates per role.
Getting Started
- Navigate to PPM > Capacity Plans and click + New Plan.
- Set the plan name, planning horizon (start and end dates), and status.
- For each role, enter the planned headcount and available hours per month.
- Approve the plan when ready (approved plans cannot be modified).
- Use the Capacity vs. Demand comparison to identify gaps.
- Review Hiring Triggers for roles with persistent shortfalls.
How It Works
Plan Lifecycle
| Status | Description |
|---|---|
| Draft | Plan is being built — entries can be added or modified |
| Approved | Plan is locked — no further modifications allowed |
Only draft plans can be updated. Once approved, the plan becomes a reference document. The approve mutation records:
- The approver's user ID (
approvedById) - The approval timestamp (
approvedAt)
Attempting to modify an approved plan returns a BAD_REQUEST error.
Monthly Entries
Each entry in the capacity grid specifies:
| Field | Type | Description |
|---|---|---|
| Plan ID | string | The parent capacity plan |
| Role ID | string | The organizational role (e.g., Project Manager, Data Scientist) |
| Month | string | The calendar month in YYYY-MM format |
| Planned Headcount | numeric | Number of people available in this role |
| Available Hours | numeric | Total hours available for the role that month |
| Notes | string | Optional context (e.g., "2 contractors ending in June") |
Entry Management
Entries can be managed through two procedures:
-
upsertEntry: Create or update a single entry. Uses conflict resolution on the(planId, roleId, month)unique constraint. If an entry already exists for that combination, it updates the headcount, hours, and notes. -
batchUpsertEntries: Upsert multiple entries at once for efficient grid population. Each entry in the batch follows the same upsert logic. This is the preferred method for populating an entire capacity grid from a spreadsheet import or template.
Capacity vs. Demand Comparison
The compareCapacityVsDemand query aggregates:
| Metric | Calculation | Interpretation |
|---|---|---|
| Capacity hours | Sum of availableHours from capacity plan entries per role | What the organization can supply |
| Demand hours | Sum of demandHours from resource demand records across active projects | What projects need |
| Gap | Capacity minus demand | Positive = surplus, negative = shortfall |
| Utilization % | (Demand / Capacity) × 100 | How fully utilized each role is |
Results can be filtered by date range (defaults to the plan's full horizon) and are broken down per role with role name and code included.
The response shape:
{
planId: string;
startDate: string;
endDate: string;
comparison: Array<{
roleId: string;
roleName: string;
capacityHours: number;
demandHours: number;
gapHours: number;
utilizationPct: number;
}>;
}
Hiring Triggers
The getHiringTriggers query automatically identifies roles where demand exceeds capacity for three or more consecutive months. These are flagged as hiring triggers with:
| Field | Description |
|---|---|
roleId | The under-resourced role |
roleName | Human-readable role name |
deficitMonths | Number of months with demand exceeding capacity |
totalDeficitHours | Cumulative deficit across the deficit period |
recommendation | Suggested action ("Consider hiring to close capacity gap") |
The analysis works by:
- Fetching all capacity plan entries with their role information
- Aggregating resource demands for the plan's horizon period
- Computing a monthly demand share per role (total demand / number of months)
- Identifying roles where the monthly demand exceeds monthly capacity
- Filtering for roles with three or more deficit months
This feeds directly into the Hiring Plans module, where the autoGenerate feature can create requisitions for all triggered roles in a single action.
Plan Details View
The getById query returns a single capacity plan with all its entries. Entries are joined to the role definitions table to include role name and code, and are ordered by role ID then month for consistent grid rendering.
Configuration
- Planning horizon — defined per plan via start and end dates
- Roles — managed in the organization's role definitions
- Demand sources — automatically aggregated from project resource demand records
- Hiring trigger threshold — fixed at 3 consecutive months (not currently configurable)
Permissions
| Action | Required Role |
|---|---|
| View capacity plans | Any member |
| Create or update draft plans | Editor or Admin |
| Approve a plan | Admin |
| Delete a plan | Admin |
| Run comparison reports | Any member |
| View hiring triggers | Any member |
API Reference
| Procedure | Type | Description |
|---|---|---|
ppmCapacityPlans.create | Mutation | Create a new capacity plan |
ppmCapacityPlans.update | Mutation | Update plan metadata (draft only) |
ppmCapacityPlans.delete | Mutation | Delete a plan and cascade entries |
ppmCapacityPlans.list | Query | List plans with optional status filter |
ppmCapacityPlans.getById | Query | Get plan with all entries and role info |
ppmCapacityPlans.upsertEntry | Mutation | Create or update a single capacity entry |
ppmCapacityPlans.batchUpsertEntries | Mutation | Upsert multiple entries at once |
ppmCapacityPlans.approve | Mutation | Move plan from draft to approved |
ppmCapacityPlans.compareCapacityVsDemand | Query | Capacity vs demand comparison by role |
ppmCapacityPlans.getHiringTriggers | Query | Roles with 3+ months of demand exceeding capacity |
Tips & Best Practices
Create one capacity plan per fiscal quarter rather than a single annual plan. Quarterly plans are easier to maintain and approve, and they encourage regular review of resource assumptions as project landscapes evolve.
Pay close attention to hiring triggers. A three-month consecutive shortfall for a given role is a strong signal that organic capacity adjustments will not suffice and a formal hiring process should begin.
Use the batch upsert feature when populating a new plan from a spreadsheet. It is significantly more efficient than individual entry creation and reduces the number of API round trips.
Related Features
- Hiring Plans — Create requisitions from capacity gap triggers
- Resource Reports — Utilization and demand forecast reports
- Schedules — Resource demands originate from schedule assignments
- Budgets & Costs — Capacity decisions impact labor cost forecasts