<?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: zaina ahmed</title>
    <description>The latest articles on DEV Community by zaina ahmed (@zaina_ahmed).</description>
    <link>https://dev.to/zaina_ahmed</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3854670%2Fb05aa6a9-349d-4985-8768-aac6abfb78de.jpg</url>
      <title>DEV Community: zaina ahmed</title>
      <link>https://dev.to/zaina_ahmed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zaina_ahmed"/>
    <language>en</language>
    <item>
      <title>"Beyond the Booth: How the Elevation 2026 Careers Expo by Engineers Australia sharpened My Edge in Australia's Tech Industry"</title>
      <dc:creator>zaina ahmed</dc:creator>
      <pubDate>Wed, 01 Apr 2026 08:05:57 +0000</pubDate>
      <link>https://dev.to/zaina_ahmed/beyond-the-booth-how-the-elevation-2026-careers-expo-by-engineers-australia-sharpened-my-edge-in-14p4</link>
      <guid>https://dev.to/zaina_ahmed/beyond-the-booth-how-the-elevation-2026-careers-expo-by-engineers-australia-sharpened-my-edge-in-14p4</guid>
      <description>&lt;p&gt;There are moments in your career that don't just add a line to your resume but they reshape how you see yourself professionally.&lt;/p&gt;

&lt;p&gt;For me, that moment was walking into the &lt;strong&gt;Elevation 2026 Careers Expo by Engineers Australia&lt;/strong&gt; at the Perth Convention and Exhibition Centre.&lt;/p&gt;

&lt;p&gt;I attended as a Software Engineer with 2+ years of enterprise experience at Ericsson actively building Java microservices, Apache Kafka systems, and cloud-native infrastructure while simultaneously exploring what Australia's technology landscape has to offer someone with my background.&lt;/p&gt;

&lt;p&gt;I came away with something far more valuable than a stack of business cards, genuine clarity, real confidence, and a sharp understanding of exactly where my skills fit in Australia's technology landscape.&lt;/p&gt;

&lt;p&gt;This is the story of what happened, what I learned, and what it means for any internationally trained engineer looking to grow their presence in the Australian tech market.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌏 The Context — An Engineer Expanding Her Horizons
&lt;/h2&gt;

&lt;p&gt;Being part of Ericsson's engineering team while based in Perth, Western Australia puts me in an interesting position. The technical work is world-class building distributed systems at global telecom scale teaches you things that are hard to learn anywhere else.&lt;/p&gt;

&lt;p&gt;But the &lt;em&gt;professional ecosystem&lt;/em&gt; here is how engineers present themselves, what Australian employers actually look for, how relationships get built in this market that requires a completely different kind of learning. One that no amount of LeetCode practice or certification studying can give you.&lt;/p&gt;

&lt;p&gt;The technical skills are universal. Java microservices work the same way in Perth as they do anywhere in the world. Apache Kafka doesn't care which continent you're on. Docker containers run identically regardless of timezone.&lt;/p&gt;

&lt;p&gt;What &lt;em&gt;isn't&lt;/em&gt; universal is understanding how to position those skills effectively in a new market and that's exactly what I came to the Elevation Expo to explore.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏛️ Walking Into the Room — First Impressions
&lt;/h2&gt;

&lt;p&gt;The Perth Convention and Exhibition Centre was buzzing. Engineers, recruiters, industry leaders, and emerging professionals filled the space. All gathered under one roof with one shared purpose: to connect the talent of tomorrow with the opportunities of today.&lt;/p&gt;

&lt;p&gt;What immediately struck me was the &lt;strong&gt;diversity of industries represented&lt;/strong&gt;. This wasn't just a software job fair. This was Australia's engineering ecosystem in microcosm. Infrastructure, resources, technology, construction, utilities, and everything in between.&lt;/p&gt;

&lt;p&gt;For a Software Engineer whose work at Ericsson touches telecommunications infrastructure, cloud-native systems, and automation at scale, this breadth was genuinely exciting. My skills aren't niche here, they're relevant across multiple sectors.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤝 The Conversations That Changed My Perspective
&lt;/h2&gt;

&lt;p&gt;The most valuable part of any careers expo isn't the brochures or the booths. It's the unscripted conversations with people who are actually working in the industry you want to grow into.&lt;/p&gt;

&lt;p&gt;My conversations with &lt;strong&gt;Katie Ryan, Mohammadreza Fekri, Seda Aygun, and Kaveen Lekamalage&lt;/strong&gt; were exactly that honest, direct, and incredibly insightful.&lt;/p&gt;

&lt;p&gt;Three things came up repeatedly across these conversations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Australian employers value demonstrated impact over job titles&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's not enough to say you work at Ericsson. What do you &lt;em&gt;build&lt;/em&gt;? What &lt;em&gt;changes&lt;/em&gt; because of your work? What &lt;em&gt;numbers&lt;/em&gt; can you attach to your contributions?&lt;/p&gt;

&lt;p&gt;This aligned perfectly with how I frame my experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduced manual configuration time by &lt;strong&gt;80%&lt;/strong&gt; through a Kubernetes pod connectivity framework&lt;/li&gt;
&lt;li&gt;Cut QA effort by &lt;strong&gt;40%&lt;/strong&gt; through 150+ automated test suites&lt;/li&gt;
&lt;li&gt;Saved &lt;strong&gt;40–60%&lt;/strong&gt; in infrastructure costs through containerization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specificity isn't bragging in Australia's tech market, it's expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Cloud-native and automation skills are in extremely high demand&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every conversation touched on this. Australian organizations across industries, not just pure tech are accelerating their cloud adoption. Engineers who can bridge the gap between traditional infrastructure and modern cloud-native architectures are rare and highly sought after.&lt;/p&gt;

&lt;p&gt;My background in Docker, Kubernetes, Kafka, and CI/CD pipelines isn't just relevant to software companies. It's relevant to &lt;strong&gt;Bechtel&lt;/strong&gt;, &lt;strong&gt;DT Infrastructure&lt;/strong&gt;, &lt;strong&gt;Aurecon&lt;/strong&gt;, and every major engineering firm modernizing their technology stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Personal brand matters as much as technical skill&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was the most unexpected insight. Multiple professionals mentioned that the engineers who stand out aren't always the most technically brilliant, they're the ones who can &lt;em&gt;communicate&lt;/em&gt; their value clearly, confidently, and consistently.&lt;/p&gt;

&lt;p&gt;This is something I've been actively building through this blog, my portfolio, and the way I present my experience in conversations like these.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏢 Engaging With Industry Leaders
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Bechtel Corporation
&lt;/h3&gt;

&lt;p&gt;Speaking with the Bechtel team was a masterclass in understanding how software engineering intersects with large-scale civil and infrastructure projects. Their need for engineers who understand both the technical depth of systems engineering and the operational realities of major projects resonates deeply with my experience building reliable, fault-tolerant systems at Ericsson.&lt;/p&gt;

