Terraform
Async resource provisioning with polling
Many infrastructure APIs accept a create or delete request immediately and finish the work in the background. The API returns a 202 (or 204) with an identifier, and the resource is not actually usable, or fully removed, until a subsequent GET confirms the new state.
Speakeasy-generated Terraform providers can wait for those transitions automatically with the x-speakeasy-polling extension wired into the create and delete entity operations. This guide shows how to apply polling without touching the base OpenAPI document, by layering an overlay.
Scenario: a database that provisions asynchronously
Section titled “Scenario: a database that provisions asynchronously”The base API exposes a Database resource with an asynchronous create and delete:
POST /databasesreturns202 Acceptedonce the request is queued.GET /databases/{id}returns the currentstatus:pending,ready, orfailed.DELETE /databases/{id}returns204 No Contentwhile tear-down continues asynchronously.
Base spec (excerpt)
Section titled “Base spec (excerpt)”paths: /databases: post: operationId: createDatabase x-speakeasy-entity-operation: Database#create requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/DatabaseRequest" responses: "202": description: Database creation accepted; provisioning asynchronously. content: application/json: schema: $ref: "#/components/schemas/Database"
/databases/{id}: parameters: - name: id in: path required: true schema: type: string get: operationId: getDatabase x-speakeasy-entity-operation: Database#read responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Database" "404": description: Not found delete: operationId: deleteDatabase x-speakeasy-entity-operation: Database#delete responses: "204": description: Deletion accepted; tear-down is asynchronous.
components: schemas: Database: type: object required: [id, status] properties: id: type: string name: type: string status: type: string enum: [pending, ready, failed]Overlay: add polling to create and delete
Section titled “Overlay: add polling to create and delete”Apply polling as an overlay so the base spec stays untouched. The overlay does two things:
- Declares named polling strategies on the
GEToperation. - Wires those strategies into the create and delete entity operations so Terraform waits after each lifecycle step.
overlay: 1.0.0info: title: Add async polling to Database version: 0.0.0actions: # 1. Define polling strategies on the read operation. - target: $.paths['/databases/{id}'].get update: x-speakeasy-polling: - name: WaitForReady successCriteria: - condition: $statusCode == 200 - condition: $response.body#/status == "ready" failureCriteria: - condition: $statusCode == 200 - condition: $response.body#/status == "failed" - name: WaitForDeleted successCriteria: - condition: $statusCode == 404
# 2. Attach the read operation as a follow-up to create and delete, # using each polling strategy. - target: $.paths['/databases/{id}'].get update: x-speakeasy-entity-operation: - Database#read - entityOperation: Database#create#2 options: polling: name: WaitForReady delaySeconds: 2 intervalSeconds: 5 limitCount: 120 - entityOperation: Database#delete#2 options: polling: name: WaitForDeleted intervalSeconds: 5 limitCount: 60Apply the overlay alongside the base spec with speakeasy overlay apply -s openapi.yaml -o overlay.yaml, or attach it to a Terraform source with speakeasy configure sources.
What this produces
Section titled “What this produces”- After
terraform applycreates a database, the provider callsGET /databases/{id}on a 5-second interval, after a 2-second initial delay, untilstatus == "ready". Polling fails fast ifstatus == "failed"or after 120 attempts. - After
terraform destroy, the provider polls until theGETreturns404, confirming tear-down completed. - The
#2suffix onDatabase#create#2andDatabase#delete#2tells the generator to run theGETas a second step of the create or delete lifecycle. That is how the read operation is reused as a wait step without colliding with the normalDatabase#read.
Tuning knobs
Section titled “Tuning knobs”The behavior of each strategy is controlled by a small set of fields on x-speakeasy-polling. Per-resource values under options.polling (shown in the overlay above) override the defaults declared on the operation.
delaySeconds: Initial wait before the first poll.intervalSeconds: Time between polls.limitCount: Maximum poll attempts before giving up.successCriteria: All conditions must be true within a single poll response to stop polling successfully.failureCriteria: All conditions must be true within a single poll response to stop polling and surface an error. Use multiple criteria to assert against the same response (e.g.$statusCode == 200and$response.body#/status == "failed"); failure does not compose across separate polls.
Conditions use OpenAPI runtime expressions. The two most common contexts are $statusCode and $response.body#/<json-pointer>. See the polling reference for the full criterion grammar, including regex matching.