<?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: Lamka Joy</title>
    <description>The latest articles on DEV Community by Lamka Joy (@jlamka).</description>
    <link>https://dev.to/jlamka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3967812%2F5d51ba8d-8abe-4395-9fce-013404b3b40d.png</url>
      <title>DEV Community: Lamka Joy</title>
      <link>https://dev.to/jlamka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jlamka"/>
    <language>en</language>
    <item>
      <title>Writing SQL in Go Without Losing Type Safety: An Introduction to sqlc</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Thu, 22 Oct 2026 09:27:35 +0000</pubDate>
      <link>https://dev.to/jlamka/writing-sql-in-go-without-losing-type-safety-an-introduction-to-sqlc-11d8</link>
      <guid>https://dev.to/jlamka/writing-sql-in-go-without-losing-type-safety-an-introduction-to-sqlc-11d8</guid>
      <description>&lt;p&gt;One thing I've been exploring after GopherCon Africa 2026 is how Go developers work with databases. That's where I came across sqlc, a tool that makes writing database code in Go a little more interesting.&lt;/p&gt;

&lt;p&gt;So, what does it actually do?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is sqlc?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When building an application, you might write SQL queries to fetch or insert data into a database. You then need Go code to execute those queries and work with the results.&lt;/p&gt;

&lt;p&gt;Usually, this means writing some extra code to connect the two.&lt;/p&gt;

&lt;p&gt;sqlc generates Go code from your SQL queries, allowing you to write the SQL yourself while getting generated Go functions with defined types.&lt;/p&gt;

&lt;p&gt;In simple terms, you write the query, and sqlc helps handle the Go code around it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does it work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine we're building an application that stores information about farmers.&lt;/p&gt;

&lt;p&gt;We might have a farmers table and want to retrieve a farmer using their ID.&lt;/p&gt;

&lt;p&gt;First, we write the SQL query:&lt;/p&gt;

&lt;p&gt;-- name: GetFarmer :one&lt;br&gt;
SELECT id, name&lt;br&gt;
FROM farmers&lt;br&gt;
WHERE id = ?;&lt;/p&gt;

&lt;p&gt;The comment tells sqlc how to name the generated function and indicates that the query should return one row.&lt;/p&gt;

&lt;p&gt;After configuring sqlc and running its code-generation command, it generates Go code that lets us call the query through a function rather than writing all the database-access code ourselves.&lt;/p&gt;

&lt;p&gt;For example, the generated function might be used like this:&lt;/p&gt;

