Order something.
Two backend services that never call each other. Work flows one way through a message queue; the result comes back through a storage bucket. Here's what happens when you click:
- You place an order. The browser calls order-intake — the only service that's reachable from the internet. It publishes your order to the orders Pub/Sub topic and answers immediately with an order id. It does not wait for shipping.
- Pub/Sub wakes the worker. fulfillment is private — you can't call it, only Pub/Sub can push messages to it. It picks up your order, takes about 5 seconds to "ship" it, then writes the result into the order-status bucket. It's the only identity with write access there.
- You check the status. The browser asks order-intake again; it reads the bucket (it holds a read-only grant) and reports pending or shipped. Check right after ordering and you'll catch it pending.
No order yet.
One file in, this much out
The whole demo is this one fluffy-chainsaw.yaml — hover a block to see what deploying it provisions.
topics:
orders: {}
shipments: {}
Two Pub/Sub topics — each service can publish only to its own topic, nothing else.
buckets:
order-status:
location: US
One bucket, one prefix, opposite permissions — fulfillment writes, order-intake only reads.
runners:
order-intake:
uses:
publishes: [orders]
buckets:
- name: order-status
prefix: status/
viewer: true
trigger: { http: true }
The only internet-reachable service — publishes orders, reads status.
fulfillment:
uses:
publishes: [shipments]
buckets:
- name: order-status
prefix: status/
writer: true
trigger:
subscriptions:
- topic: orders
path: /events
ack_deadline: 30
A private worker — only the queue can reach it, never the internet; a public subscriber is a build error.
Full resources + IAM ledger in the example README.
What a deploy spins up
One command. Watch the resources land.
$