Where
newsletters
get discovered.
Find your next favorite read and join the conversation under every article. For writers, it's where new readers find you, your audience grows, and every article sparks a discussion.
Featured
An editor's pick worth your time

Provisioning Infrastructure with Terraform from AsyncAPI
Provisioning Infrastructure with Terraform from AsyncAPI When your AsyncAPI says one thing and your Kafka platform does another, people stop trusting the API. In Arcadia the AsyncAPI file stays the source of truth for the platform too: we generate the Terraform for topics, schemas and ACLs from it, merging to develop provisions the development cluster, and each release packs that Terraform so the same files are promoted to pre and prod. When we talk about API First we usually think about the code. We generate models and clients from the API, we validate messages against it, and we test that producers and consumers do what the spec says. But in an event driven architecture, part of the API lives in the broker: the topics, their partitions and retention, the schema compatibility, and the ACLs that say who can read and who can write. This is not only for the platform. The producer and the consumer need this information too, to design and configure their applications: Three partitions or one, it’s not the same, because with three you can run three consumers in parallel and with one you can’t. One week of retention or one year, it’s not the same, because it decides how far back a consumer can replay. A compacted topic or a normal one, it’s not the same either. And schema compatibility even decides who deploys first: with FORWARD the producer can go first, and with BACKWARD the consumers have to go first. So everybody needs this information, and the natural place for it is the AsyncAPI. Now imagine the AsyncAPI says seven days, but someone changed it to one day in the Confluent console. Or the AsyncAPI says nothing at all, because the retention lives in a Terraform file in another repository. People stop reading the API and start asking someone, and from that moment nobody trusts the API. Creating Kafka topics is easy, there are scripts, the Confluent CLI, JulieOps, Jikkou or Terraform for that. What goes wrong is that we write the same information twice, once in AsyncAPI and once in the provisioning tool, and then we hope both stay in sync forever. In Arcadia we write it only once, in the AsyncAPI file. Every service that talks Kafka already has one, with the topics it owns, their partitions, the Avro schemas of each message, and the topics it reads from other teams. With the ZenWave AsyncAPI Ops plugin we generate the Terraform from that file, in the same way we generate code, docs or the Event Catalog. Nobody edits that Terraform by hand, so if you want to change something in the platform, you change the AsyncAPI first. What the generator creates The plugin reads one or more AsyncAPI files and writes a folder with Terraform files: topics.tf with the Kafka topics that the service owns, plus their retry and dead letter topics. schemas.tf with the Avro subjects for the Schema Registry. acls.tf with the read and write permissions, which come from the send and receive operations. The service account for the service, when you use serviceAccountMode=managed. The Avro schemas, bundled so Terraform can upload them. It knows which topics belong to the service because they are declared inline with an address. Channels that come with a $ref from another team’s API are dependencies, so for those it only creates the ACLs to read them, and never the topic. This is why in Arcadia we pass both files together, asyncapi.yml with what the service publishes and asyncapi-client.yml with what it consumes. This is how a channel looks in orders-checkout-api, and the topic size comes from a shared trait that every team can reuse: channels: order-created-event-v1: address: orders-checkout.order-created.event.avro.v1 x-visibility: global messages: OrderCreatedEvent: $ref: "#/components/messages/OrderCreatedEvent" bindings: kafka: partitions: 3 replicas: 3 topicConfiguration: cleanup.policy: [ "delete" ] retention.ms: 604800000 retention.bytes: 1000000000 delete.retention.ms: 86400000 max.message.bytes: 1048588 x-env-server-overrides: develop: partitions: 1 replicas: 1 topicConfiguration: cleanup.policy: [ "delete" ] retention.ms: 604800 And this is the command that the pipeline runs, more or less: jbang zw -p AsyncAPIOpsGeneratorPlugin \ apiFiles=asyncapi.yml,asyncapi-client.yml \ templates=TerraformConfluent \ serviceAccountMode=managed \ server=develop \ targetFolder=target/terraform The server option chooses which entry of x-env-server-overrides the generator applies on top of the Kafka bindings. This is the kafkaTopicS trait from api-contract-commons: kafkaTopicS: bindings: kafka: partitions: 3 replicas: 3 x-env-server-overrides: dev: partitions: 1 replicas: 1 staging: partitions: 3 replicas: 2 NOTE: Channel traits are available on AsyncAPI v3.2.0 and later So the same topic gets one partition with server=dev, and three partitions with server=staging or with any other server, like production, that has no override. For Arcadia we use Confluent Cloud, but there are also templates for plain Kafka with an open source Schema Registry. Cluster IDs, endpoints and credentials never go inside the AsyncAPI file. The pipeline injects them from GitHub secrets and variables, and a small shared overlay in terraform/common adds the provider configuration and some safe defaults. Two different rhythms Once we can generate Terraform, we still need to decide when to apply it and where, and development and production don’t move at the same speed. In development you want to see your new topic as soon as you merge, because you are going to test against it this afternoon. But in production you want to apply only what was released, and only when somebody decides it is time. So in api-product-workflows we have one path for develop and another one for releases: WhenWhat happensWorkspace You push to any branch or open a PRGenerate and terraform plan, nothing is applied<repo>-develop You merge to developGenerate, plan and apply<repo>-develop You release asyncapi-allGenerate from the release tag, validate, zip and attach to the GitHub releasenone You promote a releaseDownload the zip and apply it<repo>-pre, then <repo>-prod Every service has one Terraform Cloud workspace per environment, and the name is always the repository name plus the environment. The console and pipeline illustrations below use example values to explain the workflow; they are not captures of live infrastructure. Merge to develop, and develop is provisioned Service repositories don’t need a special workflow for this. Their normal artifact-ci.yml calls the shared artifact-ci.yml, the same one that validates the APIs, and this one has two extra jobs for Kafka. First it looks at what changed in the commit, and if an asyncapi or asyncapi-client artifact changed, or any .avsc file in the repository, it selects all the Kafka contracts of that service as one unit. Then the kafka-plan job runs provision-kafka-plan.yml. It asks the architecture manifest which AsyncAPI files belong to this repository, generates the Terraform and makes a plan against the develop workspace. This happens in every branch and every pull request, so a reviewer can see what is going to change before the merge. When the push is on the develop branch, a second job, kafka-develop, runs provision-kafka-develop.yml. It does the same generation and plan, and then it applies, with no approval: # No approval gate: a successful plan against develop applies immediately. - name: Terraform apply run: terraform apply -auto-approve tfplan We do this on purpose, because develop is where we want fast feedback: you merge your new event into develop, and some minutes later the topic, the schema and the ACLs exist in the development cluster. The apply also records a Terraform output called provisioned_from with the value develop@<commit sha>, so you can always ask the workspace which commit it was built from. Release, and the Terraform is packed For production we don’t regenerate anything at deploy time, because then what you deploy could be different from what you tested. When a team releases its Kafka contracts with artifact-release.yml and artifact=asyncapi-all, the release job publishes the API as usual and creates the tag release/asyncapi-all/vX. After that, a job called release-kafka calls provision-kafka-release.yml, which: Checks out the service at that exact release tag. Generates the Terraform with the prod server profile. Runs terraform init -backend=false and terraform validate, offline, without touching any cluster. Writes a RELEASE.json with the version and the AsyncAPI files that are inside. Zips everything as <repo>-asyncapi-all-vX-terraform.zip and attaches it to the GitHub release. Nothing is applied in this step. The Terraform Cloud backend stays as a template, cloud.tftpl, with the workspace name still empty, because the bundle doesn’t know yet where it will be applied, and that is why the same zip can go to pre today and to prod next week, once somebody approves it. Promote from environment to environment To apply a release, the service calls provision-kafka-promote.yml by hand: jobs: promote-kafka: uses: arcadia-editions/api-product-workflows/.github/workflows/provision-kafka-promote.yml@main with: service_repo: orders-checkout-api target_env: pre # or: prod version: "1.4.0" # only for pre secrets: inherit For pre you choose the version, and the workflow downloads the zip from that release, renders cloud.tf for the <repo>-pre workspace, plans, applies, and saves the version in provisioned_from. For prod you cannot choose a version, and this is my favourite part. The workflow reads provisioned_from from the pre workspace and applies exactly that same release in prod, so prod can only receive what was already running in pre and the two environments cannot drift apart by mistake. The pipeline doesn’t approve anything by itself, because approving a release is part of your organization’s process, with its change requests, release boards or whatever your company uses. The pipeline is only the technical part: once the release is approved offline, somebody runs the promotion manually, first to pre and then to prod. There is also a provision-kafka-destroy.yml to remove an environment, and to run it you need to type the exact workspace name, because there is no way back. The AsyncAPI file is the source Service teams only edit their AsyncAPI file and their Avro schemas, as they already do, and the pipelines take care of develop, of the release package and of the promotion to pre and prod. The platform team, on their side, owns the shared overlay and the credentials, and decides which defaults every topic gets. You can read about all the options of the generator in the AsyncAPI Ops plugin docs, and all the workflows of this article are in arcadia-editions/api-product-workflows. Originally published at ivangsa.com.
Jump into the discussion
Threads people are talking in right now
Joyce Stack@joycestack· 2dI love your writing and wanna be in your teams. This feels very relevant to my own situation with discussions with my manager at the moment. I'm fearful of the end of year review. I've had a turbulent year personally and I've have had feedback on some negative engagements and delivery. I accept the feedback. Work just wasn't a priority for me this year and I coasted because LIFE.
Samir Amzani@samz· 1wThank you, Kin. Agreed, the speed of the shift surprised me too. Twenty months ago we were comparing SDK generators on features, and now the question is which ones will still exist 😅
Jack Lhasa@moonshadow· 1wThink you’ve got it right. The last year on SubStack has seen. The addition is 3 features no one asked for, and did nothing but alienate the writers there. Writers who didn’t have a need for short videos, or podcasts, or AI detector that is another AI and lie about its own accuracy. Pangram claims a 90+% accuracy. I ran experiments including over 30 articles ran through Pangram. Not one was correctly identified. Not one in 30. Most weren’t difficult, like an article I wrote that was flagged as 100% AI, and one that was fully generated with no changes from me that it ID’d at 100% human. As I went in u mixed AI into writing in different ways, but Pangram never recognized the mixes. What each of these new features had was a negative effect on the community. Video and podcast formulas were obviously pandering in to a completely different kind of user. The Pangram integration caused 6 months of arguments as to the ethical implications it brought along with several new authors that were being courted by the largest publishers, suddenly developed rumors of possible AI content. Two lost multimillion dollar publishing deals. Just because of of rumors, these brand new authors had careers destroyed forever and lost lucrative contracts with major publishers. Pangram brought with it only suspicion. It didn’t decrease slop(which I’m almost certain has nothing to do with AI, and is actually the result of normal living people who are just bad writers). By embracing an AI judgement machine that could only be used by authors and readers, and no result that would actually punish the users in anyway, absolutely destroyed the community. It caused months of frustration from authors, and created a space where any article about AI becoming the norm.
Domain Modeling with ZDL: Aggregates, Commands, Events, and State Machines
Event-Driven Architecture Notes by Iván García
1 replyactive 2w agoJack Lhasa@moonshadow· 2wI wish I understood more of this. A lot of it sounds like it would make my notes and world building easier
Samir Amzani@samz· 2wThanks Kin, and thanks for putting real numbers on what many of us only suspected, looking forward to OpenLint bright future
Newsletter of the week
One publication we think you'll love
Rising newsletters
Growing fast this week
On this day
From the archives
Most discussed
Where the conversation is busiest
Editor's picks
Handpicked reads from across the network