&lt;p&gt;farmer, err := queries.GetFarmer(ctx, farmerID)&lt;br&gt;
if err != nil {&lt;br&gt;
    return err&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;fmt.Println(farmer.Name)&lt;/p&gt;

&lt;p&gt;This is an illustrative usage example; the exact function signature depends on your database driver and sqlc configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why would you use it?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A few things make sqlc useful:&lt;/p&gt;

&lt;p&gt;Type safety: Generated code uses Go types for query parameters and results, helping catch certain mistakes at compile time.&lt;/p&gt;

&lt;p&gt;Less repetitive code: You can spend less time manually writing code to scan database results into Go values.&lt;/p&gt;

&lt;p&gt;SQL stays readable: You write and maintain your queries directly instead of hiding them behind an abstraction.&lt;/p&gt;

&lt;p&gt;Of course, sqlc doesn't eliminate every possible database error. A query can still fail at runtime, and you still need to design your database and write correct SQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My takeaway&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What I find interesting about tools like sqlc is how they help connect two things developers work with regularly: SQL and Go.&lt;/p&gt;

&lt;p&gt;Instead of choosing between writing SQL yourself and having convenient Go code to work with its results, sqlc lets you do both.&lt;/p&gt;

&lt;p&gt;I'm still exploring the Go ecosystem, and it's interesting discovering the tools that make everyday development a little easier.&lt;/p&gt;

&lt;p&gt;Have you ever used sqlc in a Go project, or do you prefer writing your database-access code manually?&lt;/p&gt;

</description>
      <category>backend</category>
      <category>database</category>
      <category>go</category>
      <category>sql</category>
    </item>
    <item>
      <title>Domain-Driven Design in Go: Writing Code Around the Problem</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Thu, 22 Oct 2026 09:19:23 +0000</pubDate>
      <link>https://dev.to/jlamka/domain-driven-design-in-go-writing-code-around-the-problem-1j46</link>
      <guid>https://dev.to/jlamka/domain-driven-design-in-go-writing-code-around-the-problem-1j46</guid>
      <description>&lt;p&gt;At GopherCon Africa 2026, one of the concepts that caught my attention during the Go workshop was Domain-Driven Design (DDD).&lt;/p&gt;

&lt;p&gt;The idea is simple: your code should reflect the problem you're trying to solve, not just the technology you're using.&lt;/p&gt;

&lt;p&gt;But what does that actually mean when you're writing Go?&lt;/p&gt;

&lt;p&gt;Let's use a simple example.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;What is Domain-Driven Design?&lt;br&gt;
*&lt;/em&gt;&lt;br&gt;
DDD is an approach to software development that focuses on understanding the business problem before deciding how to build the solution.&lt;/p&gt;

&lt;p&gt;Imagine we're building a smart irrigation system to help farmers determine when their crops need water.&lt;/p&gt;

&lt;p&gt;Our application might involve sensors, a database, and an API. But those are just the technical components.&lt;/p&gt;

&lt;p&gt;The actual problem we're solving revolves around farms, soil conditions, and irrigation decisions.&lt;/p&gt;

&lt;p&gt;DDD encourages us to model these concepts in our code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What does this look like in Go?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go gives us structs and methods that we can use to represent concepts from our problem domain.&lt;/p&gt;

&lt;p&gt;For example, imagine we're working with soil moisture readings:&lt;/p&gt;

&lt;p&gt;package main&lt;/p&gt;

&lt;p&gt;import "fmt"&lt;/p&gt;

&lt;p&gt;type SoilMoisture struct {&lt;br&gt;
    Percentage float64&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;func (s SoilMoisture) NeedsWater() bool {&lt;br&gt;
    return s.Percentage &amp;lt; 30&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;func main() {&lt;br&gt;
    soil := SoilMoisture{Percentage: 25}&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if soil.NeedsWater() {
    fmt.Println("The soil may need watering.")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Here, SoilMoisture represents a concept in our application, while NeedsWater() expresses a simple rule related to it.&lt;/p&gt;

&lt;p&gt;The 30% threshold is illustrative. A real irrigation system would need to consider factors such as soil type, crop requirements, and sensor readings before making a recommendation.&lt;/p&gt;

&lt;p&gt;The interesting part is that the rule is connected to the concept it describes. We're not hiding it inside a database query or an HTTP handler.&lt;/p&gt;

&lt;p&gt;It's a small example, but it demonstrates how we can make our code reflect the problem we're solving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does this matter?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As applications grow, mixing business rules with database operations and HTTP handlers can make changes harder to manage.&lt;/p&gt;

&lt;p&gt;Separating these responsibilities can help us:&lt;/p&gt;

&lt;p&gt;Maintain our code: Changes to one component are less likely to affect unrelated parts.&lt;/p&gt;

&lt;p&gt;Test business rules: We can test important behaviour without always needing a database or external service.&lt;/p&gt;

&lt;p&gt;Understand the application: Code becomes easier to navigate when its structure reflects the problem we're solving.&lt;/p&gt;

&lt;p&gt;Of course, DDD involves more than structs and methods. Understanding the business domain and using its language consistently are also important.&lt;/p&gt;

&lt;p&gt;And not every project needs a complicated architecture. Sometimes, a simple structure is all you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What did I get from all this?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing I'm learning is that writing software isn't just about making features work. It's also about how we organise our code so we can understand and maintain it as the application grows.&lt;/p&gt;

&lt;p&gt;DDD encourages us to start with the problem, identify the concepts that matter, and let that understanding guide our design.&lt;/p&gt;

&lt;p&gt;I'm still exploring these concepts, but it's interesting to see how a little thought about structure can make a difference in how we build software.&lt;/p&gt;

&lt;p&gt;Good code isn't necessarily code with more layers. Sometimes, it's code that represents the problem clearly.&lt;/p&gt;

&lt;p&gt;Attending GopherCon Africa opened my mind to a whole new set of possibilities. I'm realising just how much there is to learn beyond simply getting code to work.&lt;/p&gt;

&lt;p&gt;How do you approach structuring your Go projects?&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>go</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Your Go Code Works. But Is It Efficient?</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Wed, 21 Oct 2026 15:13:25 +0000</pubDate>
      <link>https://dev.to/jlamka/your-go-code-works-but-is-it-efficient-h19</link>
      <guid>https://dev.to/jlamka/your-go-code-works-but-is-it-efficient-h19</guid>
      <description>&lt;p&gt;At GopherCon Africa 2026, one of the things that caught my attention during the Go workshop was profiling.&lt;/p&gt;

&lt;p&gt;It got me thinking about something: we spend so much time making sure our code works, but how often do we stop to ask whether it's working efficiently?&lt;/p&gt;

&lt;p&gt;So, I did a little more reading, and here's what I learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, what is profiling?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Simply put, profiling helps you understand what's happening inside your application while it's running.&lt;/p&gt;

&lt;p&gt;Is your code using too much CPU? Is it consuming more memory than necessary? Is something slowing it down?&lt;/p&gt;

&lt;p&gt;Instead of guessing, profiling helps you investigate what's actually happening.&lt;/p&gt;

&lt;p&gt;And apparently, Go has a tool for this called pprof.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why should we care?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine building an application that works perfectly during development. Then more users start using it, and suddenly, things get slower.&lt;/p&gt;

&lt;p&gt;Your first instinct might be to start changing things until performance improves. But what if you're fixing the wrong thing?&lt;/p&gt;

&lt;p&gt;That's where profiling comes in. It helps you identify potential bottlenecks so you can focus on the parts of your code that actually need attention.&lt;/p&gt;

&lt;p&gt;And here's the part I found particularly interesting: small improvements can have a bigger impact than we think.&lt;/p&gt;

&lt;p&gt;If an application is wasting resources, fixing the problem could improve performance and potentially reduce infrastructure costs, especially at scale.&lt;/p&gt;

&lt;p&gt;It's a reminder that software development isn't just about getting things to work. It's also about understanding how they work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where does pprof come in?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go's pprof tooling helps developers investigate different aspects of an application's performance.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU profiling helps identify where processing time is being spent.&lt;/li&gt;
&lt;li&gt;Memory profiling helps you understand how your application uses memory.&lt;/li&gt;
&lt;li&gt;Goroutine profiling helps you investigate what your goroutines are doing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don't necessarily need to know everything about profiling to appreciate why it matters. Even understanding what these tools can help you investigate is a good starting point.&lt;/p&gt;

&lt;p&gt;Of course, profiling doesn't automatically fix your code. You still need to understand what the results mean, make changes, and check whether those changes actually helped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My biggest takeaway?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, improving software isn't about adding more features or rewriting everything.&lt;/p&gt;

&lt;p&gt;Sometimes, it's about looking at what you already have and asking, "Could this be working better?"&lt;/p&gt;

&lt;p&gt;I'm still learning Go, and profiling is one of those concepts that reminded me how much there is to explore beyond simply writing code that works.&lt;/p&gt;

&lt;p&gt;One thing's for sure: I'll be paying more attention to what happens behind the scenes from now on.&lt;/p&gt;

&lt;p&gt;If you've worked with Go before, have you used pprof? I'd love to hear about your experience!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Further reading&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Profiling Go programs&lt;/li&gt;
&lt;li&gt;Go diagnostics&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>Git Real: From Faking Conflicts to Surviving Real Ones</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:44:33 +0000</pubDate>
      <link>https://dev.to/jlamka/git-real-from-faking-conflicts-to-surviving-real-ones-2dm5</link>
      <guid>https://dev.to/jlamka/git-real-from-faking-conflicts-to-surviving-real-ones-2dm5</guid>
      <description>&lt;p&gt;Let’s be honest: learning Git as a beginner can feel like absolute hell.&lt;br&gt;
In the beginning, you’re memorizing commands like magic spells such as git add, git commit -m "fixed stuff", git push, without really understanding what’s happening behind the curtain. You hear developers talk about branches, rebasing, and merge conflicts as if they're everyday occurrences, but until you hit those hurdles yourself, it all feels abstract.&lt;/p&gt;

&lt;p&gt;Recently, while working on projects at my developer program, I went from intentionally trying to break Git just to see what a conflict looked like, to unintentionally manifesting a full-blown merge conflict in my very next project. Here is what that journey taught me about navigating Git, resolving conflicts, and surviving the dangerous lure of the force push.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Weird World of "Ghost" Conflicts&lt;/strong&gt;&lt;br&gt;
During one of our early team assignments, we were specifically instructed to practice handling merge conflicts. A conflict happens when Git cannot automatically reconcile differences between two commits, typically because two people modified the exact same line in the exact same file in contradictory ways.&lt;/p&gt;

&lt;p&gt;I set up my separate branches, made edits on both sides, prepared my mind for chaos, and executed the merge. To my complete surprise, everything merged smoothly without a single warning or conflict marker. It was baffling to say the least.Then now I actually had to go out of my way to force a failure just so I could learn how to solve one. I had to manually edit identical lines across both branches to finally trigger those infamous angle-bracket conflict markers. At the time, it felt like a controlled laboratory experiment, but as every developer quickly learns, real software projects rarely stay inside the lab for long.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be Careful What You Wish For: Manifesting a Real Conflict&lt;/strong&gt;&lt;br&gt;
Fast forward to my next project. I was working on a web application, feeling confident, and pushing code across different features when suddenly an actual merge conflict halted my build. It felt as though I had manifested the very nightmare I was trying to simulate earlier.&lt;/p&gt;

&lt;p&gt;Unlike my rehearsed test, this was real code that I could not afford to lose. The initial shock quickly dissolved once I realized that a merge conflict is not a system failure, but rather Git asking for human judgment. Instead of making risky assumptions about which code matters more, Git pauses and hands control back to you.&lt;/p&gt;

&lt;p&gt;To resolve a conflict without relying on structured step-by-step checklists, you simply treat the file like any other code review. You open the conflicted file, locate the section flagged by the markers, and evaluate both versions side by side. Once you choose the ground truth—whether that means keeping your local changes, accepting the incoming branch's changes, or manually combining both into a better solution—you erase the leftover conflict markers. Staging the modified file and executing a standard commit seals the resolution, leaving the repository clean and ready for deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rebase vs. Merge: Keeping History Clean&lt;/strong&gt;&lt;br&gt;
As branching becomes second nature, developers inevitably encounter git rebase as an alternative to git merge. While standard merges preserve every historic branch intersection by creating a dedicated merge commit, they can leave your commit history looking like a chaotic subway map.&lt;/p&gt;

&lt;p&gt;Rebasing solves this visual clutter by taking your branch's unique commits and replaying them individually on top of another target branch. This process rewrites history to present a clean, linear story of development. However, because rebasing alters existing commit hashes, it introduces a vital rule of thumb: you should never rebase commits that have already been pushed to a shared public repository, as it disrupts the history for everyone else on the team.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Playing with Fire: The Infamous Force Push&lt;/strong&gt;&lt;br&gt;
This historical rewriting brings us to one of the most dangerous commands in a developer's toolkit: git push --force. When you rebase a local branch that was previously pushed upstream, Git will reject a standard push command because your local history no longer aligns with the remote server's records.&lt;/p&gt;

&lt;p&gt;Executing a force push instructs the remote repository to discard its current state and forcibly accept your local history. If a teammate pushed code to that remote branch in the meantime, their hard work gets completely wiped out without warning. To prevent accidental data loss, experienced developers favor using --force-with-lease instead. This safer option acts as an automatic guardrail, refusing to overwrite the remote repository if anyone else has updated it since your last pull.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Mastering Git commands like checkout, rebase, and reset requires making mistakes and stepping through uncomfortable terminal errors. Yet, once you get the hang of it, Git transforms from an intimidating chore into an indispensable superpower. It provides a safety net that allows you to experiment freely, recover from mistakes, and collaborate seamlessly across teams. The initial learning curve may be steep, but emerging on the other side as a confident developer makes every struggle worth it.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>codenewbie</category>
      <category>git</category>
      <category>learning</category>
    </item>
    <item>
      <title>From Terminal to Container: The Evolution and Dockerization of an ASCII Art Web Application.</title>
      <dc:creator>Lamka Joy</dc:creator>
      <pubDate>Mon, 20 Jul 2026 08:26:38 +0000</pubDate>
      <link>https://dev.to/jlamka/from-terminal-to-container-the-evolution-and-dockerization-of-an-ascii-art-web-application-4dde</link>
      <guid>https://dev.to/jlamka/from-terminal-to-container-the-evolution-and-dockerization-of-an-ascii-art-web-application-4dde</guid>
      <description>&lt;p&gt;Being a software developer just looks like a journey of learning something new everyday. Recently, I embarked on this exact progression with a project called ascii-web art. What began as a simple command-line interface (CLI) application written in Go evolved into an interactive web service, which was ultimately packaged inside a Docker container. Through this process, I gained firsthand experience in web development, containerization, and did research on the foundational principles of container orchestration with Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1: Building in the Terminal&lt;/strong&gt;&lt;br&gt;
The initial iteration of the project was a pure terminal application. The core logic read plain text input from the command line, parsed each character, and mapped it to corresponding ASCII banner characters stored in template files such as standard, shadow, or thinkertoy.&lt;/p&gt;

&lt;p&gt;While building a CLI application was an excellent way to practice core programming logic, algorithms, and file parsing in Go, it had inherent limitations in terms of usability:&lt;/p&gt;

&lt;p&gt;Execution required direct access to a command terminal and the underlying source code environment.&lt;/p&gt;

&lt;p&gt;Formatting and visual output depended heavily on the user's local terminal dimensions and font settings.&lt;/p&gt;

&lt;p&gt;Non-technical users could not easily interact with or benefit from the tool.&lt;/p&gt;

&lt;p&gt;To overcome these barriers and make the program accessible to a wider audience, the next logical step was bringing the application to the web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2: Transitioning to the Web&lt;/strong&gt;&lt;br&gt;
Transitioning the project to a web application meant wrapping the core ASCII generation logic inside an HTTP server using Go's standard library.&lt;/p&gt;

&lt;p&gt;Instead of accepting command-line arguments, the application served a web interface containing a clean HTML form. Users could enter their desired text, choose an ASCII font style, and submit the request. The Go backend received the POST request, processed the string through the ASCII generator, and rendered the rendered banner dynamically on the web page.&lt;/p&gt;

&lt;p&gt;While this solved the user-accessibility problem, it introduced a common software engineering challenge: environment dependency, commonly summarized as the "works on my machine" problem. Running the application required anyone pulling the project to have Go installed, correctly configure their local environment, and manage directory dependencies for templates and banner files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 3: Containerization with Docker&lt;/strong&gt;&lt;br&gt;
To make the application truly portable and self-contained, we containerized it using Docker.&lt;/p&gt;

&lt;p&gt;At its core, Docker wraps application code along with its specific runtime, system libraries, configuration files, and dependencies into a single, standardized unit known as a Docker Image. When executed, this image runs inside an isolated environment called a Docker Container. Because the container carries its own lightweight runtime environment, it guarantees that the application runs identically regardless of the underlying host operating system—whether Linux, macOS, or Windows.&lt;/p&gt;

&lt;p&gt;The Dockerfile Blueprint&lt;br&gt;
To containerize ascii-web art, we authored a Dockerfile at the root of the project to serve as the build recipe:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 4: Beyond Single Containers—Understanding Kubernetes&lt;/strong&gt;&lt;br&gt;
Working with Docker naturally opens the door to broader infrastructure questions: How do you manage, scale, and maintain hundreds of containers in a production environment across multiple server nodes?&lt;/p&gt;

&lt;p&gt;This is where Kubernetes (K8s) comes into play. While Docker excels at packaging and running individual containers on a single host, Kubernetes is a container orchestraPhase 3: Containerization with Dockertion platform designed to automate management at scale. It handles essential operational needs including:&lt;/p&gt;

&lt;p&gt;Autoscaling: Spinning up additional instances of a container during traffic spikes.&lt;/p&gt;

&lt;p&gt;Self-Healing: Automatically restarting or replacing containers that crash or fail health checks.&lt;/p&gt;

&lt;p&gt;Load Balancing: Distributing network traffic across multiple container instances to maintain uptime and performance.&lt;/p&gt;

&lt;p&gt;In essence, Docker provides the container, and Kubernetes provides the system to manage an entire fleet of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The journey of building and containerizing ascii-web art highlighted the practical value of modern software architecture patterns. Moving from a CLI utility to a web application made the software accessible to end-users, while wrapping it in a Docker container made it instantly deployable for developers and systems administrators alike. Understanding containerization—along with the foundational concepts of orchestration tools like Kubernetes—provides a strong foundation for building portable, scalable, and resilient cloud-native applications.with Kubernetes.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>go</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
