AWS Builder Center

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.

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.md  for  **/*.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.md  for  src/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.ts  checks 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.ts  fails 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
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article