&lt;h3&gt;
  
  
  DT Infrastructure
&lt;/h3&gt;

&lt;p&gt;DT Infrastructure's focus on digital transformation in Australia's infrastructure sector opened my eyes to how cloud-native technologies I work with daily containerization, event-driven architecture, automated pipelines are being applied to solve challenges far beyond traditional software contexts.&lt;/p&gt;

&lt;h3&gt;
  
  
  RSGx
&lt;/h3&gt;

&lt;p&gt;The RSGx team's warmth was memorable. A genuine conversation, not a sales pitch. Their perspective on what makes engineers valuable in Australia's market reinforced that technical competence is the baseline, but curiosity, adaptability, and communication elevate you above the field.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aurecon
&lt;/h3&gt;

&lt;p&gt;Aurecon's presence highlighted the growing intersection of engineering consulting and technology. As firms like Aurecon increasingly deliver technology-enabled solutions, the demand for engineers who can operate comfortably across both technical and business domains is accelerating rapidly.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 What I Realized About My Own Value
&lt;/h2&gt;

&lt;p&gt;Standing in that room, talking to these professionals, something clicked.&lt;/p&gt;

&lt;p&gt;The skills I'm building at Ericsson, designing distributed systems, automating infrastructure, building reliable pipelines at scale are not just relevant to telecommunications. They are &lt;strong&gt;directly transferable to every major industry&lt;/strong&gt; represented at that expo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For infrastructure companies:&lt;/strong&gt; My experience with Kubernetes orchestration and automated deployment pipelines maps directly to their needs for reliable, scalable operational systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For consulting firms:&lt;/strong&gt; My ability to diagnose complex system problems, communicate findings clearly, and implement targeted solutions is exactly what consulting environments demand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For technology companies:&lt;/strong&gt; My Java microservices, Kafka, and CI/CD expertise speaks directly to their core engineering needs.&lt;/p&gt;

&lt;p&gt;The expo didn't just help me understand Australia's market. It helped me understand that I had been underestimating the breadth of my own relevance.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What Building a Personal Brand Actually Means
&lt;/h2&gt;

&lt;p&gt;One of the most repeated pieces of advice I received at the expo was this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"The best time to build your brand was five years ago. The second best time is right now."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what does "personal brand" actually mean for a software engineer? It's not about self-promotion or LinkedIn performance. It's about &lt;strong&gt;making your value visible and consistent&lt;/strong&gt; across every touchpoint: your resume, your GitHub, your portfolio, your conversations, your writing.&lt;/p&gt;

&lt;p&gt;Here's what I've been doing intentionally alongside my work at Ericsson:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Portfolio website&lt;/strong&gt;&lt;br&gt;
Built with Next.js and React, my portfolio at &lt;a href="https://zee-projects.vercel.app" rel="noopener noreferrer"&gt;zee-projects.vercel.app&lt;/a&gt; showcases my projects, skills, and experience in a way that a resume simply can't. Every conversation I have now ends with: &lt;em&gt;"Check out my portfolio."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Technical writing&lt;/strong&gt;&lt;br&gt;
This blog series covering Kafka, Docker, Kubernetes, prompt engineering, and now this is my way of demonstrating that I don't just use these technologies. I understand them deeply enough to teach them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Showing up in the room&lt;/strong&gt;&lt;br&gt;
The Elevation Expo proved that nothing replaces physical presence. Being in the room, having real conversations, making eye contact with the people who make hiring decisions, this is irreplaceable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Consistency over perfection&lt;/strong&gt;&lt;br&gt;
One article a week. One GitHub commit a day. One meaningful LinkedIn post per event I attend. Small, consistent actions compound into a brand that's hard to ignore.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 The Australian Tech Market — What I Now Understand
&lt;/h2&gt;

&lt;p&gt;After the expo, here's my clearer picture of what Australian employers are actually looking for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What They Say&lt;/th&gt;
&lt;th&gt;What They Mean&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Strong communication skills"&lt;/td&gt;
&lt;td&gt;Can you explain complex systems to non-technical stakeholders?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Self-starter"&lt;/td&gt;
&lt;td&gt;Will you take initiative without waiting to be told?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Cultural fit"&lt;/td&gt;
&lt;td&gt;Are you collaborative, direct, and genuine?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Relevant experience"&lt;/td&gt;
&lt;td&gt;Can you show specific impact, not just job descriptions?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Passionate about technology"&lt;/td&gt;
&lt;td&gt;Do you keep learning outside of work hours?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every single one of these I can speak to, with specific examples, real numbers, and genuine enthusiasm.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌟 The Moment That Meant the Most
&lt;/h2&gt;

&lt;p&gt;Amid all the professional conversations and industry insights, the moment that meant the most was simpler than any of that.&lt;/p&gt;

&lt;p&gt;It was standing in that room, surrounded by Australia's engineering community, realising that I &lt;em&gt;belonged&lt;/em&gt; there.&lt;/p&gt;

&lt;p&gt;Not because I had the most impressive title. Not because I knew everyone in the room. But because I am building something real, skills that matter, systems that work, a track record of solving hard problems and I am ready to bring that fully to Australia's technology ecosystem.&lt;/p&gt;

&lt;p&gt;That realization, that quiet, confident &lt;em&gt;I belong here&lt;/em&gt; is worth more than any job offer.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;p&gt;The Elevation Expo was a catalyst, not a destination.&lt;/p&gt;

&lt;p&gt;While continuing to build enterprise-grade systems at Ericsson, I am actively exploring opportunities across Perth and broader Australia where I can contribute and grow my expertise in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Java microservices and distributed systems&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apache Kafka and event-driven architecture&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Docker, Kubernetes, and cloud-native infrastructure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD pipeline automation and DevOps practices&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI-assisted development and prompt engineering&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building something challenging and need an engineer who brings both technical depth and genuine enthusiasm — let's talk!&lt;/p&gt;

&lt;p&gt;And if you're an internationally trained engineer navigating Australia's tech market for the first time, the Elevation Expo is one of the best investments of time you can make. Show up, be genuine, and trust that the skills you've built have real value here.&lt;/p&gt;

&lt;p&gt;They do. I promise.&lt;/p&gt;




&lt;h2&gt;
  
  
  💬 A Genuine Thank You
&lt;/h2&gt;

&lt;p&gt;To &lt;strong&gt;Katie Ryan, Mohammadreza Fekri, Seda Aygun, and Kaveen Lekamalage&lt;/strong&gt;, thank you for your time, your candour, and your generosity in sharing your perspectives. Those conversations mattered more than you know.&lt;/p&gt;

&lt;p&gt;To the teams at &lt;strong&gt;Bechtel Corporation, DT Infrastructure, RSGx, and Aurecon&lt;/strong&gt;, thank you for engaging genuinely with an engineer who is passionate about contributing to Australia's technology landscape. The insights you shared will shape how I approach the next chapter of my career.&lt;/p&gt;

