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:
- TypeScript
- Java
- Go
- .NET
{
slug: 'prd',
cloud: 'prod_aws', // connection tag — not a connection ID
// + resource-specific fields (instance, bucketName, queueName, …)
}
Map.of(
"slug", "prd",
"cloud", "prod_aws", // connection tag — not a connection ID
// + resource-specific fields (instance, bucketName, queueName, …)
)
{
"slug": "prd",
"cloud": "prod_aws", // connection tag — not a connection ID
// + resource-specific fields (instance, bucketName, queueName, …)
}
{
["slug"] = "prd",
["cloud"] = "prod_aws", // connection tag — not a connection ID
// + resource-specific fields (instance, bucketName, queueName, …)
}
On save, Ductape:
- Lists resources in the linked account (if needed)
- Imports the resource if it already exists, or provisions a new one
- Stores credentials as workspace secrets (
$Secret{...}) - 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)
- TypeScript
- Java
- Go
- .NET
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',
}],
});
ductape.databases.create(Map.of(
"product", "my-product",
"tag", "app-db",
"name", "App Database",
"type", "postgresql",
envs: [Map.of(
"slug", "prd",
"cloud", "prod_azure",
"instance", "my-pg-server",
"region", "eastus"
)]
));
client.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",
}],
});
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",
}],
});
| Provider | Connection tag | Key fields |
|---|---|---|
| AWS RDS | prod_aws | instance, region, securityGroups (if customer-managed) |
| GCP Cloud SQL | prod_gcp | instance, region |
| Azure Flexible Server | prod_azure | instance, region |
| MongoDB Atlas | prod_atlas | instance (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
- TypeScript
- Java
- Go
- .NET
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',
},
}],
});
ductape.storage.create(Map.of(
"product", "my-product",
"tag", "app-storage",
"name", "App Storage",
envs: [Map.of(
"slug", "prd",
"type", "aws",
config: Map.of(
"cloud", "prod_aws",
"bucketName", "my-app-uploads",
"region", "us-east-1"
)
)]
));
client.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",
},
}],
});
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",
},
}],
});
| Provider | Config fields |
|---|---|
| AWS | cloud, bucketName, region |
| GCP | cloud, bucketName, location |
| Azure | cloud, containerName, region |
Message broker
- TypeScript
- Java
- Go
- .NET
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',
},
}],
});
ductape.messaging.create(Map.of(
"product", "my-product",
"tag", "order-events",
"name", "Order Events",
envs: [Map.of(
"slug", "prd",
"type", "aws_sqs",
config: Map.of(
"cloud", "prod_aws",
"queueName", "order-events",
"region", "us-east-1"
)
)]
));
client.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",
},
}],
});
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",
},
}],
});
| Provider | Config fields |
|---|---|
| AWS SQS | cloud, queueName, region |
| GCP Pub/Sub | cloud, topicName, region |
| Azure Service Bus | cloud, queueName, region, namespaceName |
Graph
- TypeScript
- Java
- Go
- .NET
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.graph.create(Map.of(
"product", "my-product",
"tag", "social-graph",
"name", "Social Graph",
"type", "neptune",
envs: [Map.of(
"slug", "prd",
"cloud", "prod_aws",
"instance", "my-neptune-cluster",
"region", "us-east-1",
securityGroups: ['prod-rds']
)]
));
client.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'],
}],
});
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
- TypeScript
- Java
- Go
- .NET
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.vector.create(Map.of(
"product", "my-product",
"tag", "product-vectors",
"name", "Embeddings",
"type", "opensearch",
"dimensions", 1536,
envs: [Map.of(
"slug", "prd",
"cloud", "prod_aws",
"instance", "my-opensearch-domain",
"region", "us-east-1"
)]
));
client.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",
}],
});
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.
- TypeScript
- Java
- Go
- .NET
// 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, … }, …]
// List all tiers for a provider and resource type
Map<String, Object> tiers = ductape.cloud.tiers.list(Map.of(
"provider", "aws",
"resource_type", "database",
"db_type", "postgresql"
));
// tiers[0].tiers → [Map.of( "name", "db.t3.micro", "label", "Micro — 2 vCPU, 1 GB RAM", "est_cost_per_month", 11.68, "free_tier", true, … ), …]
// List all tiers for a provider and resource type
tiers := client.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, … }, …]
// List all tiers for a provider and resource type
var 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:
| Provider | Example tier names |
|---|---|
| AWS RDS | db.t3.micro, db.t3.medium, db.r6g.large |
| GCP Cloud SQL | db-f1-micro, db-n1-standard-2, db-n1-highmem-4 |
| Azure Flexible Server | Standard_B1ms, Standard_D2ds_v4, Standard_E4ds_v4 |
| MongoDB Atlas | M0, M10, M30, M50 |
| Neo4j Aura | aura-free, aura-professional-2, aura-professional-4 |
Import vs provision
| Situation | What happens |
|---|---|
| Resource name exists in the account | Import — link existing resource |
| Name omitted or resource not found | Provision — create with default template |
Component create / update via SDK | Materializer 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:
- TypeScript
- Java
- Go
- .NET
// 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',
});
// List what's in the account
Map<String, Object> Map.of( resources ) = ductape.cloud.resources.list(Map.of(
"cloud", "prod_aws",
"service", "rds",
"region", "us-east-1"
));
// Import an existing server
ductape.cloud.resources.import(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"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
ductape.cloud.resources.provision(Map.of(
"cloud", "prod_aws",
"service", "opensearch",
"type", "vectors",
"product", "my-product",
"component", "product-vectors",
"env", "prd",
"tier", "t3.small.search",
"region", "us-east-1"
));
// List what's in the account
const { resources } = client.cloud.resources.list({
"cloud": "prod_aws",
"service": "rds",
"region": "us-east-1",
});
// Import an existing server
client.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
client.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
client.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
client.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
client.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
client.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
client.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",
});
// List what's in the account
var { 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 type | Relevant 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 |
storage | storage 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 type | AWS service | GCP service | Azure service | Atlas / Aura |
|---|---|---|---|---|
storage | s3 | gcs | blob | — |
messageBrokers | sqs | pubsub | servicebus | — |
databases | rds | cloudsql | postgresql | atlas-cluster |
graphs | neptune | spanner-graph | cosmos-gremlin | aura-instance |
vectors | opensearch | vertex-vector-search | azure-search | — |
Workbench
When editing a component env:
- Pick a cloud connection (shown by tag)
- Select or type a resource name
- Save — import/provision runs in the background
The link panel lists all services for the selected provider.
See also
- Cloud overview — the full three-step flow
- Cloud connections — create, complete, validate
- AWS networking — RDS and Neptune security groups
- Provider guides — per-provider IAM and credentials
- CLI cloud commands