La chica de la ensalada de pollo
La Mínima-lista
From Event Storming to ZFL: Translating Business Flows into Code
#BlinkTank: What Shopify is telling AI agents about your store
On Fathers and Father Figures
Your Body Isn't the Problem
If nights are when it all crashes in…here is a tool to help
Hidden gems
Underrated reads you may have missed
Apple’s Key Innovations Buried Beneath the Noise of a Camera Button
Apple’s keynote like the past few years was boring as all heck. But two key innovations that aren’t sexy were announced and nobody is talking about it due to a (camera) button. Lowering the barrier of entry to hearing aids Airpods Pro 2 now are FDA approved as a hearing aid. So many people need hearing aids and won’t get them. I have three people in mind when I am writing this article. Mid-range hearing loss is what most people in the 20-50 age range have. Typically the easie
Pup On Tech

Kaffebox Advent Calendar Day 5
Advent calendar day 5 enhanced v20:00/270.1641671× This is day five of the Kaffebox Advent Calendar. Today we're brewing a Costa Rican from the Montaro family roasted by Morgon out of Sweden. It's a honey process and 1900 meters above sea level. This is actually our second brew of this today. The first brew we followed the exact recipe 18 to 300, 50 gram bloom, 100 grams at 30 seconds, 100 grams more at one minute, and 50 grams at 1:30. We did 18 clicks on the Q Air for that. Now we are brewi
Pup On Tech
You don’t *need* a funnel (not even the big guys do)
Digitalie - Creative Marketing Strategies