&lt;p&gt;To &lt;strong&gt;Engineers Australia&lt;/strong&gt; and the Elevation Expo organizers, thank you for creating a space where connections like these are possible.&lt;/p&gt;

&lt;p&gt;The conversations have started. The opportunities are ahead.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Looking forward to what's next.&lt;/em&gt; 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I'm Zaina Nazimudeen Ahmed, a Software Engineer currently at Ericsson, based in Perth, Australia, building Java microservices, Apache Kafka systems, and cloud-native infrastructure. I'm actively exploring opportunities in Australia's technology sector while continuing to grow my expertise at Ericsson.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Connect with me on &lt;a href="https://www.linkedin.com/in/zainanahmed" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, explore my work at &lt;a href="https://zee-projects.vercel.app" rel="noopener noreferrer"&gt;zee-projects.vercel.app&lt;/a&gt;, or reach out directly at &lt;a href="mailto:zainaahmed003@gmail.com"&gt;zainaahmed003@gmail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this resonated with you, whether you're an engineer navigating a new market or an employer looking for someone exactly like this, drop a comment or a ❤️. Let's connect.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>engineersaustralia</category>
      <category>elevation2026careersexpo</category>
      <category>career</category>
      <category>networking</category>
    </item>
    <item>
      <title>How I Cut Infrastructure Costs by 60% by developing a Fast Feedback Development Platform using containerization technologies.</title>
      <dc:creator>zaina ahmed</dc:creator>
      <pubDate>Wed, 01 Apr 2026 06:16:38 +0000</pubDate>
      <link>https://dev.to/zaina_ahmed/how-i-cut-infrastructure-costs-by-60-by-developing-a-fast-feedback-development-platform-using-53m2</link>
      <guid>https://dev.to/zaina_ahmed/how-i-cut-infrastructure-costs-by-60-by-developing-a-fast-feedback-development-platform-using-53m2</guid>
      <description>&lt;p&gt;When I joined Ericsson's R&amp;amp;D team as an intern, our development environment had a problem that every engineer on the team silently accepted as normal: spinning up a full local environment took over 30 minutes, consumed enormous cloud resources, and cost the team 40–60% more in infrastructure than it needed to.&lt;/p&gt;

&lt;p&gt;Six months later, I managed to cut that cost by 60%, reduced memory footprint per machine by 60%, and validation time from 30 minutes to under 10 minutes by smartly optimizing resources.&lt;/p&gt;

&lt;p&gt;The tools that made it possible? &lt;strong&gt;Docker and Kubernetes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is exactly how I did it.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐳 What Is Docker — And Why Should You Care?
&lt;/h2&gt;

&lt;p&gt;Before Docker, deploying software meant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;"It works on my machine"&lt;/em&gt; — classic&lt;/li&gt;
&lt;li&gt;Different OS versions breaking builds&lt;/li&gt;
&lt;li&gt;Manual dependency installation on every server&lt;/li&gt;
&lt;li&gt;Hours wasted on environment setup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Docker solves this by packaging your application and everything it needs into a single portable unit called a container.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Without Docker&lt;/th&gt;
&lt;th&gt;With Docker&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"Install Java 17, then Maven, then..."&lt;/td&gt;
&lt;td&gt;&lt;code&gt;docker run my-app&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works on my machine, breaks on server&lt;/td&gt;
&lt;td&gt;Runs identically everywhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual environment setup per developer&lt;/td&gt;
&lt;td&gt;One command, same environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dependency conflicts between services&lt;/td&gt;
&lt;td&gt;Each container is isolated&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  📦 Docker Basics — The Essential Commands
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Your first Dockerfile:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start from official Java 17 base image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; eclipse-temurin:17-jre-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Set working directory inside container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy the built jar file&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; target/notification-service.jar app.jar&lt;/span&gt;

&lt;span class="c"&gt;# Expose the port your app runs on&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; "port-number"&lt;/span&gt;

&lt;span class="c"&gt;# Command to run when container starts&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Build your image:&lt;/strong&gt;&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="c"&gt;# Build the Docker image and tag it&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; notification-service:1.0 &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Verify it was created&lt;/span&gt;
docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run your container:&lt;/strong&gt;&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="c"&gt;# Run container on port "port_number"&lt;/span&gt;
docker run &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"port_number"&lt;/span&gt;:&lt;span class="s2"&gt;"port_number"&lt;/span&gt; notification-service:1.0

&lt;span class="c"&gt;# Run in background (detached mode)&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"port_number"&lt;/span&gt;:&lt;span class="s2"&gt;"port_number"&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; notification notification-service:1.0

&lt;span class="c"&gt;# Check running containers&lt;/span&gt;
docker ps

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker logs notification

&lt;span class="c"&gt;# Stop container&lt;/span&gt;
docker stop notification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔗 Docker Compose — Running Multiple Services Together
&lt;/h2&gt;

&lt;p&gt;A real application has multiple services, your app, a database, Kafka, Redis. Docker Compose lets you define and run them all together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our notification service stack:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker-compose.yml&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Spring Boot notification service&lt;/span&gt;
  &lt;span class="na"&gt;notification-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number":"port_number"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;SPRING_PROFILES_ACTIVE=dev&lt;/span&gt;

  &lt;span class="c1"&gt;# PostgreSQL database&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:15-alpine&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notifications&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_name"&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;password"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres-data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;notification-network&lt;/span&gt;

  &lt;span class="c1"&gt;# Apache Kafka&lt;/span&gt;
  &lt;span class="na"&gt;kafka&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;confluentinc/cp-kafka:7.4.0&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;zookeeper&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number":"port_number"&lt;/span&gt;

  &lt;span class="c1"&gt;# Zookeeper (required by Kafka)&lt;/span&gt;
  &lt;span class="na"&gt;zookeeper&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;confluentinc/cp-zookeeper:7.4.0&lt;/span&gt;

  &lt;span class="c1"&gt;# Redis cache&lt;/span&gt;
  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7-alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number":"port_number"&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;notification-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;notification-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start everything:&lt;/strong&gt;&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="c"&gt;# Start all services&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Check all running&lt;/span&gt;
docker-compose ps

&lt;span class="c"&gt;# View logs for specific service&lt;/span&gt;
docker-compose logs &lt;span class="nt"&gt;-f&lt;/span&gt; notification-service

&lt;span class="c"&gt;# Stop everything&lt;/span&gt;
docker-compose down

&lt;span class="c"&gt;# Stop and remove volumes (fresh start)&lt;/span&gt;
docker-compose down &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ☸️ What Is Kubernetes — And When Do You Need It?
&lt;/h2&gt;

