Gateway

Gateways let a Stackie stack expose local cloud-provider API endpoints from a gateway.<provider> block. A gateway block does not run a user process and does not require a local source path:. Instead, stackied builds an embedded Gateways router for the declared provider, binds it to the block’s served port, and owns the HTTP serving task until the stack stops.

Use a Gateway when application code expects AWS, Cloudflare, Azure, or GCP endpoints but you want those calls routed to local Stackie-managed backing services during development.

Stack Declaration

Gateway blocks are typed stack nodes. The YAML is only the serialization surface for the Rust stack model:

my-project:
  mode: managed
  blocks:
    gateway.cloudflare:
      provider: cloudflare
      serves:
        API: { port: 4569, type: api }

The typed rules are:

  • block names start with gateway.
  • provider: is required and must be one of the compiled Gateways providers
  • path: is not allowed
  • command: is not allowed
  • serves: publishes the local endpoint that application blocks consume

Those rules are enforced by the stack parser and are reflected in the generated stack-format specification.

Runtime Lifecycle

When a stack declares a gateway.<provider> block, stackied does not spawn a child process. Instead it asks the embedded Gateways runtime to build a single-provider axum::Router, binds that router to a TCP listener on the allocated port, and owns the serving future for the lifetime of the block.

The GatewayRegistry tracks every live gateway by name, holding both the tokio::task::JoinHandle (so it can be awaited or aborted on shutdown) and a tokio_util::sync::CancellationToken (so graceful shutdown can be signalled through axum’s with_graceful_shutdown future).

Gateways runtimeGatewayRegistrystackied daemonstackie CLIDeveloperstackie up1POST /stackie/v1/gateways { name, provider, port, env }2build_gateway_router(provider, config)3provider-scoped axum::Router4bind TCP listener on served port5register JoinHandle and CancellationToken6201 Created with GatewayInfo7stackie down8DELETE /stackie/v1/gateways/{name}9cancel and await JoinHandle10204 No Content11
Stackie documentation diagram: Gateways runtime, GatewayRegistry, stackied daemon, stackie CLI, #stackie-mermaid-0{font-family:Inter Variable,Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:16px;fill:#f8fafc;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#stackie-mermaid-0 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#stackie-mermaid-0 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#stackie-mermaid-0 .error-icon{fill:#111827;}#stackie-mermaid-0 .error-text{fill:#f8fafc;stroke:#f8fafc;}#stackie-mermaid-0 .edge-thickness-normal{stroke-width:1px;}#stackie-mermaid-0 .edge-thickness-thick{stroke-width:3.5px;}#stackie-mermaid-0 .edge-pattern-solid{stroke-dasharray:0;}#stackie-mermaid-0 .edge-thickness-invisible{stroke-width:0;fill:none;}#stackie-mermaid-0 .edge-pattern-dashed{stroke-dasharray:3;}#stackie-mermaid-0 .edge-pattern-dotted{stroke-dasharray:2;}#stackie-mermaid-0 .marker{fill:#facc15;stroke:#facc15;}#stackie-mermaid-0 .marker.cross{stroke:#facc15;}#stackie-mermaid-0 svg{font-family:Inter Variable,Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:16px;}#stackie-mermaid-0 p{margin:0;}#stackie-mermaid-0 .actor{stroke:#facc15;fill:#1f2937;stroke-width:1;}#stackie-mermaid-0 rect.actor.outer-path[data-look="neo"]{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 rect.note[data-look="neo"]{stroke:hsl(52.6829268293, 60%, 73.9215686275%);fill:#fff5ad;filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 text.actor>tspan{fill:#f8fafc;stroke:none;}#stackie-mermaid-0 .actor-line{stroke:#facc15;}#stackie-mermaid-0 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#stackie-mermaid-0 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#facc15;}#stackie-mermaid-0 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#facc15;}#stackie-mermaid-0 [id$="-arrowhead"] path{fill:#facc15;stroke:#facc15;}#stackie-mermaid-0 .sequenceNumber{fill:#cbd5e1;}#stackie-mermaid-0 [id$="-sequencenumber"]{fill:#facc15;}#stackie-mermaid-0 [id$="-crosshead"] path{fill:#facc15;stroke:#facc15;}#stackie-mermaid-0 .messageText{fill:#f8fafc;stroke:none;}#stackie-mermaid-0 .labelBox{stroke:#facc15;fill:#1f2937;filter:none;}#stackie-mermaid-0 .labelText,#stackie-mermaid-0 .labelText>tspan{fill:#f8fafc;stroke:none;}#stackie-mermaid-0 .loopText,#stackie-mermaid-0 .loopText>tspan{fill:#f8fafc;stroke:none;}#stackie-mermaid-0 .sectionTitle,#stackie-mermaid-0 .sectionTitle>tspan{fill:#f8fafc;stroke:none;}#stackie-mermaid-0 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:#facc15;fill:#facc15;}#stackie-mermaid-0 .note{stroke:hsl(52.6829268293, 60%, 73.9215686275%);fill:#fff5ad;}#stackie-mermaid-0 .noteText,#stackie-mermaid-0 .noteText>tspan{fill:#333;stroke:none;font-weight:normal;}#stackie-mermaid-0 .activation0{fill:#134e4a;stroke:#2dd4bf;}#stackie-mermaid-0 .activation1{fill:#134e4a;stroke:#2dd4bf;}#stackie-mermaid-0 .activation2{fill:#134e4a;stroke:#2dd4bf;}#stackie-mermaid-0 .actorPopupMenu{position:absolute;}#stackie-mermaid-0 .actorPopupMenuPanel{position:absolute;fill:#1f2937;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#stackie-mermaid-0 .actor-man circle,#stackie-mermaid-0 line{fill:#1f2937;stroke-width:2px;}#stackie-mermaid-0 g rect.rect{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));stroke:#facc15;}#stackie-mermaid-0 .node .neo-node{stroke:#facc15;}#stackie-mermaid-0 [data-look="neo"].node rect,#stackie-mermaid-0 [data-look="neo"].cluster rect,#stackie-mermaid-0 [data-look="neo"].node polygon{stroke:url(#stackie-mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 [data-look="neo"].swimlane.cluster rect{filter:none;}#stackie-mermaid-0 [data-look="neo"].node path{stroke:url(#stackie-mermaid-0-gradient);stroke-width:1px;}#stackie-mermaid-0 [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 [data-look="neo"].node .neo-line path{stroke:#facc15;filter:none;}#stackie-mermaid-0 [data-look="neo"].node circle{stroke:url(#stackie-mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 [data-look="neo"].node circle .state-start{fill:#000000;}#stackie-mermaid-0 [data-look="neo"].icon-shape .icon{fill:url(#stackie-mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 [data-look="neo"].icon-shape .icon-neo path{stroke:url(#stackie-mermaid-0-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#stackie-mermaid-0 :root{--mermaid-font-family:Inter Variable,Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;}. Use horizontal scrolling when the full diagram is wider than the visible frame. Generated from Stackie public documentation source.

