<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ritesh Bangal</title>
    <description>The latest articles on DEV Community by Ritesh Bangal (@riteshbangal).</description>
    <link>https://dev.to/riteshbangal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4071305%2Faf93eb20-69fe-468b-8bc3-5a862b298617.jpg</url>
      <title>DEV Community: Ritesh Bangal</title>
      <link>https://dev.to/riteshbangal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/riteshbangal"/>
    <language>en</language>
    <item>
      <title>Hello World, the Production Way: Java, AWS CDK and GitHub Actions</title>
      <dc:creator>Ritesh Bangal</dc:creator>
      <pubDate>Tue, 20 Oct 2026 10:27:49 +0000</pubDate>
      <link>https://dev.to/riteshbangal/hello-world-the-production-way-java-aws-cdk-and-github-actions-2lgc</link>
      <guid>https://dev.to/riteshbangal/hello-world-the-production-way-java-aws-cdk-and-github-actions-2lgc</guid>
      <description>&lt;p&gt;&lt;em&gt;The app is three lines of Java. The path that ships it is the point.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Writing a Hello World Lambda takes five minutes. Shipping it like a real service is the hard part, so this article shows that path, mostly in pictures. Everything is in the &lt;a href="https://github.com/riteshbangal/aws-cdk-path-to-production" rel="noopener noreferrer"&gt;aws-cdk-path-to-production&lt;/a&gt; repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Friteshbangal%2Faws-cdk-path-to-production%2Fmain%2Fdocs%2Fdiagrams%2F00-path-to-production.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Friteshbangal%2Faws-cdk-path-to-production%2Fmain%2Fdocs%2Fdiagrams%2F00-path-to-production.gif" alt="Animation of one release, 1.2.3, moving from commit to production. A push reaches GitHub. App CI and Infra CI check it with no AWS access. A tag publishes the JAR once to Artifactory. A pull request pins it, and AWS CDK synthesizes CloudFormation templates once. The release job signs in to AWS with OIDC, then the same files deploy to Dev, QA after a smoke test, and Prod after tests and a person's approval." width="720" height="456"&gt;&lt;/a&gt;&lt;/p&gt;
The whole path in 30 seconds: one release, from commit to production.



&lt;h2&gt;
  
  
  Two kinds of code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbyhwxuk2975hx7af4rs1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbyhwxuk2975hx7af4rs1.png" alt="Two kinds of code: app/ builds a versioned JAR with Gradle; infrastructure/ runs cdk synth to produce a CloudFormation template; they meet only at cdk deploy." width="800" height="830"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application and infrastructure have separate build pipelines. CDK brings them together during synthesis, and CloudFormation deploys the resulting infrastructure.&lt;/p&gt;

&lt;p&gt;This is the entire app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;APIGatewayProxyResponseEvent&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withStatusCode&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Three pipelines
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft4do6j4ou92ka7mz4mfs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft4do6j4ou92ka7mz4mfs.png" alt="Three pipelines: App CI and Infra CI run without AWS access; the Release pipeline signs in with OIDC, deploys and smoke-tests." width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;App CI builds and tests the Java code, and publishes a versioned JAR when we tag a release. Infra CI validates the infrastructure independently. Only the Release pipeline deploys to AWS.&lt;br&gt;
A tag publishes the JAR once, and a pull request pins which version ships:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;LAMBDA_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1.2.3
&lt;span class="nv"&gt;LAMBDA_SHA256&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;digest printed by App CI&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Bootstrap, then deploy
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2zpzd6eopyvyg1jniso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo2zpzd6eopyvyg1jniso.png" alt="CDK bootstrap: cdk bootstrap creates the CDKToolkit stack (S3 bucket, IAM roles, ECR repository, SSM version parameter); cdk deploy uses the bucket and roles so CloudFormation can create the API." width="800" height="880"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cdk bootstrap&lt;/code&gt; prepares each AWS account once. &lt;code&gt;cdk synth&lt;/code&gt; only writes templates; &lt;code&gt;cdk deploy&lt;/code&gt; is what changes AWS.&lt;/p&gt;
&lt;h2&gt;
  
  
  No stored AWS keys
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdtt3u782folplrszf35.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwdtt3u782folplrszf35.png" alt="Signing in without stored keys: the job requests a token from GitHub's OIDC issuer, exchanges it at AWS STS, STS checks the IAM role's trust policy, and returns credentials valid for at most one hour." width="800" height="930"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub vouches for the job, and AWS returns credentials that expire within an hour. Each environment has its own role, so Dev can't sign in as Prod.&lt;/p&gt;
&lt;h2&gt;
  
  
  Gated promotion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F840pzylcyf5b1xknjdcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F840pzylcyf5b1xknjdcv.png" alt="Promotion gates: deploy Dev, smoke test, deploy QA, smoke and integration tests, production approval, deploy Prod, smoke test and alarms. Each failed gate stops the release." width="800" height="1220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Same JAR, same infrastructure code, environment-specific templates. CDK synthesizes them once for the release, and the pipeline promotes that release through Dev → QA → Prod. A failed gate stops the release, but it doesn't roll back what's already deployed.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's real today
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdq5c00fxvmsn8lmuhozn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdq5c00fxvmsn8lmuhozn.png" alt="What's verified: build, unit tests, CDK tests, synth and cfn-lint run on every push. Publishing, deploying, smoke and QA tests and promotion are ready and run once you connect AWS and Artifactory. API auth, alarms, scoped IAM and separate AWS accounts should be added before real traffic." width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The lesson
&lt;/h2&gt;

