CALL "DEPLOY": I taught fixed-format COBOL to deploy AWS, with Kiro
For Kiroween 2026 I resurrected COBOL as an infrastructure-as-code language. A real fixed-format COBOL program, checked by GnuCOBOL, becomes AWS CloudFormation and deploys a three-tier stack. This is how it works, and how Kiro steering, hooks and tests kept the AI honest.
This post is written as part of the Kiroween 2026 hackathon. My entry, COBOL DEPLOY DIVISION, is in the Resurrection category.
- Demo video (under 3 minutes): https://www.youtube.com/watch?v=YhqlqcMIz-k
The ghost of Oracle 8i
Years ago I analyzed a COBOL and Pro*COBOL application in order to convert it to Java. Behind it sat Oracle 8i. Oracle 8i could not be clustered at the time, so the system kept its databases redundant by wiring servers to each other with DB links.
AWS can now transform COBOL into Java. For Kiroween I wanted to try the other direction. COBOL stays COBOL, and the people who know it get to use AWS. COBOL is not dead; it still runs core systems at municipalities and financial institutions. As a language for cloud infrastructure, though, it did not exist. So I resurrected it as one.
What it looks like
This is real fixed-format COBOL. Columns 1 to 6 are a sequence number, column 7 is an indicator, and code starts in column 8.
000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. THREE-TIER.000300 AUTHOR. COBOLFORM.000400 ENVIRONMENT DIVISION.000500 CONFIGURATION SECTION.000600 OBJECT-COMPUTER. AWS-AP-NORTHEAST-1.000700 DATA DIVISION.000800 WORKING-STORAGE SECTION.000900 01 MAIN-VPC.001000 05 RESOURCE-TYPE PIC X(13) VALUE "AWS::EC2::VPC".001100 05 VPC-CIDR PIC X(11) VALUE "10.0.0.0/16".001200 05 VPC-DNS-SUPPORT PIC X(1) VALUE "Y".001300 05 VPC-DNS-HOSTNAMES PIC X(1) VALUE "Y".001400 05 NAME-TAG PIC X(15) VALUE "cobolform-3tier"....018900 CALL "DEPLOY".The rules are conventions, not new syntax:
COBOL | Infrastructure |
|---|---|
PROGRAM-ID | Stack name |
OBJECT-COMPUTER. AWS-AP-NORTHEAST-1. | Region |
01 group item | A resource |
VALUE | A property |
SELECT ... ASSIGN TO "DYNAMODB-MRSC" plus FD | A multi-region, strongly consistent DynamoDB table |
CALL "DEPLOY" | The intent to deploy |
Every sample passes
cobc -fsyntax-only --fixed with GnuCOBOL. The tool, cobf , is a static transpiler written in TypeScript. It never runs the .cbl file; it reads it as text, like a card reader, and emits CloudFormation. Then cobf creates a ChangeSet, executes it, and prints the stack events on a 132-column line-printer report.It covers 46 resource types, from VPCs and Auto Scaling groups to RDS, ECS, SQS, SNS and CloudFront. Defaults are secure: IMDSv2 is required, storage is encrypted, databases are never public, and a plain-text password is an error.
And because it is Kiroween, the card reader has opinions. Shift one column and it tells you where. Write in lower case and you are told it is heresy. Write
ASSIGN TO "DBLINK" and the ghost of the 8i servers appears, with the message that the era of DB-link redundancy is over.It really deploys
On a real AWS account,
examples/three-tier.cbl deployed 21 resources: a VPC, four subnets, an internet gateway, three security groups, an ALB, an Auto Scaling group and an RDS MySQL instance. The load balancer answered COBOL . Then destroy removed all 21, and nothing billable was left behind. An SNS-to-SQS pipeline, an ECS Fargate service, S3, IAM, Lambda and a DynamoDB MRSC table were deployed and checked the same way.Some types were only checked with
cobf diff , which asks CloudFormation to accept a ChangeSet and then deletes it: CloudFront, ACM, Route 53, EKS, ElastiCache and the classic load balancer. The README says so, and the next section explains why it does.How I used Kiro
I used two Kiro apps on the same repository: Kiro IDE, where the agent hook below runs when a file is saved, and Kiro CLI in the terminal. When I ask Kiro CLI to make the demo video, it runs
npm run video , which reads the narration from the script and builds the video with subtitles.Steering: six documents, two inclusion modes
The
.kiro/steering/ directory holds six documents. Four are loaded in every conversation ( inclusion: always ):-
product.md: what the project is, and its principles.
-
tech.md: the stack and the exact commands (typecheck, tests, builds, cfn-lint, GnuCOBOL).
-
structure.md: where things live, and which files are generated.
-
aws-safety.md: how to touch the AWS account.
Two are loaded only when the matching files are open (
inclusion: fileMatch ):-
cobol-conventions.mdfor**/*.cbl: the fixed format, column by column, and the trap where a long string split at the wrong column silently loses its closing quote.
-
mapping-rules.mdforsrc/mapping/**: the eight steps to add a resource type, ending with "fix the table, not the test".
The rule that made the biggest difference is one line in
product.md : say only what was verified. A claim goes into the README only after a real run or a test, and a resource type that CloudFormation accepted as a ChangeSet but that was never deployed must be described that way. That rule is why this post can tell you exactly which types were deployed and which were not.aws-safety.md does similar work for the account: deploy only with the owner's approval for that specific stack, say what it costs first, destroy and confirm nothing is left after every real deployment, and never print the account ID. When a deliberately broken stack ended in ROLLBACK_FAILED , the report claimed the previous state was restored. The steering says to report that state honestly, never as "restored". The bug was fixed and is covered by tests.An agent hook keeps two READMEs in sync
The README exists in English and Japanese. English is the source of truth. One hook in
.kiro/hooks/ fires on PostFileSave for README.md and runs an agent action:{ "name": "Sync README translations", "trigger": "PostFileSave", "matcher": "(^|/)README\\.md$", "action": { "type": "agent", "prompt": "README.md was changed. It is the English source of truth. Review the change ... and update every translated README ... Translate only what changed ..." }}The important part of the prompt is "translate only what changed". The Japanese README keeps its wording everywhere else, so the diffs stay small and reviewable.
Agents that review
Before writing code, I had Kiro agents review the design document, and I asked for another review after each revision. The findings came back ranked by severity, and the very first commits in the repository fix them: H1–H3, M1–M5 and L1–L4 in
docs/DESIGN.md . Starting from a reviewed design meant the code had fewer surprises later.Tests as a safety net for the agent
More than three hundred Vitest tests guard the project. Two kinds matter most when an agent is writing code:
-
tests/mapping.test.tschecks every property name, enum value and default in the mapping tables against the official CloudFormation schemas bundled with cfn-lint. A typo in a table fails a test, not a deployment. It caught a real mistake in a security group egress rule.
-
tests/i18n.test.tsfails if a message in the compiler is left untranslated. The CLI speaks English and Japanese, and the test makes sure an agent cannot add a Japanese-only error by accident.
What I learned
COBOL's data structures map onto declarative infrastructure better than I expected. A
01 record with its fields really is a resource with its properties.On the Kiro side, the lesson was that steering is most useful when it holds rules you would otherwise repeat in every prompt, and when those rules are checkable. "Say only what was verified" and "fix the table, not the test" are short, but they changed what the agent wrote.
What's next
- Deploy the types that so far were only accepted as ChangeSets, and try rollback of a failed update.
- An authenticated backend, so the browser demo can deploy without AWS keys ever reaching the browser.
- Aurora DSQL, and policy checks with cfn-guard.
Fixed format, forever.
CALL "DEPLOY". Written for the Kiroween 2026 hackathon. #KiroweenHackathon26
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article