Speakeasy Logo
Skip to Content

Terraform

Per-resource security and server URLs in Terraform providers

Speakeasy Team

Speakeasy Team

December 8, 2025 - 4 min read


Large infrastructure companies often expose multiple APIs under a single platform: a cloud management API for creating and configuring resources, plus specialized APIs for managing individual databases, clusters, or other infrastructure components. Each API may have its own endpoint and credentials.

Terraform’s configuration model presents a challenge here. It provides only two levels of configuration: global provider settings and individual resource settings. There’s no concept of grouping related resources with shared configuration. This limitation meant you either needed to create separate Terraform providers for each API or write significant custom code to handle the complexity.

We’ve added support for per-resource security and server URLs in Terraform provider generation. This feature allows resource groups to declare their own endpoints and credentials while staying within a single provider.

The challenge with multi-API infrastructure platforms

Infrastructure platforms often separate their control plane APIs from their data plane APIs. Here’s a common pattern:

  • Cloud API: Manages users, organizations, clusters, and high-level resources at https://api.platform.com
  • Cluster API: Manages resources within a specific cluster at https://cluster-abc123.platform.com with cluster-specific credentials

Take MongoDB Atlas as a real-world example. The Atlas Admin API handles projects, clusters, and organizational resources. But once a cluster exists, managing databases, collections, and users within that cluster requires connecting to the cluster’s specific API endpoint with database-specific credentials.

The traditional approach: multiple providers

The technically correct solution in Terraform is to create separate providers:

# Configure the cloud management provider provider "platform_cloud" { api_token = var.cloud_token api_url = "https://api.platform.com" } # Create a cluster using the cloud provider resource "platform_cloud_cluster" "main" { name = "production" } # Configure a separate provider for cluster management provider "platform_cluster" { api_token = var.cluster_token server_url = platform_cloud_cluster.main.endpoint } # Manage resources within the cluster resource "platform_cluster_topic" "orders" { provider = platform_cluster name = "orders" }

This works, but requires:

  • Maintaining two separate Terraform providers
  • Users downloading and managing multiple provider binaries
  • Coordination between two codebases for API changes
  • Complex provider aliasing in Terraform configurations

Per-resource configuration

With per-resource security and server URL support, resources can accept their own endpoint and credentials directly:

provider "platform" { api_token = var.cloud_token } # Create a cluster resource "platform_cluster" "main" { name = "production" } # Configure resources within the cluster - no second provider needed resource "platform_cluster_topic" "orders" { name = "orders" server_url = platform_cluster.main.endpoint api_token = var.cluster_token }

The cluster topic resource accepts its own server_url and api_token configuration, pulling values directly from the cluster resource output. Users write a single Terraform configuration that handles both layers without managing multiple providers.

How it works

Per-resource configuration uses the OpenAPI specification’s operation-level security and server definitions. When your OpenAPI spec declares different servers or security requirements for specific operations, Speakeasy can expose these as resource-level configuration options in the Terraform provider.

This feature is disabled by default. Not every API with operation-level configuration needs per-resource settings exposed to end users. Enable it selectively for resources that genuinely require different endpoints or credentials.

When to use per-resource configuration

This feature fits specific architectural patterns:

  • Admin APIs and data APIs: Separate management planes and control planes with distinct authentication
  • Multi-tenant infrastructure: Resources that connect to tenant-specific endpoints
  • Cluster-based systems: Managing both cluster provisioning and internal cluster resources
  • Database platforms: Controlling database instances plus in-database resources like schemas and users

Configuration from a user perspective

Users configure per-resource settings just like any other resource attribute. The difference is these settings control how the provider connects to the API rather than what data gets sent.

Here’s what it looks like with environment-specific clusters:

resource "platform_cluster" "staging" { name = "staging" } resource "platform_cluster" "production" { name = "production" } # Same resource type, different endpoints resource "platform_cluster_topic" "staging_orders" { name = "orders" server_url = platform_cluster.staging.endpoint api_token = var.staging_cluster_token } resource "platform_cluster_topic" "production_orders" { name = "orders" server_url = platform_cluster.production.endpoint api_token = var.production_cluster_token }

The provider handles the different endpoints automatically based on the configuration. Users don’t need provider aliases or complex meta-arguments.

Next steps

Per-resource security and server URL support is available now for Terraform provider generation. When your OpenAPI specification includes operation-level servers or security schemes, you can choose which resources should expose these as configuration options.

If you’re building providers for infrastructure platforms with multiple API layers, or migrating existing providers with these patterns, check out the documentation:

Last updated on

Build with
confidence.

Ship what's next.