&lt;p&gt;Docker Compose is great for local development. But in production you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-scaling&lt;/strong&gt; — handle traffic spikes automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-healing&lt;/strong&gt; — restart crashed containers automatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt; — distribute traffic across instances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rolling updates&lt;/strong&gt; — deploy new versions with zero downtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This is what Kubernetes does.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kubernetes (K8s) is a container orchestration platform that manages your containers in production, deciding where they run, scaling them up and down, and keeping them healthy.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Core Kubernetes Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pod
&lt;/h3&gt;

&lt;p&gt;The smallest unit in Kubernetes, one or more containers running together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pod.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notification-pod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notification-service&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notification-service:1.0&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;

&lt;p&gt;Manages multiple pod replicas and handles rolling updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service
&lt;/h3&gt;

&lt;p&gt;Exposes your pods to network traffic — internal or external.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ How We Used Kubernetes-in-Docker (Kind) at Ericsson
&lt;/h2&gt;

&lt;p&gt;Running full Kubernetes clusters in the cloud for every developer is expensive. We solved this using &lt;strong&gt;Kind (Kubernetes in Docker)&lt;/strong&gt; — a tool that runs a full Kubernetes cluster inside Docker containers on your local machine.&lt;br&gt;
&lt;strong&gt;Note:&lt;/strong&gt; Kind is a multi-node cluster suitable for fast, lightweight, and disposable Kubernetes testing and development directly on a local machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Kind:&lt;/strong&gt;&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="c"&gt;# On Linux/WSL&lt;/span&gt;
curl &lt;span class="nt"&gt;-Lo&lt;/span&gt; ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./kind
&lt;span class="nb"&gt;sudo mv&lt;/span&gt; ./kind /usr/local/bin/kind

&lt;span class="c"&gt;# Verify&lt;/span&gt;
kind version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a local cluster:&lt;/strong&gt;&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="c"&gt;# Create cluster&lt;/span&gt;
kind create cluster &lt;span class="nt"&gt;--name&lt;/span&gt; kind

&lt;span class="c"&gt;# Verify it's running&lt;/span&gt;
kubectl cluster-info &lt;span class="nt"&gt;--context&lt;/span&gt; kind-kind

&lt;span class="c"&gt;# See nodes&lt;/span&gt;
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deploy our notification stack locally:&lt;/strong&gt;&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="c"&gt;# Apply all manifests&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; deployment.yaml
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; service.yaml

&lt;span class="c"&gt;# Check deployments&lt;/span&gt;
kubectl get deployments

&lt;span class="c"&gt;# Check pods&lt;/span&gt;
kubectl get pods

&lt;span class="c"&gt;# Check logs&lt;/span&gt;
kubectl logs &lt;span class="nt"&gt;-f&lt;/span&gt; deployment/notification-deployment

&lt;span class="c"&gt;# Scale up to 5 replicas&lt;/span&gt;
kubectl scale deployment notification-deployment &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Helm — Kubernetes Package Manager
&lt;/h2&gt;

&lt;p&gt;Managing dozens of YAML files manually gets messy fast. &lt;strong&gt;Helm&lt;/strong&gt; is the package manager for Kubernetes, it templates and packages all your Kubernetes manifests into reusable charts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install Helm:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create a Helm chart:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm create notification-chart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Chart structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notification-chart/
├── Chart.yaml          ← chart metadata
├── values.yaml         ← default configuration values
└── templates/
    ├── deployment.yaml ← deployment template
    ├── service.yaml    ← service template
    └── configmap.yaml  ← config template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;values.yaml — configure everything in one place:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;repository&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;notification-service&lt;/span&gt;
  &lt;span class="na"&gt;tag&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0"&lt;/span&gt;
  &lt;span class="na"&gt;pullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;IfNotPresent&lt;/span&gt;

&lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterIP&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deploy with Helm:&lt;/strong&gt;&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="c"&gt;# Install chart&lt;/span&gt;
helm &lt;span class="nb"&gt;install &lt;/span&gt;notification ./notification-chart

&lt;span class="c"&gt;# Upgrade with new values&lt;/span&gt;
helm upgrade notification ./notification-chart &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;replicaCount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; image.tag&lt;span class="o"&gt;=&lt;/span&gt;2.0

&lt;span class="c"&gt;# Check releases&lt;/span&gt;
helm list

&lt;span class="c"&gt;# Rollback to previous version&lt;/span&gt;
helm rollback notification 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is exactly how we scaled down 10+ microservices at Ericsson&lt;/strong&gt;, reducing memory footprint by 60% by optimising the &lt;code&gt;resources.requests&lt;/code&gt; values in each chart's &lt;code&gt;values.yaml&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 The Results at Ericsson
&lt;/h2&gt;