&lt;p&gt;The app is Hello World. The value is the path that delivers it: swap in a real service, and the pipelines, the pin and the gates stay the same.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/riteshbangal" rel="noopener noreferrer"&gt;
        riteshbangal
      &lt;/a&gt; / &lt;a href="https://github.com/riteshbangal/aws-cdk-path-to-production" rel="noopener noreferrer"&gt;
        aws-cdk-path-to-production
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      The path from commit to production for a serverless app on AWS: versioned artifacts, AWS CDK infrastructure in Java, GitHub Actions with OIDC, and gated Dev → QA → Prod promotion. The app is deliberately a Hello World so the delivery path stays the focus.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;AWS CDK: the path to production&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/riteshbangal/aws-cdk-path-to-production/actions/workflows/app-ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/riteshbangal/aws-cdk-path-to-production/actions/workflows/app-ci.yml/badge.svg" alt="App CI"&gt;&lt;/a&gt;
&lt;a href="https://github.com/riteshbangal/aws-cdk-path-to-production/actions/workflows/infra-ci.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/riteshbangal/aws-cdk-path-to-production/actions/workflows/infra-ci.yml/badge.svg" alt="Infra CI"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The path from commit to production for a serverless app on AWS: versioned artifacts, AWS CDK infrastructure in Java, GitHub Actions with OIDC, and gated Dev → QA → Prod promotion.&lt;/p&gt;
&lt;p&gt;The app is deliberately a Hello World, so the delivery path stays the focus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Read the walkthrough:&lt;/strong&gt; &lt;a href="https://dev.to/riteshbangal/hello-world-the-production-way-java-aws-cdk-and-github-actions-2lgc" rel="nofollow"&gt;Hello World, the Production Way&lt;/a&gt; on DEV.&lt;/p&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/riteshbangal/aws-cdk-path-to-production/main/docs/diagrams/00-path-to-production.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fraw.githubusercontent.com%2Friteshbangal%2Faws-cdk-path-to-production%2Fmain%2Fdocs%2Fdiagrams%2F00-path-to-production.gif" width="800" alt="Animation of one release, 1.2.3, moving from commit to production. A push reaches GitHub. App CI and Infra CI check it with no AWS access. A tag publishes the JAR once to Artifactory. A pull request pins it, and AWS CDK synthesizes CloudFormation templates once. The release job signs in to AWS with OIDC, then the same files deploy to Dev, QA after a smoke test, and Prod after tests and a person's approval."&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;One release, from commit to production. A &lt;a href="https://github.com/riteshbangal/aws-cdk-path-to-production/blob/main/docs/diagrams/01-the-path-to-production.png" rel="noopener noreferrer"&gt;static version&lt;/a&gt; is also available.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What's in here&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;app/                    The payload: a Java 21 Lambda that returns "Hello, World!"
infrastructure/         AWS CDK in Java: API Gateway + Lambda, with unit tests
  lambda-artifact.env   The release pin: which JAR version (and SHA-256) to deploy
foundation/             One-time AWS setup: the role GitHub Actions signs in to (OIDC)
scripts/                Fetch/publish the JAR, synth + lint, smoke and QA checks
.github/workflows/      app-ci · infra-ci · release (+ reusable deploy-environment)
docs/                   The reasoning behind each piece, and the&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/riteshbangal/aws-cdk-path-to-production" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>aws</category>
      <category>java</category>
      <category>githubactions</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
