Terraform Professional (002): Operating HCP Terraform and Tracking Usage and Cost
Operating HCP Terraform means running workspaces day to day — choosing where runs execute, managing agents, CLI runs, permissions, locks, notifications and health checks — while tracking what the platform manages and what it costs. This lesson covers objectives 7a and 7b of the Terraform Infrastructure Engineer Professional (002) exam: remote, local and agent execution and what each keeps; agent pools; CLI-driven runs; workspace and project roles; locking and deletion; notifications and webhook signing; health assessments and the Explorer; ephemeral workspaces; managed-resource billing; and cost estimation. Multi-environment workspaces, Terraform version upgrades and policy as code in pipelines belong to the next lesson.
On this page10 sections
- Choosing remote, local or agent execution
- Operating agent pools
- CLI-driven runs through the cloud block
- Workspace and project permissions for operating teams
- Locking and deleting workspaces
- Notifications: destinations, triggers and webhook security
- Health assessments, continuous validation and the Explorer
- Ephemeral workspaces and auto-destroy
- How HCP Terraform bills: managed resources
- Cost estimation and cost data in policies
- Choose remote, local or agent execution for a workspace and predict which features each mode keeps
- Operate agent pools: scoping, token rotation and network-uniform pools
- Predict CLI-driven run behaviour, workspace locks and the result of deleting a workspace
- Pick least-privilege workspace, project and organization permissions for operating teams
- Configure notifications, secure generic webhooks and use health assessments and the Explorer
- Explain how managed resources are counted and billed, and where usage and charges are reported
- Enable cost estimation, read its data in Sentinel policies, and tell cloud spend from HCP Terraform spend
Choosing remote, local or agent execution
A workspace's execution mode decides where Terraform actually runs, and with it which HCP Terraform features the workspace keeps. There are three modes, set per workspace or inherited from a default:
| Mode | Where Terraform runs | What you keep | Use it when |
|---|---|---|---|
| Remote | HCP Terraform's own workers | The full run pipeline: run history, approvals, variables and variable sets, policy checks, run tasks, notifications, health assessments, cost estimation | The resources are reachable from the internet (public cloud APIs) |
| Agent | HCP Terraform agents you host, in an agent pool | The same full run pipeline as remote | The targets are reachable only from a private network that blocks inbound connections |
| Local | The machine where someone runs the Terraform CLI | State storage, state locking and state sharing (outputs, terraform_remote_state) only | You want HCP Terraform purely as a state backend |
Local execution turns the workspace into state storage. Terraform runs on the workstation or CI runner, so HCP Terraform does not evaluate the workspace's Terraform or environment variables, nor any variable sets in scope — the caller must supply every value and every credential locally (tfvars files, environment variables). Features that exist only because HCP Terraform runs Terraform itself stop as well: notifications, health assessments (drift detection and continuous validation), policy sets and run tasks. State-based features continue, because the cloud block still stores and locks state in the workspace.
That last point matters for governance: any CLI execution outside HCP Terraform — a build server or an engineer's workstation inside the private network — can reach private targets, but policy sets and run tasks never evaluate, because they exist only inside HCP Terraform runs. When a private network and governance are both required, agent execution is the mode that satisfies both.
Defaults. The organization settings hold a default execution mode (remote, local, or agent with a chosen pool); workspaces set to use the organization default inherit it, so changing it once moves every new workspace onto agents without per-workspace edits. Projects can also set a default execution mode that new workspaces created in them inherit (existing workspaces keep their setting) — useful when only one project needs agents.
Operating agent pools
An HCP Terraform agent is a lightweight process you run inside your own network; it polls HCP Terraform over outbound HTTPS only, picks up runs for workspaces in agent mode, executes them, and streams results back. Nothing needs to reach into the network, which is why agents are the answer for vSphere, on-premises or private-endpoint targets behind firewalls that block inbound traffic. Agents are grouped into agent pools, and each workspace in agent mode points at one pool.
- Scoping. By default a pool is available to every workspace. You can restrict it to specific projects and workspaces, which stops others from selecting it — but HCP Terraform does not detach workspaces already using the pool. Those must be moved to another pool or execution mode in their own settings.
- Tokens. Agents authenticate with an agent token, and a pool can have several tokens at once. Revoking a token makes the agents using it exit; they cannot take runs until they restart with a valid token. Rotate make-before-break: create a new token, restart or redeploy each agent with it, then revoke the old one.
- Any agent can run any phase. HCP Terraform may run a run's plan on one agent and its apply on another, depending on which are free. Every agent in a pool must therefore reach everything its workspaces manage and share the same platform. A pool spread across networks with no route between them produces failures that look random (plan works, apply times out); split pools by network instead.
CLI-driven runs through the cloud block
In the CLI-driven workflow an engineer runs terraform plan or terraform apply locally against a workspace named in the cloud block; the local configuration is uploaded and the run executes in HCP Terraform (remote or agent mode), with logs streamed to the terminal. Behaviours to know:
- Plans work everywhere, applies don't.
terraform planstarts a speculative plan with the local code in any workspace. A remoteterraform applyis refused in workspaces connected to a VCS repository, because the repository is the source of truth: commit and merge to the tracked branch to trigger the real run. - Auto-apply versus
-auto-approve. The workspace's auto-apply setting governs runs created from the UI, the API and VCS webhooks (run triggers have their own setting). CLI runs ignore it: without-auto-approve, Terraform asks for confirmation in the terminal. - Ctrl-C. Pressing Ctrl-C while the run waits for confirmation cancels it; once the apply has started, Ctrl-C only stops log streaming — the remote apply carries on, visible in the UI. Cancel or discard a run from the UI or API instead.
- What gets uploaded. A
.terraformignorefile in the configuration directory excludes files (for example large local artefacts) from the upload. - Saved plans.
terraform plan -out=FILEcreates a saved-plan run in HCP Terraform;terraform apply FILElater applies exactly that plan, and only in the workspace that produced it.
Workspace and project permissions for operating teams
HCP Terraform grants teams access through fixed roles or custom permissions at workspace and project level, plus organization-level permissions. The fixed workspace roles are cumulative:
| Workspace role | Adds |
|---|---|
| Read | View runs and logs, variables, and the full state |
| Plan | Queue plans (but not approve applies) |
| Write | Approve applies, edit variables, write state, lock and unlock the workspace |
| Admin | Workspace settings, team access, force unlock, notifications, deletion |
Project roles grant workspace access across every workspace in the project:
| Project role | Effect |
|---|---|
| Read / Write | The matching workspace role on every workspace in the project |
| Maintain | Admin on every workspace and Stack in the project, plus creating and deleting workspaces there |
| Admin | Everything Maintain has, plus the project itself: team access to the project, moving workspaces in or out, renaming or deleting it, project variable sets and project notifications |
State access is the classic least-privilege trap. Custom workspace permissions offer four state levels: No access, Read outputs only, Read (the whole state file) and Read and write. Every fixed role, even Read, includes full state read — which exposes any secrets stored in state. A team that only needs terraform output, the state-version-outputs API or terraform_remote_state against another team's workspace should get a custom role with Read outputs only.
At organization level, View all workspaces gives read access to every workspace without the ability to change them; it is also the minimum (besides being an owner) for using the Explorer.
Locking and deleting workspaces
A workspace lock freezes change: it blocks all applies and most plans, whether runs come from the UI, CLI, API or VCS, until the lock is released. Two kinds of operation proceed anyway — plan-only runs such as speculative plans (pull-request plans, CLI terraform plan) and the planning stage of saved-plan runs; their applies, like any apply, wait. A lock also restricts state uploads: HCP Terraform accepts a new state version only when the workspace is locked by the user doing the upload.
Users with lock/unlock permission (Write and above) can release only their own locks. A lock held by someone else needs a workspace admin to force unlock. So replacing state while a colleague's lock is in place takes: admin force unlock → you lock → upload → unlock.
Deleting a workspace never destroys infrastructure. There are two paths:
- Safe delete (the default for workspace admins) succeeds only when the workspace is unlocked and its state manages no resources.
- Force delete skips that check; it is reserved to organization owners unless they allow workspace admins to use it. The resources keep running in the cloud, now unmanaged.
The clean decommission path is a destroy run first, then a safe delete.
Notifications: destinations, triggers and webhook security
Notification configurations send workspace events to Slack, Microsoft Teams, email or a generic webhook. Each configuration picks its triggers:
- Run events — Created, Planning, Needs Attention (a plan needs confirmation or a policy override), Applying, Completed, Errored (the run ended early because of an error or cancellation).
- Health events — Drift detected, Check failed (continuous validation found a failing assertion between runs) and Health assessment errored.
- Auto-destroy events — Auto destroy reminder (sent 12 and 24 hours before a scheduled auto-destroy, leaving time to postpone it) and Auto destroy results.
Two things never notify: speculative plans, and anything in a workspace using local execution.
Securing a generic webhook. Give the notification a token; HCP Terraform then signs every payload with an HMAC using SHA-512 keyed by that token and sends it in the X-TFE-Notification-Signature header. The receiver recomputes the HMAC and rejects anything that doesn't match. Verification on enable: when a generic webhook or Slack notification is enabled, HCP Terraform sends a test message, and the destination must answer with a 2xx status or the configuration stays disabled — an endpoint that rejects or redirects the test request (any non-2xx answer, such as a 403 from an IP allowlist or a 3xx redirect) leaves the notification disabled. Make the receiver accept HCP Terraform's requests and authenticate them by the signature.
Project notifications are configured once on a project and fire for run events in every workspace in it, including workspaces created in or moved into it later. They sit alongside workspace notifications, workspace admins cannot switch them off from workspace settings, and creating them needs project Admin (not Maintain).
Health assessments, continuous validation and the Explorer
Health assessments check a workspace between runs and come in two parts: drift detection (does real infrastructure still match state?) and continuous validation (do the configuration's check blocks, preconditions and postconditions still pass?). They can be enabled per workspace or enforced across the organization.
| Requirement | Drift detection | Continuous validation |
|---|---|---|
| Execution mode | Remote or agent | Remote or agent |
| Run history | Latest run successful, with at least one successful apply | Latest run successful, with at least one successful apply |
| Terraform version | 0.15.4 or later | 1.3.0 or later |
| Something to evaluate | Managed resources | Checks, preconditions or postconditions in the configuration |
After an errored, canceled or discarded run, assessments pause until the next successful apply. Continuous validation suits post-apply monitoring such as "the public endpoint must return HTTP 200": a check block reports a failure without blocking runs, and the assessment re-evaluates it on schedule without anyone operating a scheduler.
Runtime behaviour. Assessments run speculative plans that never modify infrastructure, do not consume the organization's run concurrency, and never hold up deployments — if a run starts during an assessment, the assessment is cancelled and rescheduled. In large organizations assessments may be batched, which delays results, not runs. The cadence is measured from the more recent of the last apply and the last assessment, so a fresh apply restarts the clock.
The Explorer answers organization-wide questions without opening each workspace. It queries four data types — workspaces, modules, providers and Terraform versions — and offers built-in use cases such as Drifted workspaces, Workspaces with failed checks and Terraform version usage. Filter conditions are combined with a logical AND, so two mutually exclusive conditions on the same field (for example, two different module names in the Modules data type) return no rows; run separate queries instead. Saved views store the query, not a snapshot of results. Access requires being an organization owner or holding View all workspaces (or greater).
Ephemeral workspaces and auto-destroy
An ephemeral workspace is one set to destroy its infrastructure automatically, so short-lived environments stop costing money (cloud spend and managed resources) when people forget them. Auto-destroy has two triggers:
- A scheduled date and time — a one-off; the setting is cleared after its destroy run.
- Inactivity — a period with no state changes. Only runs that change state reset the window, and the setting stays active after the destroy run.
When it fires, HCP Terraform queues a destroy run that does not wait for approval; the workspace itself remains. Projects can hold a default auto-destroy setting that their workspaces inherit (and may override), so one setting on a sandbox project covers current and future feature workspaces. Pair it with the Auto destroy reminder notification so owners can postpone a destroy they still need.
How HCP Terraform bills: managed resources
HCP Terraform's usage-based plans bill managed resources: resources with mode = "managed" in a state file that HCP Terraform manages, counted from provisioning until destruction. The rules:
- What counts. Every managed-mode resource in HCP Terraform-managed state — in workspaces and in Stacks deployments — including logical resources (random, time providers) and resources inside modules.
- What doesn't.
null_resourceandterraform_dataare excluded, and data sources (mode = "data") are not managed resources at all. - Hourly peak. Billing is per hour at the peak count reached in that hour, and partial hours bill as full hours. A burst of 80 resources that exists for only 10 minutes still adds 80 to that hour's peak; resources that straddle an hour boundary count in both hours.
- It follows state, not the runner. Moving workspaces to local execution or self-hosted CI changes where Terraform runs, not where state lives, so the count is unchanged. Only destroying resources (or removing them from HCP Terraform-managed state) lowers it. Resizing an instance changes the cloud bill, not the HCP Terraform count.
Where to see it. The organization's Usage page shows the managed resource count, plan limits and summaries of projects, workspaces, Stacks and applies; on paid plans its billable resource table breaks the count down by project and workspace, with search, filters and CSV export. The money actually charged is shown in the HashiCorp Cloud Platform portal's billing section, refreshed hourly.
Cost estimation and cost data in policies
Cost estimation projects the cloud provider's hourly and monthly cost of the workspace's resources before and after the run, and the change between them, shown as a phase between plan and apply. It is off by default; an organization owner enables it for all workspaces under the organization's Settings > Cost Estimation — no integration to host. Behaviours to know:
- It covers supported resources on AWS, Azure and Google Cloud. Resources without cost data or with unpredictable usage-based pricing (for example some API and streaming resources) are listed as unestimated and left out of the total; supported resources with no direct charge are itemised at $0.
- Runs that use resource targeting (
-target) skip cost estimation.
Using estimates in policy. Sentinel's tfrun import exposes cost_estimate.prior_monthly_cost, proposed_monthly_cost and delta_monthly_cost (which is negative when a plan lowers the estimate). prior_monthly_cost is the workspace's estimated monthly total at the start of the plan; proposed_monthly_cost is the estimated monthly total for all the workspace's resources if the plan were applied — not just the changed ones; delta_monthly_cost is proposed minus prior. All are estimates from published prices, never figures from a provider invoice. All three are strings holding decimal numbers such as "0.0", so a policy converts them with the decimal import before comparing with a threshold. The namespace exists only when an estimate is available, so a policy must handle its absence (targeted runs, estimation disabled).
Three cost questions, three sources:
| Question | Source |
|---|---|
| What will this change add to the cloud bill? | The run's cost estimation phase |
| What does HashiCorp bill us? | Managed resource count on the Usage page; money in the HCP portal billing |
| What do we run, and on which versions? | The Explorer (workspaces, modules, providers, Terraform versions) |
One change can move both bills through different mechanisms: adding a load balancer with two listeners adds its monthly price to the cloud estimate and three managed resources to the HCP Terraform count, whatever they cost.
Tip. Expect operational scenarios where every option is a real HCP Terraform feature and one stated constraint decides: a network that blocks inbound traffic plus mandatory governance, a least-privilege team with a narrow job, a notification endpoint that misbehaves, a lock someone else holds, or a sandbox that must clean itself up. Execution-mode items ask which features survive a switch to local mode. Agent items cover pool scoping, token rotation and pools that span networks. CLI items cover auto-apply versus -auto-approve, Ctrl-C and VCS-linked workspaces. Billing items give resource counts across an hour, a mix of resource types or a Stack, and ask what HCP Terraform bills; cost items separate cloud spend (cost estimation) from HashiCorp's charge (managed resources, Usage page, HCP portal billing) and test what the tfrun.cost_estimate fields hold. Multi-select items pair two facts from the same feature.
- Agent execution = private network with the full HCP Terraform run pipeline; agents connect outbound only.
- Local execution keeps state storage, locking and sharing but drops variables, variable sets, notifications, health assessments, policies and run tasks.
- Scoping an agent pool doesn't detach existing users; rotate agent tokens make-before-break; any agent may run any phase.
- CLI runs ignore workspace auto-apply (use -auto-approve), cannot apply in VCS-linked workspaces, and Ctrl-C after apply starts stops only the logs.
- Every fixed role reads full state; only a custom role with Read outputs only hides secrets. Project Maintain administers workspaces; project Admin administers the project.
- A lock blocks applies and uploads by others; deleting a workspace never destroys its infrastructure.
- Generic webhooks: set a token, verify X-TFE-Notification-Signature (HMAC SHA-512); enabling needs a 2xx test response.
- Continuous validation needs Terraform 1.3+ and checks or conditions; assessments never change infrastructure and yield to runs.
- HCP Terraform bills the hourly peak of managed resources (workspaces + Stacks, minus null_resource and terraform_data); partial hours count in full.
- Cost estimation = cloud spend, off by default, skipped for -target; tfrun.cost_estimate prior/proposed are before/after monthly totals (decimal strings), delta = proposed minus prior.
Frequently asked questions
When should an HCP Terraform workspace use agent execution instead of local execution?
Use agent execution when Terraform must reach resources in a private network and you still want HCP Terraform's run pipeline — run history, approvals, variables, policy sets, run tasks, notifications and health assessments. Agents run inside the network and connect outbound only. Local execution also reaches private resources, but HCP Terraform then only stores and locks state, so none of those run features apply.
Does switching workspaces to local execution reduce the HCP Terraform bill?
No. HCP Terraform bills managed resources held in the state it manages, and local execution keeps state in the workspace through the cloud block. Only destroying resources, or removing them from HCP Terraform-managed state, lowers the managed resource count.
Which resources are excluded from HCP Terraform's billable managed resource count?
Resources of type null_resource and terraform_data are excluded, and data sources are not managed resources at all. Every other resource with mode managed in HCP Terraform-managed state counts, including random and time provider resources, resources inside modules, and resources managed by Stacks.
How do I verify that a webhook request really came from HCP Terraform?
Set a token on the generic webhook notification. HCP Terraform then sends an X-TFE-Notification-Signature header containing an HMAC SHA-512 of the payload keyed with that token; the receiving service recomputes the HMAC and rejects requests whose signature does not match. The endpoint must also return a 2xx response to the test message sent when the notification is enabled.
Why does a terraform plan with -target show no cost estimate in HCP Terraform?
HCP Terraform skips cost estimation for runs that use resource targeting. Sentinel policies that read tfrun.cost_estimate must therefore handle the namespace being absent on such runs, as well as when cost estimation is disabled for the organization.
Does deleting an HCP Terraform workspace destroy its resources?
No. Deleting a workspace removes the workspace and its state from HCP Terraform but never runs a destroy. Safe delete refuses while the state still manages resources; force delete, normally reserved to organization owners, removes it anyway and leaves the resources running unmanaged. Queue a destroy run first, then safe delete.
What is the difference between drift detection and continuous validation?
Both are parts of HCP Terraform health assessments. Drift detection compares real infrastructure with state and needs Terraform 0.15.4 or later. Continuous validation re-evaluates check blocks, preconditions and postconditions and needs Terraform 1.3.0 or later plus at least one such assertion in the configuration. Both need remote or agent execution and a successful latest run with at least one successful apply.
Source
This lesson covers the "HCP Terraform and Terraform Enterprise operations" domain of the official Terraform Pro 002 exam guide. Vendors revise their guides — check the source for the current version.
Sign up free to mark lessons complete, bookmark topics and track your exam readiness.