The env field shown in the lifecycle request is daemon-internal resolved stack state. It can include local credentials for backing services such as Postgres or MinIO, so it is not a public user API and must not be logged, copied into examples, or exposed outside the trusted local daemon boundary.

Provider Compatibility

The provider table is generated from Gateways provider metadata, which derives from the same provider descriptors that build runtime routers and settings UI.

ProviderStack declarationDefault portAccount selectorEmulated service familiesBacking services
Amazon Web Services (AWS)gateway.aws
provider: aws
4566Configured default account ID; AWS SigV4 credentials are parsed for diagnostics but do not embed the account ID.S3
DynamoDB
SQS
SNS
Lambda
RDS
ElastiCache
SES
Secrets Manager
SSM
IAM
STS
KMS
EventBridge
Step Functions
Kinesis
Cognito
CloudWatch
Athena
Route 53
CloudFormation
EC2
ECS
EKS
ECR
App Runner
Postgres via DATABASE_URL
MinIO via MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY
Kafka via KAFKA_BROKERS
SMTP via SMTP_HOST/SMTP_PORT
DuckDB analytics for Athena
Stackie block registry for managed-service endpoints
Google Cloud Platform (GCP)gateway.gcp
provider: gcp
4567Path segment after /projects/ or /v1/projects/.Cloud Storage
Pub/Sub
Firestore
Cloud SQL
Cloud Functions
Secret Manager
IAM
KMS
Eventarc
Logging
Monitoring
BigQuery
GKE
Cloud Run
Artifact Registry
Cloud Build
Postgres via DATABASE_URL
DuckDB analytics for BigQuery
Stackie block registry for managed-service endpoints
Microsoft Azuregateway.azure
provider: azure
4568Path segment after /subscriptions/.Blob Storage
Service Bus
Cosmos DB
Azure SQL
Functions
Key Vault
Entra ID
Event Grid
Monitor
DNS
AKS
Container Instances
Container Registry
Container Apps
Postgres via DATABASE_URL
MinIO via MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY
Stackie block registry for managed-service endpoints
Cloudflaregateway.cloudflare
provider: cloudflare
4569Path segment after /accounts/.R2
Queues
D1
KV
Workers
DNS
Hyperdrive
Pages
Access
Postgres via DATABASE_URL
MinIO via MINIO_ENDPOINT/MINIO_ACCESS_KEY/MINIO_SECRET_KEY
Stackie block registry for managed-service endpoints

Generated from Gateways provider metadata; do not edit this table by hand.

Health Check

Every Gateway exposes GET /gateway/health on its served port. The response reports the Gateways runtime version, configured region/account, registered provider, and which optional backing services are configured.

Runtime Boundaries

Gateways are local development emulators. They are not a security boundary and do not validate real cloud signatures before accepting requests. Bind and expose them only in trusted development environments.

Gateway blocks run in-process inside stackied, not inside a sandboxed block. They can still route to Stackie-managed backing services through the block endpoint registry when those services are configured.

Limitations

Gateways emulate provider APIs for local development and compatibility testing. They are not a cloud-provider control plane, and per-operation behavior depends on the provider service family listed above and the backing services available in the current stack.