&lt;p&gt;Here's what we achieved after moving to a fully containerised, Kubernetes-orchestrated setup:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;th&gt;Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Environment setup time&lt;/td&gt;
&lt;td&gt;30+ mins&lt;/td&gt;
&lt;td&gt;Under 10 mins&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloud infrastructure cost&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;Reduced&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;40–60% saving&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory per developer machine&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;Optimized&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual configuration steps&lt;/td&gt;
&lt;td&gt;~20 steps&lt;/td&gt;
&lt;td&gt;1 command&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;95% reduction&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Onboarding time for new developers&lt;/td&gt;
&lt;td&gt;2 days&lt;/td&gt;
&lt;td&gt;2 hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;8x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🐛 Mistakes I Made (So You Don't Have To)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Not setting resource limits
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ❌ Wrong — no limits, one service can eat all memory&lt;/span&gt;
&lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service:1.0&lt;/span&gt;

&lt;span class="c1"&gt;# ✅ Correct — always set requests and limits&lt;/span&gt;
&lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-service:1.0&lt;/span&gt;
    &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mem"&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu"&lt;/span&gt;
      &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mem"&lt;/span&gt;
        &lt;span class="na"&gt;cpu&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Storing secrets in environment variables directly
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ❌ Wrong — secret visible in plain text&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DB_PASSWORD&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mysecretpassword"&lt;/span&gt;

&lt;span class="c1"&gt;# ✅ Correct — use Kubernetes Secrets&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DB_PASSWORD&lt;/span&gt;
    &lt;span class="na"&gt;valueFrom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;secretKeyRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;db-credentials&lt;/span&gt;
        &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the secret:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create secret generic db-credentials &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from-literal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mysecretpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. No health checks
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ✅ Always add readiness and liveness probes&lt;/span&gt;
&lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/actuator/health&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number"&lt;/span&gt;
  &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
  &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="na"&gt;livenessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/actuator/health&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;port_number"&lt;/span&gt;
  &lt;span class="na"&gt;initialDelaySeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
  &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Getting Started Checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Install Docker Desktop&lt;/li&gt;
&lt;li&gt;[ ] Write your first Dockerfile&lt;/li&gt;
&lt;li&gt;[ ] Build and run a container locally&lt;/li&gt;
&lt;li&gt;[ ] Write a docker-compose.yml for your full stack&lt;/li&gt;
&lt;li&gt;[ ] Install Kind and create a local cluster&lt;/li&gt;
&lt;li&gt;[ ] Write your first Deployment and Service YAML&lt;/li&gt;
&lt;li&gt;[ ] Install Helm and create a chart&lt;/li&gt;
&lt;li&gt;[ ] Deploy with Helm and test scaling&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;p&gt;Once you're comfortable with the basics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes Ingress&lt;/strong&gt; — expose services externally with routing rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal Pod Autoscaler&lt;/strong&gt; — auto-scale based on CPU/memory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes Operators&lt;/strong&gt; — automate complex stateful applications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ArgoCD&lt;/strong&gt; — GitOps continuous deployment for Kubernetes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Istio&lt;/strong&gt; — service mesh for advanced traffic management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Container orchestration is the backbone of modern cloud-native engineering. Every major cloud provider — AWS (EKS), Azure (AKS), Google (GKE) is built around Kubernetes. Learning it now puts you ahead of the curve.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thanks for reading! I'm Zaina, a Software Engineer based in Perth, Australia, working with Java microservices, Apache Kafka, Docker and Kubernetes at Ericsson. Connect with me on &lt;a href="https://www.linkedin.com/in/zainanahmed" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or check out my &lt;a href="https://zee-projects.vercel.app" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found this useful? Drop a ❤️ and share it with a fellow engineer just getting started with containers!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>containers</category>
      <category>development</category>
    </item>
    <item>
      <title>Getting Started with Apache Kafka: What I Learned Building Event-Driven Microservices at Ericsson</title>
      <dc:creator>zaina ahmed</dc:creator>
      <pubDate>Wed, 01 Apr 2026 05:44:46 +0000</pubDate>
      <link>https://dev.to/zaina_ahmed/getting-started-with-apache-kafka-what-i-learned-building-event-driven-microservices-at-ericsson-2h2h</link>
      <guid>https://dev.to/zaina_ahmed/getting-started-with-apache-kafka-what-i-learned-building-event-driven-microservices-at-ericsson-2h2h</guid>
      <description>&lt;p&gt;When I first heard the word &lt;em&gt;"Kafka"&lt;/em&gt; in a technical meeting at Ericsson, I nodded confidently while quietly Googling it under the table. A few months later, I was designing Avro schemas, building consumer groups, and debugging lag metrics in production.&lt;/p&gt;

&lt;p&gt;This is everything I wish someone had told me when I started.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What Is Apache Kafka ?
&lt;/h2&gt;

&lt;p&gt;Imagine a post office. Instead of letters, services send &lt;strong&gt;events&lt;/strong&gt; things that happened, like &lt;em&gt;"user logged in"&lt;/em&gt; or &lt;em&gt;"notification dispatched"&lt;/em&gt;. Instead of delivering directly to recipients, every event goes into a &lt;strong&gt;central post box (Kafka)&lt;/strong&gt;. Any service that cares about that event can pick it up whenever it's ready.&lt;/p&gt;

&lt;p&gt;This is event-driven architecture. And Kafka is the most battle-tested way to build it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The technical version:&lt;/strong&gt;&lt;br&gt;
Apache Kafka is a distributed event streaming platform that lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Publish&lt;/strong&gt; events from producer services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store&lt;/strong&gt; events reliably and durably&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscribe&lt;/strong&gt; to events from consumer services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Process&lt;/strong&gt; streams of events in real time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At Ericsson, every customer notification: SMS, push, email, in-app is flown through a Kafka-based pipeline. Getting this right was critical. Getting it wrong meant missed messages at scale.&lt;/p&gt;


&lt;h2&gt;
  
  
  🏗️ Core Concepts You Must Understand
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Topics
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;topic&lt;/strong&gt; is a named category for events. Think of it like a database table, but append-only.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notification-events     ← all notification events
user-activity-events    ← all user activity events
payment-events          ← all payment events
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Producers
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;producer&lt;/strong&gt; is any service that writes events to a topic.&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="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationProducer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;KafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NotificationEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;TOPIC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"notification-events"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;NotificationProducer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;KafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NotificationEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;kafkaTemplate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NotificationEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TOPIC&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Notification event sent for userId: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consumers
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;consumer&lt;/strong&gt; is any service that reads events from a topic.&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="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationConsumer&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;NotificationProcessor&lt;/span&gt; &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@KafkaListener&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;topics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"notification-events"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;groupId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"notification-service"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NotificationEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Received event for userId: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consumer Groups
&lt;/h3&gt;

&lt;p&gt;Multiple consumers can form a &lt;strong&gt;group&lt;/strong&gt; to share the work of processing events. Kafka automatically distributes partitions across group members, this is how you scale horizontally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;notification-events (3 partitions)
        |
Consumer Group: notification-service
        |
    ┌───┴───┐
Consumer1  Consumer2  Consumer3
(partition 0) (partition 1) (partition 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Partitions
&lt;/h3&gt;

&lt;p&gt;Topics are split into &lt;strong&gt;partitions&lt;/strong&gt;, this is what enables parallelism. Events with the same key always go to the same partition, preserving order.&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="c1"&gt;// Events for the same userId always land on the same partition&lt;/span&gt;
&lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TOPIC&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;//                         ↑ this is the partition key&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Avro Schemas — Why They Matter
&lt;/h2&gt;

&lt;p&gt;Raw JSON Kafka messages are flexible but dangerous at scale. One typo in a field name can break every downstream consumer silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avro schemas&lt;/strong&gt; solve this by defining the exact structure of every message, enforced at the Schema Registry level before a message is even sent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Define your schema&lt;/strong&gt; (&lt;code&gt;notification-event.avsc&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"record"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NotificationEvent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.ericsson.notifications"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eventId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unique identifier for this event"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Target user identifier"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"channel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Channel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"symbols"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"EMAIL"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SMS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUSH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IN_APP"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"long"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"logicalType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timestamp-millis"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"priority"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"null"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"doc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Optional priority level — backward compatible field"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ⚡ Setting Up Kafka Locally
&lt;/h2&gt;

&lt;p&gt;The fastest way to run Kafka locally for development:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker-compose.yml:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify Kafka is running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;span class="c"&gt;# You should see zookeeper, kafka, and schema-registry all running&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔍 Monitoring Kafka Lag
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Consumer lag&lt;/strong&gt; is the number of unprocessed messages sitting in a partition. High lag = your consumers are falling behind.&lt;/p&gt;

&lt;p&gt;At Ericsson we monitored this constantly. &lt;/p&gt;

&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GROUP                TOPIC                PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG
notification-service notification-events  0          1250            1250            0
notification-service notification-events  1          980             985             5
notification-service notification-events  2          1100            1100            0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Partition 1 has a lag of 5 minor, but worth watching. If lag grows consistently, you need more consumer instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a second consumer instance&lt;/strong&gt; by simply running another instance of your service, Kafka automatically rebalances partitions across the group.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐛 Common Mistakes I Made (So You Don't Have To)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Not setting a partition key
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Wrong — no key, random partition assignment&lt;/span&gt;
&lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TOPIC&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct — keyed by userId, preserves order per user&lt;/span&gt;
&lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;TOPIC&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserId&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Creating ObjectMapper inside the consumer loop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Wrong — new ObjectMapper on every message = slow&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;consume&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;Event&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct — inject as Spring Bean&lt;/span&gt;
&lt;span class="nd"&gt;@Autowired&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Not handling deserialization errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Always configure an error handler&lt;/span&gt;
&lt;span class="nd"&gt;@Bean&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;DefaultErrorHandler&lt;/span&gt; &lt;span class="nf"&gt;errorHandler&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DefaultErrorHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DeadLetterPublishingRecoverer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kafkaTemplate&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FixedBackOff&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000L&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Forgetting idempotency
&lt;/h3&gt;

&lt;p&gt;Kafka guarantees &lt;strong&gt;at least once&lt;/strong&gt; delivery, your consumer may receive the same message twice. Always make processing idempotent:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;NotificationEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if already processed before doing work&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processedEventRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEventId&lt;/span&gt;&lt;span class="o"&gt;()))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Duplicate event ignored: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEventId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Process and mark as done&lt;/span&gt;
    &lt;span class="n"&gt;notificationService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;send&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;processedEventRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEventId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 What I Learned in Production
&lt;/h2&gt;

&lt;p&gt;After months of running Kafka in production at Ericsson:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lesson&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Partition key matters&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always key by the entity that needs ordering (userId, orderId)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monitor lag daily&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lag growth is an early warning sign&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dead letter queues&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always have a DLQ for failed messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema evolution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Add fields as nullable with defaults — never remove fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consumer group naming&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use descriptive group IDs — &lt;code&gt;notification-service&lt;/code&gt; not &lt;code&gt;group1&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Replication factor&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Always 3 in production for fault tolerance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🚀 Getting Started Checklist
&lt;/h2&gt;

&lt;p&gt;If you're setting up Kafka for the first time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Run Kafka locally with Docker Compose (see above)&lt;/li&gt;
&lt;li&gt;[ ] Create your first topic&lt;/li&gt;
&lt;li&gt;[ ] Write a simple producer in Spring Boot&lt;/li&gt;
&lt;li&gt;[ ] Write a simple consumer with &lt;code&gt;@KafkaListener&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Define an Avro schema for your messages&lt;/li&gt;
&lt;li&gt;[ ] Add error handling and a dead letter queue&lt;/li&gt;
&lt;li&gt;[ ] Monitor consumer lag&lt;/li&gt;
&lt;li&gt;[ ] Test with multiple consumer instances&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;p&gt;Kafka is one of those technologies where the basics are approachable but the depth is enormous. Once you're comfortable with the fundamentals, explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kafka Streams&lt;/strong&gt; — real-time stream processing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KSQL&lt;/strong&gt; — SQL-like queries over Kafka streams&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exactly-once semantics&lt;/strong&gt; — guaranteeing no duplicates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kafka Connect&lt;/strong&gt; — integrating Kafka with databases and external systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The investment in learning Kafka properly pays dividends across your entire engineering career. Event-driven architecture is how modern distributed systems are built and Kafka is at the center of it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Thanks for reading! I'm Zaina, a Software Engineer based in Perth, Australia, working with Java microservices, Apache Kafka, and cloud-native technologies at Ericsson. Connect with me on &lt;a href="https://www.linkedin.com/in/zainanahmed" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or check out my &lt;a href="https://zee-projects.vercel.app" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found this useful? Drop a ❤️ and share it with a fellow engineer who's just getting started with Kafka!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kafka</category>
      <category>eventdriven</category>
      <category>microservices</category>
      <category>career</category>
    </item>
    <item>
      <title>Prompt Engineering at Workplace: How I Used Amazon Q Developer to Boost Team Productivity by 30%</title>
      <dc:creator>zaina ahmed</dc:creator>
      <pubDate>Wed, 01 Apr 2026 05:25:52 +0000</pubDate>
      <link>https://dev.to/zaina_ahmed/prompt-engineering-in-the-workplace-how-i-used-amazon-q-developer-to-boost-team-productivity-by-30-4ola</link>
      <guid>https://dev.to/zaina_ahmed/prompt-engineering-in-the-workplace-how-i-used-amazon-q-developer-to-boost-team-productivity-by-30-4ola</guid>
      <description>&lt;p&gt;If someone had told me a year ago that learning how to &lt;em&gt;talk to an AI&lt;/em&gt; would become one of the most valuable skills in my engineering career, I probably would have laughed. But here I am. A certified Prompt Engineer at Ericsson, having driven a &lt;strong&gt;30% improvement in team developer efficiency&lt;/strong&gt; simply by integrating AI-assisted tooling into our daily workflows.&lt;/p&gt;

&lt;p&gt;This is the story of how it happened, what I learned, and how you can apply it too.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Little Background
&lt;/h2&gt;

&lt;p&gt;I'm Zaina, a Software Engineer at Ericsson, one of the world's largest telecommunications technology companies. My day-to-day work involves building Java microservices, working with Apache Kafka event-driven systems, and maintaining CI/CD pipelines at enterprise scale.&lt;/p&gt;

&lt;p&gt;Like most engineers, I was skeptical when AI coding tools started appearing. &lt;em&gt;"It'll write buggy code."&lt;/em&gt; &lt;em&gt;"You still have to review everything."&lt;/em&gt; &lt;em&gt;"It's just autocomplete on steroids."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;All of that is partially true. But I was missing the bigger picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 &lt;strong&gt;What Is Amazon Q Developer?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Amazon Q Developer&lt;/strong&gt; is AWS's AI-powered coding assistant, think of it as an engineer who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writes boilerplate code on demand&lt;/li&gt;
&lt;li&gt;Explains complex codebases in plain English&lt;/li&gt;
&lt;li&gt;Generates documentation automatically&lt;/li&gt;
&lt;li&gt;Suggests fixes for bugs and code smells&lt;/li&gt;
&lt;li&gt;Answers questions about AWS services instantly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's similar to GitHub Copilot but with deeper AWS and enterprise integration which made it a natural fit for Ericsson's infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 &lt;strong&gt;What Is Prompt Engineering really?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most people think prompt engineering means typing clever questions into ChatGPT. In a professional engineering context, it's much more structured than that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt engineering is the discipline of crafting precise, contextual instructions that consistently produce accurate, useful AI outputs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of it like writing a function specification. A vague spec gives you vague code. A precise spec gives you exactly what you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bad prompt:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write documentation for this function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Good prompt:&lt;/strong&gt;&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="nc"&gt;Write&lt;/span&gt; &lt;span class="n"&gt;technical&lt;/span&gt; &lt;span class="n"&gt;documentation&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="nc"&gt;Java&lt;/span&gt; &lt;span class="nc"&gt;Spring&lt;/span&gt; &lt;span class="nc"&gt;Boot&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
&lt;span class="nc"&gt;Format&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;as&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nc"&gt;Javadoc&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nl"&gt;Include:&lt;/span&gt; &lt;span class="n"&gt;purpose&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
&lt;span class="n"&gt;exceptions&lt;/span&gt; &lt;span class="n"&gt;thrown&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Keep&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;under&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;NotificationResponse&lt;/span&gt; &lt;span class="nf"&gt;sendNotification&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;NotificationType&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;validateInput&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notificationBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;notificationService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;dispatch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference in output quality is dramatic.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔧 &lt;strong&gt;How I Applied It at Ericsson&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Documentation Generation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Our team had a backlog of undocumented internal APIs, a classic engineering problem. Manually writing Javadoc for 50+ methods would have taken days.&lt;/p&gt;

&lt;p&gt;Using Amazon Q Developer with a structured prompt template, I reduced that to hours. The key was creating a &lt;strong&gt;reusable prompt template&lt;/strong&gt; that the whole team could use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt I used:&lt;/strong&gt;&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="nc"&gt;You&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;senior&lt;/span&gt; &lt;span class="nc"&gt;Java&lt;/span&gt; &lt;span class="n"&gt;engineer&lt;/span&gt; &lt;span class="n"&gt;writing&lt;/span&gt; &lt;span class="n"&gt;internal&lt;/span&gt; &lt;span class="no"&gt;API&lt;/span&gt; &lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="nc"&gt;Given&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="nc"&gt;Spring&lt;/span&gt; &lt;span class="nc"&gt;Boot&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nc"&gt;Javadoc&lt;/span&gt; &lt;span class="n"&gt;comment&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="nl"&gt;includes:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;One&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nd"&gt;@param&lt;/span&gt; &lt;span class="n"&gt;descriptions&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;parameter&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nd"&gt;@return&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nd"&gt;@throws&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;exceptions&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Keep&lt;/span&gt; &lt;span class="n"&gt;professional&lt;/span&gt; &lt;span class="n"&gt;tone&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;under&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ServiceResponse&lt;/span&gt; &lt;span class="nf"&gt;registerPodConnection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;podId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;targetServiceId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; 
    &lt;span class="nc"&gt;ConnectionConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;PodConnectionException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;podRegistry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;exists&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;podId&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PodConnectionException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pod not found: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;podId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="nc"&gt;ConnectionResult&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connectionManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;establish&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;podId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targetServiceId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ServiceResponse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Output:&lt;/strong&gt;&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="cm"&gt;/**
 * Registers a new connection between a pod and a target service using the provided configuration.
 *
 * @param podId           the unique identifier of the source pod
 * @param targetServiceId the identifier of the service to connect to
 * @param config          the connection configuration including timeout and retry settings
 * @return a {@link ServiceResponse} containing the result of the connection attempt
 * @throws PodConnectionException if the specified pod does not exist in the registry
 *
 * Example usage:
 * ServiceResponse response = registerPodConnection("pod-001", "kafka-service", defaultConfig);
 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Documentation that previously took 3 hours took 25 minutes. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test Case Generation
&lt;/h3&gt;

&lt;p&gt;Writing unit tests is important but time-consuming. I used Amazon Q Developer to generate JUnit test skeletons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt I used:&lt;/strong&gt;&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="nc"&gt;Generate&lt;/span&gt; &lt;span class="nc"&gt;JUnit&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;cases&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="nc"&gt;Java&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="nl"&gt;Include:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Happy&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Null&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="k"&gt;case&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Boundary&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Use&lt;/span&gt; &lt;span class="nc"&gt;Mockito&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dependencies&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Follow&lt;/span&gt; &lt;span class="no"&gt;AAA&lt;/span&gt; &lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Arrange&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Act&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Assert&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nc"&gt;Add&lt;/span&gt; &lt;span class="n"&gt;descriptive&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;KafkaMessage&lt;/span&gt; &lt;span class="nf"&gt;buildNotificationEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt; &lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"userId and payload must not be null"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;KafkaMessage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;builder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eventType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Output:&lt;/strong&gt;&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="nd"&gt;@ExtendWith&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MockitoExtension&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationEventBuilderTest&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@InjectMocks&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;NotificationEventBuilder&lt;/span&gt; &lt;span class="n"&gt;eventBuilder&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should build Kafka message successfully with valid inputs"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldBuildKafkaMessageSuccessfully&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user-123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{\"message\": \"Hello\"}"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;EventType&lt;/span&gt; &lt;span class="n"&gt;eventType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PUSH&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Act&lt;/span&gt;
        &lt;span class="nc"&gt;KafkaMessage&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eventBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildNotificationEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Assert&lt;/span&gt;
        &lt;span class="n"&gt;assertNotNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getUserId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPayload&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventType&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEventType&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
        &lt;span class="n"&gt;assertNotNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getTimestamp&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should throw IllegalArgumentException when userId is null"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldThrowExceptionWhenUserIdIsNull&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"{\"message\": \"Hello\"}"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Act &amp;amp; Assert&lt;/span&gt;
        &lt;span class="n"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;eventBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildNotificationEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PUSH&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should throw IllegalArgumentException when payload is null"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldThrowExceptionWhenPayloadIsNull&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user-123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Act &amp;amp; Assert&lt;/span&gt;
        &lt;span class="n"&gt;assertThrows&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;eventBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildNotificationEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;PUSH&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="nd"&gt;@DisplayName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Should throw IllegalArgumentException when payload is empty string"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;shouldHandleEmptyPayloadAsEdgeCase&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Arrange&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user-123"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Act&lt;/span&gt;
        &lt;span class="nc"&gt;KafkaMessage&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eventBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildNotificationEvent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;EventType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SMS&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Assert&lt;/span&gt;
        &lt;span class="n"&gt;assertNotNull&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;assertEquals&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPayload&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generated tests still needed review and refinement but having a solid skeleton cut test writing time by roughly half.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Code Review Assistance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before submitting code for peer review, I started running my changes through Amazon Q Developer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prompt I used:&lt;/strong&gt;&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="nc"&gt;Review&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;following&lt;/span&gt; &lt;span class="nc"&gt;Java&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Potential&lt;/span&gt; &lt;span class="n"&gt;bugs&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;logic&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Performance&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Security&lt;/span&gt; &lt;span class="n"&gt;vulnerabilities&lt;/span&gt;
&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Violations&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="no"&gt;SOLID&lt;/span&gt; &lt;span class="n"&gt;principles&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nc"&gt;Missing&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="n"&gt;handling&lt;/span&gt;

&lt;span class="nc"&gt;Provide&lt;/span&gt; &lt;span class="n"&gt;specific&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;by&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="n"&gt;feedback&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;relevant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;

&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaConsumerService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;NotificationRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;processMessage&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsumerRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ObjectMapper&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;Notification&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saved: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;notification&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code Review Feedback:

1. LINE 9 — PERFORMANCE: ObjectMapper is being instantiated on every method call.
   This is expensive. Inject it as a Spring Bean instead.
   Fix: @Autowired ObjectMapper mapper;

2. LINE 10 — ERROR HANDLING: mapper.readValue() throws JsonProcessingException 
   but it is not handled. Add try-catch or declare in method signature.

3. LINE 12 — LOGGING: System.out.println should be replaced with SLF4J logger.
   Fix: private static final Logger log = LoggerFactory.getLogger(KafkaConsumerService.class);

4. LINE 7 — SOLID: processMessage() is doing too much (parsing + saving + logging).
   Consider separating parsing logic into a dedicated MessageParser class.

5. MISSING: No null check on record.value() before parsing.
   If payload is null, mapper.readValue() will throw NullPointerException.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This caught several issues before they reached my colleagues, improving code quality and reducing review back-and-forth.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Knowledge Base Articles
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Prompt I used:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write an internal engineering guide explaining Avro Schema Evolution 
for a team of Java backend engineers. Assume they are familiar with 
Spring Boot and Kubernetes but new to Avro schemas. Include:
- Overview (2 paragraphs)
- Step by step setup
- Common pitfalls
- Example configuration
Keep it under 500 words, technical but approachable.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;AI Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Avro Schema Evolution — Internal Engineering Guide&lt;/span&gt;

&lt;span class="gu"&gt;## **Overview**&lt;/span&gt;
Apache Avro is a binary serialisation format used with Apache Kafka to define 
the structure of messages exchanged between services. Unlike JSON, Avro schemas 
are strongly typed and versioned, meaning changes to the schema must be managed 
carefully to avoid breaking existing consumers.

Schema evolution allows you to update your Avro schema over time — adding fields, 
removing fields, or changing defaults without breaking services that depend on 
older versions. The Schema Registry (Confluent) acts as the central store for all 
schema versions and enforces compatibility rules.

&lt;span class="gu"&gt;## **Step-by-Step Setup**&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; Add dependency to pom.xml:
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;io.confluent&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;kafka-avro-serializer&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;7.4.0&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;
2.&lt;/span&gt; Define your initial schema (notification.avsc):
{
  "type": "record",
  "name": "Notification",
  "namespace": "com.ericsson.notifications",
  "fields": [
    {"name": "userId", "type": "string"},
    {"name": "message", "type": "string"},
    {"name": "timestamp", "type": "long"}
  ]
}
&lt;span class="p"&gt;
3.&lt;/span&gt; Add new optional field safely (backward compatible):
{"name": "priority", "type": ["null", "string"], "default": null}

&lt;span class="gu"&gt;## **Common Pitfalls**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Never remove a required field — use ["null", "type"] union with default instead
&lt;span class="p"&gt;-&lt;/span&gt; Never rename a field — add a new field and deprecate the old one
&lt;span class="p"&gt;-&lt;/span&gt; Always set default values for new fields to maintain backward compatibility

&lt;span class="gu"&gt;## **Compatibility Rules**&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; BACKWARD: New schema can read old data (safest, recommended)
&lt;span class="p"&gt;-&lt;/span&gt; FORWARD: Old schema can read new data
&lt;span class="p"&gt;-&lt;/span&gt; FULL: Both directions supported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What used to take an afternoon became a 30-minute task.&lt;/p&gt;

&lt;h2&gt;
  
  
  📊 &lt;strong&gt;The Results&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After three months of consistent use and sharing prompt templates with the team:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Documentation time&lt;/td&gt;
&lt;td&gt;~3 hrs&lt;/td&gt;
&lt;td&gt;~25 mins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test skeleton writing&lt;/td&gt;
&lt;td&gt;~2 hrs&lt;/td&gt;
&lt;td&gt;~45 mins&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge base articles&lt;/td&gt;
&lt;td&gt;~4 hrs&lt;/td&gt;
&lt;td&gt;~1 hr&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer efficiency (quarterly review)&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+30% improvement&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 30% figure came from our quarterly engineering efficiency review. &lt;br&gt;
A real, measured outcome, not an estimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎓 Getting Certified
&lt;/h2&gt;

&lt;p&gt;Ericsson offered a formal &lt;strong&gt;Prompt Engineering for Professionals (BCSS BOS)&lt;/strong&gt; certification, which I completed in November 2024. The certification covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fundamentals of large language models&lt;/li&gt;
&lt;li&gt;Prompt design patterns&lt;/li&gt;
&lt;li&gt;Chain-of-thought prompting&lt;/li&gt;
&lt;li&gt;Few-shot and zero-shot techniques&lt;/li&gt;
&lt;li&gt;Responsible AI usage in professional environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your company offers AI training, take it! If not, there are excellent free resources on platforms like Coursera, DeepLearning.AI, and AWS Skill Builder.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Top 5 Prompt Engineering Tips for Engineers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Be specific about format&lt;/strong&gt;&lt;br&gt;
Always tell the AI exactly what format you want — bullet points, table, Javadoc, code block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Give it a role&lt;/strong&gt;&lt;br&gt;
Start with &lt;em&gt;"You are a senior Java engineer..."&lt;/em&gt; — this sets the context and dramatically improves output quality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Set constraints&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;"Under 100 words"&lt;/em&gt;, &lt;em&gt;"Java 17 only"&lt;/em&gt;, &lt;em&gt;"no more than 3 bullet points"&lt;/em&gt; — constraints prevent verbose responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Use examples&lt;/strong&gt;&lt;br&gt;
Show the AI one example of what good output looks like before asking it to generate more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Always review&lt;/strong&gt;&lt;br&gt;
AI output is a first draft, not a final answer. Treat it like code from a junior developer — useful, but needs your expert eye.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔮 What's Next
&lt;/h2&gt;

&lt;p&gt;AI-assisted development is not a trend, it's the new baseline. The engineers who learn to use these tools effectively will move faster, produce higher quality work, and have more time for the complex problems that actually require human creativity.&lt;/p&gt;

&lt;p&gt;I'm now exploring how prompt engineering applies to Kafka event schema design, automated test generation for distributed systems, and CI/CD pipeline optimisation.&lt;/p&gt;

&lt;p&gt;If you're an engineer who hasn't yet experimented with AI-assisted tools, start today. The learning curve is smaller than you think, and the productivity gains are very real.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading! I'm Zaina, a Software Engineer based in Perth, Australia, working with Java microservices, Apache Kafka, and cloud-native technologies. Connect with me on &lt;a href="https://www.linkedin.com/in/zainanahmed" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or check out my &lt;a href="https://zee-projects.vercel.app" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If this article helped you, drop a ❤️ and share it with a fellow engineer!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>career</category>
      <category>promptengineering</category>
    </item>
  </channel>
</rss>