Not another Serverless AI - LMI and EventBridge along with SAM making noise 🚀☁️ #102
In the previous issue, AI Agents on Serverless🚀☁️ #101 we looked into how the AI Agents are deployed on Serverless. The conversation around AI automation has officially shifted. We’ve spent the last two years hyper-focused on the brains—the models, the prompts, and the agentic logic. Something from the recent announcement that catches my attention is - SAM CLI + BuildKit = True Velocity: We are writing features faster than ever, which means slow, sequential container builds are the ultimate bottleneck. By bringing native BuildKit support into the SAM CLI, AWS enables multi-stage builds to execute independent steps in parallel. Layer caching now tracks file-level changes instead of rebuilding entire chunks from scratch. Your deployment loop drops from minutes to seconds, matching the speed of thought. Predictable Cost Grid via EventBridge Scheduler: Running high-memory, warm instances full-blast at 3 AM when your engineering team is asleep is a massive waste of cloud budget. Amazon EventBridge Scheduler just added 619 new SDK API actions—including direct support for Lambda Managed Instances. Without writing a single line of custom integration code, you can set a time-based cron schedule to scale your LMI capacity up at 8:30 AM and drop it down to zero at night. That is true, precise control over your capacity provisioning, natively managed by the cloud. Build optimization, scalability at ease! That’s the era of Serverless we want to be in with the AI Agents taking over. ⭐ Pick of the month This month’s Pick is “Event-Driven Architecture”. Lee Gilmore breaks down Automated Certificate Generation with Event-Driven Serverless Pipelines on AWS and how crucial domain events and SQS queues are, with a complete code walkthrough. Jones Zachariah Noel’s blog on what is event driven architecture and how do you build one helps you understand EDA as a pattern; it’s all in plain sight in most serverless architectures. 🚀 AWSome content to learn from Ayesha Siddiqua talks about Serverless in 2026: hype or the real deal for startups? The honest answer is both, depending on what you are building, and a takeaway decision framework for choosing the best one. Ran Isenberg address if AWS Lambda Tenant Isolation Mode enough for SaaS? with the internals of tenant isolation mode and what exactly it solves with isolation in SaaS world. Werner Vogels and the Lambda Networking team - Ravi Nagayach, Prashant Singh, Kshitij Gupta blog on the invisible engineering behind Lambda’s network with VPC and cold starts, along with the challenges tackled! Ganesh M puts down a Mastering Serverless Security: A Guide to AWS IAM and Resource-Based Policies with IAM and the best practices and some of the pitfalls to avoid. Oscar Cortes Bracho debates on Is AgentCore the New Lambda? As AgentCore enables building agents in a serverless way, with some experiments of using AgentCore with other AWS Services. Efi Merdler-Kravitz builds out durable functions in action From Urine to the Cloud: A Journey from Kidney Physiology to Computer Vision with LDF being the backbone for the solution. Luciano Mammino is writing middlewares for Rust Lambda functions and shares the middleware pattern and reusable code with tower, and also compares it to the middleware pattern from NodeJS runtime. Darryl Ruggles shares on S3 Files: The End of Download-Process-Upload (with Terraform) with the after pattern of file system with S3 without using any complex configurations with NAT Gateways, VPC, and EFS. ⚒️ What's happening with Serverless tools, samples, and projects Ran Isenberg published AWS Lambda Handler Cookbook (Python) v10.0. Floci, an open-source local AWS emulator. Arnav Verma has published aws cost optimizer for EBS volumes. 🎙️ Podcasts, videos, and live-streams On The New Stack, Luca Chang shares how AWS Bedrock is shaping Model Context Protocol Dheeraj Choudhary explains ECS vs EKS vs Lambda: Which AWS Service to Choose? Joud Awad breaks down SNS vs SQS vs EventBridge Which One Should You Use. 🗓️ Mark your calendars Serverless Guru is hosting SLS.Day on May 15th, 2026. AWS Community Days are happening - ACD East Canada on June 20th, 2026. ACD Midwest on June 24th, 2026. ACD Bengaluru on July 11th, 2026. CFP is currently open until April 30th, 2026. ACD Poland on September 8th, 2026. CFP is currently open until July 6th, 2026. ACD Adria on October 22nd, 2026. CFP is currently open until June 15th, 2026. AWS Community Summit Birmingham on June 4th, 2026. ServerlessDays Milano on October 13th, 2026. CFP is currently open until June 15th, 2026. AWS North Community Conf on October 15th, 2026. CFP is currently open until June 30th, 2026. 📢 What's new in Serverless AWS Lambda adds support for Ruby 4.0. Amazon CloudFront Announces WebSocket Support for VPC Origins. Amazon CloudWatch Logs Insights supports querying by log group tags. AWS SAM now supports WebSocket APIs for Amazon API Gateway. AWS SAM CLI adds BuildKit support for AWS Lambda functions packaged as container images. The AWS MCP Server is now generally available. Announcing Agent Toolkit for AWS — help AI coding agents build effectively on AWS. Claude Platform on AWS is now generally available. Amazon EventBridge Scheduler adds 619 new SDK API actions, including Lambda Managed Instances. AWS Lambda supports scheduled scaling for functions on Lambda Managed Instances. Cloudflare introduces Dynamic Workflows: durable execution that follows the tenant. 👨💻 Word from the author Thanks for the support and let’s share more about Serverless!!! I’m open to feedback, so feel free to DM me on LinkedIn for any queries about AWS or Serverless. If you are looking for any guidance or assistance with learning Serverless, my LinkedIn DMs are open for a chat! Stay tuned and share with Serverless enthusiasts. Follow The Serverless Terminal on X (formerly Twitter) and Blog. The Serverless Terminal Blog Until next time, happy building on Serverless! Thanks for reading The Serverless Terminal! Subscribe for free to receive new posts and support my work.
The Serverless Terminal
Your newsletter, discovered.
Get in front of new readers, and give every article a conversation. Free to connect.
- Reach new readers
- A community under every article
- Free to connect
Get your newsletter discovered
Connect your newsletter to get in front of new readers here, grow your subscribers, and spark conversation around every article.
Sign up to connect your newsletterCommune is an open network. Join our Discord for support, to shape the roadmap, reach the founder, and try new features early.
Join our Discord

