Skip to main content

Link components

After you connect a cloud account, link resources to product components by setting cloud and a resource identifier on the component env. Ductape does the rest when you save.

The pattern

Every linked env follows the same shape:

{
slug: 'prd',
cloud: 'prod_aws', // connection tag — not a connection ID
// + resource-specific fields (instance, bucketName, queueName, …)
}

On save, Ductape:

  1. Lists resources in the linked account (if needed)
  2. Imports the resource if it already exists, or provisions a new one
  3. Stores credentials as workspace secrets ($Secret{...})
  4. Sets authMode: 'cloud_connection' on the env

At runtime, connect(), upload(), produce(), etc. resolve secrets and refresh cloud credentials automatically.

Examples by component

Database (PostgreSQL)

await ductape.databases.create({
product: 'my-product',
tag: 'app-db',
name: 'App Database',
type: 'postgresql',
envs: [{
slug: 'prd',
cloud: 'prod_azure',
instance: 'my-pg-server',
region: 'eastus',
}],
});
ProviderConnection tagKey fields
AWS RDSprod_awsinstance, region, securityGroups (if customer-managed)
GCP Cloud SQLprod_gcpinstance, region
Azure Flexible Serverprod_azureinstance, region
MongoDB Atlasprod_atlasinstance (cluster name)

AWS RDS: New instances are created on save (can take several minutes). Use the same instance across envs to share one RDS; use different names per env for separate instances. Importing existing RDS requires the master password — prefer provision for new databases. See AWS networking.

Storage

await ductape.storage.create({
product: 'my-product',
tag: 'app-storage',
name: 'App Storage',
envs: [{
slug: 'prd',
type: 'aws',
config: {
cloud: 'prod_aws',
bucketName: 'my-app-uploads',
region: 'us-east-1',
},
}],
});
ProviderConfig fields
AWScloud, bucketName, region
GCPcloud, bucketName, location
Azurecloud, containerName, region

Message broker

await ductape.messaging.create({
product: 'my-product',
tag: 'order-events',
name: 'Order Events',
envs: [{
slug: 'prd',
type: 'aws_sqs',
config: {
cloud: 'prod_aws',
queueName: 'order-events',
region: 'us-east-1',
},
}],
});
ProviderConfig fields
AWS SQScloud, queueName, region
GCP Pub/Subcloud, topicName, region
Azure Service Buscloud, queueName, region, namespaceName

Graph

await ductape.graph.create({
product: 'my-product',
tag: 'social-graph',
name: 'Social Graph',
type: 'neptune',
envs: [{
slug: 'prd',
cloud: 'prod_aws',
instance: 'my-neptune-cluster',
region: 'us-east-1',
securityGroups: ['prod-rds'],
}],
});

Ductape resolves and stores connection_url as an encrypted secret. AWS Neptune requires VPC networking.

Vector

await ductape.vector.create({
product: 'my-product',
tag: 'product-vectors',
name: 'Embeddings',
type: 'opensearch',
dimensions: 1536,
envs: [{
slug: 'prd',
cloud: 'prod_aws',
instance: 'my-opensearch-domain',
region: 'us-east-1',
}],
});

Ductape stores endpoint and apiKey from the link draft as encrypted secrets.

Choosing a tier

Before provisioning a new database, graph, or vector store, check what tiers are available for your provider. The tier catalogue is public and requires no auth.

// List all tiers for a provider and resource type
const tiers = await ductape.cloud.tiers.list({
provider: 'aws',
resource_type: 'database',
db_type: 'postgresql',
});
// tiers[0].tiers → [{ name: 'db.t3.micro', label: 'Micro — 2 vCPU, 1 GB RAM', est_cost_per_month: 11.68, free_tier: true, … }, …]

Pass the name value as tier on your provision call. The same API works from the CLI:

# List available tiers
ductape cloud tiers list --provider aws --type database --db-type postgresql

# Then provision with the chosen tier
ductape cloud resources provision -f provision.json --tier db.t3.micro

Tier names map directly to each provider's instance class:

ProviderExample tier names
AWS RDSdb.t3.micro, db.t3.medium, db.r6g.large
GCP Cloud SQLdb-f1-micro, db-n1-standard-2, db-n1-highmem-4
Azure Flexible ServerStandard_B1ms, Standard_D2ds_v4, Standard_E4ds_v4
MongoDB AtlasM0, M10, M30, M50
Neo4j Auraaura-free, aura-professional-2, aura-professional-4

Import vs provision

SituationWhat happens
Resource name exists in the accountImport — link existing resource
Name omitted or resource not foundProvision — create with default template
Component create / update via SDKMaterializer runs list → import or provision automatically

You rarely call import/provision directly unless building custom tooling.

Low-level APIs

Use ductape.cloud.resources when you need explicit control:

// List what's in the account
const { resources } = await ductape.cloud.resources.list({
cloud: 'prod_aws',
service: 'rds',
region: 'us-east-1',
});

// Import an existing server
await ductape.cloud.resources.import({
cloud: 'prod_azure',
service: 'postgresql',
type: 'databases',
product: 'my-product',
component: 'app-db',
env: 'prd',
resource: 'my-pg-server',
});

// Provision a new RDS instance — pick a tier first
await ductape.cloud.resources.provision({
cloud: 'prod_aws',
service: 'rds',
type: 'databases',
product: 'my-product',
component: 'app-db',
env: 'prd',
tier: 'db.t3.micro', // from cloud.tiers.list()
region: 'us-east-1',
dbName: 'myapp',
});

// Provision a GCP Cloud SQL instance
await ductape.cloud.resources.provision({
cloud: 'gcp_prod',
service: 'cloudsql',
type: 'databases',
product: 'my-product',
component: 'app-db',
env: 'prd',
tier: 'db-n1-standard-2',
region: 'us-central1',
});

// Provision an Azure PostgreSQL server
await ductape.cloud.resources.provision({
cloud: 'prod_azure',
service: 'postgresql',
type: 'databases',
product: 'my-product',
component: 'app-db',
env: 'prd',
tier: 'Standard_B1ms',
region: 'eastus',
});

// Provision a message broker topic
await ductape.cloud.resources.provision({
cloud: 'gcp_prod',
service: 'pubsub',
type: 'messageBrokers',
product: 'my-product',
component: 'order-events',
env: 'prd',
topicName: 'order-events',
region: 'us-central1',
});

// Provision a Neptune graph
await ductape.cloud.resources.provision({
cloud: 'prod_aws',
service: 'neptune',
type: 'graphs',
product: 'my-product',
component: 'social-graph',
env: 'prd',
tier: 'db.r5.large',
region: 'us-east-1',
});

// Provision an OpenSearch vector index
await ductape.cloud.resources.provision({
cloud: 'prod_aws',
service: 'opensearch',
type: 'vectors',
product: 'my-product',
component: 'product-vectors',
env: 'prd',
tier: 't3.small.search',
region: 'us-east-1',
});

All cloud APIs take cloud (the connection tag). Omit tier to get a provider default; set it explicitly to control cost.

tier field reference

Component typeRelevant tier examples
databases (RDS)db.t3.micro, db.t3.medium, db.r6g.large
databases (Cloud SQL)db-f1-micro, db-n1-standard-2, db-n1-highmem-4
databases (Azure)Standard_B1ms, Standard_D2ds_v4, Standard_E4ds_v4
databases (Atlas)M0, M10, M30, M50
graphs (Neptune)db.r5.large, db.r5.xlarge
graphs (Aura)aura-free, aura-professional-2, aura-professional-4
vectors (OpenSearch)t3.small.search, r6g.large.search
storagestorage is class-based (e.g. s3-standard, gcs-standard) — use tier for storage class

Use ductape.cloud.tiers.list({ provider, resource_type, db_type }) to get current values with cost estimates before provisioning.

Service reference

Component typeAWS serviceGCP serviceAzure serviceAtlas / Aura
storages3gcsblob
messageBrokerssqspubsubservicebus
databasesrdscloudsqlpostgresqlatlas-cluster
graphsneptunespanner-graphcosmos-gremlinaura-instance
vectorsopensearchvertex-vector-searchazure-search

Workbench

When editing a component env:

  1. Pick a cloud connection (shown by tag)
  2. Select or type a resource name
  3. Save — import/provision runs in the background

The link panel lists all services for the selected provider.

See also