Skip to main content
This guide covers best practices for building production-quality providers. Follow these guidelines to create providers that are reliable, secure, and easy to maintain.

Idempotency

Idempotency is the most critical requirement for providers. Lifecycle methods may be called multiple times with the same input due to retries, restarts, or redelivery.
See Lifecycle Methods - Idempotency Requirements for patterns on implementing idempotent create, update, and delete operations. Key principles:
  • Create: Handle “already exists” errors by retrieving the existing resource
  • Update: Return existing outputs when nothing changed
  • Delete: Treat “not found” as success, not failure

Error Handling

Use Specific Exception Types

Choose exception types that communicate the nature of the failure:

Let Unexpected Errors Propagate

Do not catch-all exceptions. Let unexpected errors propagate with full tracebacks for debugging:

Provide Actionable Error Messages

Error messages should help users understand what went wrong and how to fix it:

Credentials Management

Accept Credentials as Configuration

Providers should accept credentials as configuration, not rely on ambient credentials:
This approach:
  • Works in multi-tenant environments where each user has different credentials
  • Makes credential requirements explicit in the schema
  • Enables users to manage credentials via Pragma secrets

Use FieldReference for Secrets

Document that users should use FieldReference to pass credentials from a secret resource:

Never Log Credentials

Ensure credentials never appear in logs or error messages:

Performance

Cache Clients Within Lifecycle Methods

Create API clients once per lifecycle invocation, not per operation:

Minimize API Calls in Updates

Only call external APIs when configuration actually changed:

Use Async Where Possible

Lifecycle methods are async. Use async API clients when available:

Common Mistakes

Forgetting Idempotency

The most common mistake is assuming lifecycle methods only run once:

Mutable State Between Calls

Do not store state on the resource instance between lifecycle calls:

Missing Immutable Field Validation

Certain fields cannot be changed in-place. Validate these in on_update:

Not Using self.outputs

In on_update and on_delete, the previous outputs are available via self.outputs. Use them:

Incomplete Cleanup in on_delete

Delete all resources created by on_create, not just the primary resource:

Testing

Use ProviderHarness

The SDK provides ProviderHarness for testing lifecycle methods without real infrastructure:

Test Idempotency Explicitly

Write tests that verify idempotent behavior:

Test Immutable Field Validation

Verify that changing immutable fields fails appropriately:

Mock External Services

Use fixtures to mock external API clients:

What’s Next

Lifecycle Methods

Deep dive into on_create, on_update, and on_delete.

SDK Reference

Full SDK documentation.