<?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: IROSH PERERA</title>
    <description>The latest articles on DEV Community by IROSH PERERA (@irosh-perera).</description>
    <link>https://dev.to/irosh-perera</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%2F4133792%2F6db09563-d929-43c9-a34b-c8ab02148a70.jpeg</url>
      <title>DEV Community: IROSH PERERA</title>
      <link>https://dev.to/irosh-perera</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/irosh-perera"/>
    <language>en</language>
    <item>
      <title>The Terminal Is a Tool, Not a Personality</title>
      <dc:creator>IROSH PERERA</dc:creator>
      <pubDate>Tue, 06 Oct 2026 10:46:29 +0000</pubDate>
      <link>https://dev.to/irosh-perera/the-terminal-is-a-tool-not-a-personality-7b8</link>
      <guid>https://dev.to/irosh-perera/the-terminal-is-a-tool-not-a-personality-7b8</guid>
      <description>&lt;h1&gt;
  
  
  The Terminal Is a Tool, Not a Personality
&lt;/h1&gt;

&lt;p&gt;One of the first things many people notice about Linux is the terminal.&lt;/p&gt;

&lt;p&gt;There are commands for almost everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Viewing files&lt;/li&gt;
&lt;li&gt;Checking processes&lt;/li&gt;
&lt;li&gt;Installing software&lt;/li&gt;
&lt;li&gt;Managing services&lt;/li&gt;
&lt;li&gt;Inspecting logs&lt;/li&gt;
&lt;li&gt;Testing network connections&lt;/li&gt;
&lt;li&gt;Monitoring system resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, a strange idea has developed in the Linux community:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The more terminal commands someone uses, the more serious they are as a developer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I do not agree with that.&lt;/p&gt;

&lt;p&gt;The terminal is a tool.&lt;/p&gt;

&lt;p&gt;It is not a personality, a skill competition, or proof that someone is a better developer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The terminal is powerful
&lt;/h2&gt;

&lt;p&gt;The terminal is excellent when we need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeatable actions&lt;/li&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;Remote server access&lt;/li&gt;
&lt;li&gt;Fast navigation&lt;/li&gt;
&lt;li&gt;Scripting&lt;/li&gt;
&lt;li&gt;Detailed system information&lt;/li&gt;
&lt;li&gt;Command-line pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When managing a Linux VPS, checking Nginx, inspecting logs, or deploying a backend application, the terminal is often the most practical interface.&lt;/p&gt;

&lt;p&gt;It works well over SSH. It consumes very few resources. It can be combined with scripts and automation.&lt;/p&gt;

&lt;p&gt;For experienced users, the terminal can feel incredibly efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  But the terminal is not always the best interface
&lt;/h2&gt;

&lt;p&gt;A command-line interface is not automatically better for every task.&lt;/p&gt;

&lt;p&gt;A graphical interface can provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual context&lt;/li&gt;
&lt;li&gt;Clear navigation&lt;/li&gt;
&lt;li&gt;Discoverability&lt;/li&gt;
&lt;li&gt;Easier system exploration&lt;/li&gt;
&lt;li&gt;Better feedback for beginners&lt;/li&gt;
&lt;li&gt;More accessibility for some users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Imagine a new Linux user trying to understand CPU usage, storage, processes, services, and logs.&lt;/p&gt;

&lt;p&gt;Giving that person a long list of commands may not be the best introduction.&lt;/p&gt;

&lt;p&gt;A visual dashboard can help them understand the system first. After that, they may become more comfortable using the terminal.&lt;/p&gt;

&lt;p&gt;The goal should be understanding—not forcing everyone to use the same interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copying commands is not the same as learning Linux
&lt;/h2&gt;

&lt;p&gt;A beginner may copy a command from a tutorial and get the expected result.&lt;/p&gt;

&lt;p&gt;But if they do not understand the command, they may struggle when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The output is different&lt;/li&gt;
&lt;li&gt;The file path changes&lt;/li&gt;
&lt;li&gt;A permission error appears&lt;/li&gt;
&lt;li&gt;The service has another name&lt;/li&gt;
&lt;li&gt;The command is unavailable&lt;/li&gt;
&lt;li&gt;They are using another distribution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The terminal becomes much more useful when users understand the concepts behind it.&lt;/p&gt;

&lt;p&gt;Knowing what a process, port, service, permission, or log is matters more than memorizing a command.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is one reason I am building Linuvera
&lt;/h2&gt;

&lt;p&gt;I am building &lt;strong&gt;Linuvera&lt;/strong&gt;, an open-source Linux developer and system-support toolkit using Java and JavaFX.&lt;/p&gt;

&lt;p&gt;The goal is not to replace the terminal.&lt;/p&gt;

&lt;p&gt;The goal is to make useful Linux information easier to understand through a focused graphical interface.&lt;/p&gt;

&lt;p&gt;Linuvera explores areas such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU and memory usage&lt;/li&gt;
&lt;li&gt;Processes&lt;/li&gt;
&lt;li&gt;Storage&lt;/li&gt;
&lt;li&gt;Ports&lt;/li&gt;
&lt;li&gt;Systemd services&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Developer tools&lt;/li&gt;
&lt;li&gt;Linux system health&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current direction focuses on read-only inspection for Ubuntu and Debian-based systems.&lt;/p&gt;

&lt;p&gt;You can explore the project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/IroshPerera/linuvera" rel="noopener noreferrer"&gt;github.com/IroshPerera/linuvera&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A GUI can help someone discover the system. The terminal can help them control and automate it.&lt;/p&gt;

&lt;p&gt;These approaches do not need to fight each other.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the right interface for the job
&lt;/h2&gt;

&lt;p&gt;I use both graphical tools and the terminal.&lt;/p&gt;

&lt;p&gt;For remote server work, automation, and deployment, the terminal is usually the right choice.&lt;/p&gt;

&lt;p&gt;For system exploration, visual monitoring, and helping new users understand what is happening, a graphical interface can be more effective.&lt;/p&gt;

&lt;p&gt;Good software should respect both experienced users and beginners.&lt;/p&gt;

&lt;p&gt;Linux does not need a culture where users feel embarrassed for preferring a GUI.&lt;/p&gt;

&lt;p&gt;It needs tools that help people learn, explore, and become more confident.&lt;/p&gt;

&lt;p&gt;The terminal is powerful.&lt;/p&gt;

&lt;p&gt;But using a graphical interface does not make someone less technical.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which Linux tasks do you prefer to do in the terminal, and which ones do you prefer to do through a graphical interface?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Should Every Backend Developer Learn Linux Before Docker?</title>
      <dc:creator>IROSH PERERA</dc:creator>
      <pubDate>Mon, 28 Sep 2026 03:55:25 +0000</pubDate>
      <link>https://dev.to/irosh-perera/should-every-backend-developer-learn-linux-before-docker-3f7e</link>
      <guid>https://dev.to/irosh-perera/should-every-backend-developer-learn-linux-before-docker-3f7e</guid>
      <description>&lt;h1&gt;
  
  
  Should Every Backend Developer Learn Linux Before Docker?
&lt;/h1&gt;

&lt;p&gt;Docker has changed the way developers build and deploy applications.&lt;/p&gt;

&lt;p&gt;With a few commands, we can run databases, message brokers, backend services, and complete development environments. Docker makes many difficult setup tasks feel simple.&lt;/p&gt;

&lt;p&gt;But this convenience has created an interesting question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Should every backend developer learn Linux before learning Docker?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My short answer is: developers do not need to master Linux first, but every backend developer should understand the Linux concepts that Docker is hiding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker does not remove Linux
&lt;/h2&gt;

&lt;p&gt;Docker feels like an independent tool, but containers still depend on the operating system underneath them.&lt;/p&gt;

&lt;p&gt;A container is not a small virtual machine. It is a process running with isolation and resource restrictions.&lt;/p&gt;

&lt;p&gt;When a container stops, a process has exited.&lt;/p&gt;

&lt;p&gt;When a port is unavailable, something else may already be listening on that port.&lt;/p&gt;

&lt;p&gt;When a file cannot be written, permissions may be involved.&lt;/p&gt;

&lt;p&gt;When a container is slow, the host machine may be running out of memory or CPU.&lt;/p&gt;

&lt;p&gt;Docker makes these things easier to manage, but it does not remove them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Port mapping is easier when you understand networking
&lt;/h2&gt;

&lt;p&gt;Many developers have used commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what does this actually mean?&lt;/p&gt;

&lt;p&gt;The application inside the container must listen on the expected port. The host port must be available. The application may need to listen on the correct network interface.&lt;/p&gt;

&lt;p&gt;When everything works, Docker feels simple.&lt;/p&gt;

&lt;p&gt;When it fails, a basic understanding of Linux networking becomes extremely useful.&lt;/p&gt;

&lt;p&gt;Understanding ports, interfaces, localhost, processes, and firewalls can save a lot of debugging time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers still have files and permissions
&lt;/h2&gt;

&lt;p&gt;Volumes are another good example.&lt;/p&gt;

&lt;p&gt;A database container may need to write data to a mounted directory. A backend container may need to read configuration files. A build process may create files owned by a different user.&lt;/p&gt;

&lt;p&gt;If the permissions are incorrect, the application may fail even though the Docker configuration looks correct.&lt;/p&gt;

&lt;p&gt;Adding more permissions is not always the correct solution.&lt;/p&gt;

&lt;p&gt;Understanding Linux ownership and access permissions helps developers solve the real problem instead of hiding it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Logs are still essential
&lt;/h2&gt;

&lt;p&gt;Docker provides commands such as &lt;code&gt;docker logs&lt;/code&gt;, but developers still need to understand what they are looking at.&lt;/p&gt;

&lt;p&gt;Is the application failing?&lt;/p&gt;

&lt;p&gt;Is the database unavailable?&lt;/p&gt;

&lt;p&gt;Did the process stop?&lt;/p&gt;

&lt;p&gt;Is the container restarting repeatedly?&lt;/p&gt;

&lt;p&gt;Is the problem inside the container or on the host machine?&lt;/p&gt;

&lt;p&gt;The container is only one part of the system. Linux processes, services, memory, storage, and network connections may all affect the result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Linux knowledge is enough?
&lt;/h2&gt;

&lt;p&gt;Backend developers do not need to understand every kernel subsystem before using Docker.&lt;/p&gt;

&lt;p&gt;However, these concepts are extremely valuable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Processes and signals&lt;/li&gt;
&lt;li&gt;Files and permissions&lt;/li&gt;
&lt;li&gt;Ports and networking&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;CPU and memory usage&lt;/li&gt;
&lt;li&gt;Services and background processes&lt;/li&gt;
&lt;li&gt;Basic shell commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not about creating a barrier for beginners.&lt;/p&gt;

&lt;p&gt;It is about giving developers enough knowledge to understand what happens when the abstraction fails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker is still a great starting point
&lt;/h2&gt;

&lt;p&gt;I do not think developers should avoid Docker until they become Linux experts.&lt;/p&gt;

&lt;p&gt;Docker is an excellent learning tool. It helps developers run real services, experiment with environments, and understand deployment workflows.&lt;/p&gt;

&lt;p&gt;The problem starts when Docker becomes a complete replacement for understanding the operating system.&lt;/p&gt;

&lt;p&gt;Abstraction is useful when it saves time.&lt;/p&gt;

&lt;p&gt;It becomes dangerous when we cannot debug beyond the abstraction.&lt;/p&gt;

&lt;p&gt;As a Java and Spring Boot developer, I use Linux with PostgreSQL, Nginx, Docker, and other backend tools. The more I work with real applications and Linux servers, the more I understand that Docker and Linux are not competing skills.&lt;/p&gt;

&lt;p&gt;They complement each other.&lt;/p&gt;

&lt;p&gt;Docker helps us package and run applications.&lt;/p&gt;

&lt;p&gt;Linux helps us understand the environment where those applications actually live.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Did Docker make Linux easier for you, or did it help you avoid learning Linux?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>docker</category>
      <category>backend</category>
      <category>devops</category>
    </item>
    <item>
      <title>Linux Is Not Difficult — Most Tutorials Explain It Poorly</title>
      <dc:creator>IROSH PERERA</dc:creator>
      <pubDate>Tue, 22 Sep 2026 10:53:07 +0000</pubDate>
      <link>https://dev.to/irosh-perera/linux-is-not-difficult-most-tutorials-explain-it-poorly-1i72</link>
      <guid>https://dev.to/irosh-perera/linux-is-not-difficult-most-tutorials-explain-it-poorly-1i72</guid>
      <description>&lt;h1&gt;
  
  
  Linux Is Not Difficult — Most Tutorials Explain It Poorly
&lt;/h1&gt;

&lt;p&gt;Linux is often described as difficult.&lt;/p&gt;

&lt;p&gt;You need to use the terminal. You need to understand permissions. You need to manage packages. Sometimes a command fails, and the error message looks more confusing than the original problem.&lt;/p&gt;

&lt;p&gt;I understand why many beginners feel this way.&lt;/p&gt;

&lt;p&gt;But after using Ubuntu for Java and Spring Boot development, working with Linux servers, PostgreSQL, Nginx, Docker, and building my own Linux tool, I have started to see the problem differently.&lt;/p&gt;

&lt;p&gt;Linux is not necessarily difficult.&lt;/p&gt;

&lt;p&gt;Most Linux tutorials simply explain it poorly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem is not Linux. The problem is the learning path.
&lt;/h2&gt;

&lt;p&gt;Many beginner tutorials start like this:&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="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;something
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But they do not explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What &lt;code&gt;apt&lt;/code&gt; actually does&lt;/li&gt;
&lt;li&gt;Why &lt;code&gt;sudo&lt;/code&gt; is required&lt;/li&gt;
&lt;li&gt;Where the package is installed&lt;/li&gt;
&lt;li&gt;What happens if the command fails&lt;/li&gt;
&lt;li&gt;How this relates to the rest of the operating system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A beginner can copy the command successfully and still learn almost nothing.&lt;/p&gt;

&lt;p&gt;Good tutorials should not only show commands. They should explain the ideas behind those commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux is a collection of useful ideas
&lt;/h2&gt;

&lt;p&gt;To understand Linux, beginners do not need to memorize hundreds of commands.&lt;/p&gt;

&lt;p&gt;They need to understand a few important concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files and directories&lt;/li&gt;
&lt;li&gt;Users and permissions&lt;/li&gt;
&lt;li&gt;Processes&lt;/li&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;li&gt;Packages&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Networking&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these concepts become familiar, many commands start to make sense.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;systemctl status nginx&lt;/code&gt; is not just a command to memorize. It is a way to ask Linux about the current state of a service.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;journalctl -u nginx&lt;/code&gt; is not random syntax. It is a way to inspect the logs created by that service.&lt;/p&gt;

&lt;p&gt;The commands become easier when the mental model comes first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions are not an unnecessary obstacle
&lt;/h2&gt;

&lt;p&gt;File permissions are one of the first things that confuse new Linux users.&lt;/p&gt;

&lt;p&gt;A command fails because the current user does not have permission. The common reaction is to add &lt;code&gt;sudo&lt;/code&gt; immediately.&lt;/p&gt;

&lt;p&gt;Sometimes that works. But using &lt;code&gt;sudo&lt;/code&gt; without understanding the reason can create bigger problems.&lt;/p&gt;

&lt;p&gt;Permissions exist for a good reason. They protect files, processes, services, and the entire system from accidental or unauthorized changes.&lt;/p&gt;

&lt;p&gt;Instead of teaching beginners to use &lt;code&gt;sudo&lt;/code&gt; everywhere, tutorials should explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who owns the file&lt;/li&gt;
&lt;li&gt;Which user is running the command&lt;/li&gt;
&lt;li&gt;What read, write, and execute permissions mean&lt;/li&gt;
&lt;li&gt;Why a service may need different access&lt;/li&gt;
&lt;li&gt;When elevated privileges are actually necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The error message is not always the enemy. Sometimes it is Linux explaining the boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package management is one of Linux’s strengths
&lt;/h2&gt;

&lt;p&gt;Installing software manually can become difficult when dependencies, updates, and versions are involved.&lt;/p&gt;

&lt;p&gt;On Ubuntu and Debian-based systems, package managers help organize this process. They provide a consistent way to install software, resolve dependencies, receive updates, and remove packages cleanly.&lt;/p&gt;

&lt;p&gt;That does not mean package management is perfect. Different distributions use different tools, and beginners may become confused by package formats and repositories.&lt;/p&gt;

&lt;p&gt;But the idea itself is powerful.&lt;/p&gt;

&lt;p&gt;The problem is that many tutorials show package commands without explaining the package ecosystem. Beginners learn what to type, but not what is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  Linux feels close to production
&lt;/h2&gt;

&lt;p&gt;As a backend developer, one of the biggest advantages of Linux is that it feels close to the environments where many applications run.&lt;/p&gt;

&lt;p&gt;I use technologies such as Java, Spring Boot, PostgreSQL, Nginx, Docker, and Git. These tools are common in Linux-based development and server environments.&lt;/p&gt;

&lt;p&gt;When the local development environment and the production server use similar tools and conventions, there are fewer surprises.&lt;/p&gt;

&lt;p&gt;This does not remove every deployment problem. It does not guarantee that everything will work immediately.&lt;/p&gt;

&lt;p&gt;But Linux helps developers understand what is happening underneath the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which process is running&lt;/li&gt;
&lt;li&gt;Which port is open&lt;/li&gt;
&lt;li&gt;Which service failed&lt;/li&gt;
&lt;li&gt;Where the logs are stored&lt;/li&gt;
&lt;li&gt;Which environment variables are available&lt;/li&gt;
&lt;li&gt;How the operating system interacts with the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That knowledge becomes extremely valuable when debugging real systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  GUI and terminal should not be enemies
&lt;/h2&gt;

&lt;p&gt;There is also an unnecessary debate between graphical interfaces and the terminal.&lt;/p&gt;

&lt;p&gt;Some people believe serious Linux users should only use the terminal. Others avoid Linux because they think everything requires commands.&lt;/p&gt;

&lt;p&gt;I do not think either position is helpful.&lt;/p&gt;

&lt;p&gt;A good graphical interface can help beginners understand the system. The terminal can provide speed, automation, and deeper control.&lt;/p&gt;

&lt;p&gt;This is one of the reasons I started building &lt;strong&gt;Linuvera&lt;/strong&gt;, an open-source Linux developer and system-support toolkit using Java and JavaFX.&lt;/p&gt;

&lt;p&gt;The idea is to make important Linux information easier to see without hiding the system behind unnecessary complexity. It explores areas such as CPU and memory usage, processes, storage, ports, services, logs, and developer tools.&lt;/p&gt;

&lt;p&gt;You can find the project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/IroshPerera/linuvera" rel="noopener noreferrer"&gt; github.com/IroshPerera/linuvera&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, the goal is not to replace the terminal. It is to make Linux easier to understand while still respecting how the system works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Linux tutorials should do better
&lt;/h2&gt;

&lt;p&gt;In my opinion, beginner-friendly Linux tutorials should:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explain the goal before showing the command.&lt;/li&gt;
&lt;li&gt;Use safe and understandable examples.&lt;/li&gt;
&lt;li&gt;Explain the output, not only the input.&lt;/li&gt;
&lt;li&gt;Show common errors and how to recover from them.&lt;/li&gt;
&lt;li&gt;Explain when &lt;code&gt;sudo&lt;/code&gt; should and should not be used.&lt;/li&gt;
&lt;li&gt;Connect terminal actions with the graphical interface.&lt;/li&gt;
&lt;li&gt;Teach concepts instead of encouraging blind copy-and-paste.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Linux does not need to hide everything to become beginner-friendly.&lt;/p&gt;

&lt;p&gt;It needs a better learning path.&lt;/p&gt;

&lt;p&gt;The more I use Linux, the more I appreciate the control and transparency it provides. But I also understand why beginners feel lost when they are given commands without context.&lt;/p&gt;

&lt;p&gt;Linux is not difficult because it is badly designed.&lt;/p&gt;

&lt;p&gt;Sometimes, it is difficult because we teach it as a list of commands instead of a system of ideas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was the first Linux concept that confused you when you started using Linux—permissions, packages, the terminal, services, or something else?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>beginners</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>I Built a Spring Boot Starter to Handle Duplicate API Requests</title>
      <dc:creator>IROSH PERERA</dc:creator>
      <pubDate>Sun, 20 Sep 2026 07:24:07 +0000</pubDate>
      <link>https://dev.to/irosh-perera/i-built-a-spring-boot-starter-to-handle-duplicate-api-requests-2m4j</link>
      <guid>https://dev.to/irosh-perera/i-built-a-spring-boot-starter-to-handle-duplicate-api-requests-2m4j</guid>
      <description>&lt;p&gt;A client sends a request to create an order. The server processes it, but the connection drops before the response reaches the client.&lt;/p&gt;

&lt;p&gt;The client retries. How can the API recognise that retry and avoid creating another order?&lt;/p&gt;

&lt;p&gt;This is the problem my open-source &lt;strong&gt;Spring Boot Idempotency Starter&lt;/strong&gt; aims to address.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is idempotency?
&lt;/h2&gt;

&lt;p&gt;For an API operation, idempotency means that repeating the same logical request should not produce additional side effects.&lt;/p&gt;

&lt;p&gt;An idempotency key lets the client identify that logical request. It should reuse the same key when retrying and generate a new key for a new operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the starter provides
&lt;/h2&gt;

&lt;p&gt;The starter supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;code&gt;@Idempotent&lt;/code&gt; annotation for protected endpoints.&lt;/li&gt;
&lt;li&gt;An &lt;code&gt;Idempotency-Key&lt;/code&gt; request header.&lt;/li&gt;
&lt;li&gt;Request body hash validation.&lt;/li&gt;
&lt;li&gt;Caching and replaying completed responses.&lt;/li&gt;
&lt;li&gt;In-memory and Redis storage.&lt;/li&gt;
&lt;li&gt;Configurable record expiry and processing timeout.&lt;/li&gt;
&lt;li&gt;Spring Boot auto-configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is how to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Add the Maven dependency
&lt;/h2&gt;

&lt;p&gt;Requirements: Java 17+, Spring Boot 3.x, and Maven 3.8+.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&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.github.iroshperera&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;spring-boot-idempotency-starter&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;0.1.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Annotate an endpoint
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;@Idempotent&lt;/code&gt; to the endpoint you want to protect:&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;lk.irosh.idempotency.annotation.Idempotent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Idempotent&lt;/span&gt;
&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/orders"&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;OrderResponse&lt;/span&gt; &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="nc"&gt;OrderRequest&lt;/span&gt; &lt;span class="n"&gt;request&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="n"&gt;orderService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&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;This snippet belongs inside your controller. &lt;code&gt;OrderRequest&lt;/code&gt;, &lt;code&gt;OrderResponse&lt;/code&gt;, and &lt;code&gt;orderService&lt;/code&gt; represent your application's own types and service.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configure the starter
&lt;/h2&gt;

&lt;p&gt;For a local example, add the following to &lt;code&gt;application.yml&lt;/code&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;idempotency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;memory&lt;/span&gt;
  &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;header-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Idempotency-Key&lt;/span&gt;
  &lt;span class="na"&gt;default-expiry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;24h&lt;/span&gt;
  &lt;span class="na"&gt;processing-timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5m&lt;/span&gt;
  &lt;span class="na"&gt;cache-response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;reject-different-request-hash&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration requires a key, enables response caching, and rejects reuse of a key with a different request body.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Send a request with a key
&lt;/h2&gt;

&lt;p&gt;Assuming your endpoint is available at &lt;code&gt;/orders&lt;/code&gt; and accepts the example payload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/orders &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Idempotency-Key: order-request-001"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"item":"Laptop","quantity":1}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retry the same request with the &lt;strong&gt;same key and body&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The documented behaviour is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;First request&lt;/td&gt;
&lt;td&gt;Executes the controller and saves the response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retry after completion, with the same key and body&lt;/td&gt;
&lt;td&gt;Returns the saved response without executing the controller again&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same key with a different body&lt;/td&gt;
&lt;td&gt;Returns &lt;code&gt;409 Conflict&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing key when a key is required&lt;/td&gt;
&lt;td&gt;Returns &lt;code&gt;400 Bad Request&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Use a fresh key when creating a genuinely new order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing a storage option
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;In-memory storage&lt;/strong&gt; is a starting point for development, testing, and single-instance applications. Its records are local to the running application and do not survive a restart.&lt;/p&gt;

&lt;p&gt;For shared records across application instances, the starter also provides &lt;strong&gt;Redis storage&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;idempotency&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;

&lt;span class="na"&gt;spring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="pi"&gt;:&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;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;localhost&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6379&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Merge these settings into your configuration and make sure Redis is running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things to consider before production use
&lt;/h2&gt;

&lt;p&gt;Idempotency records have a limited lifetime. Once a record expires, you should not assume that an old key will still prevent duplicate processing.&lt;/p&gt;

&lt;p&gt;Shared storage is also only one part of a distributed solution. Concurrent requests, failures during processing, and the relationship between business transactions and stored responses need careful testing.&lt;/p&gt;

&lt;p&gt;For critical operations, keep appropriate database constraints and business-level safeguards in place. An idempotency layer should not be treated as a blanket guarantee of exactly-once execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;p&gt;The project roadmap includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JDBC and PostgreSQL storage.&lt;/li&gt;
&lt;li&gt;MongoDB storage.&lt;/li&gt;
&lt;li&gt;Distributed locking improvements.&lt;/li&gt;
&lt;li&gt;Metrics and monitoring.&lt;/li&gt;
&lt;li&gt;Additional integration tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it and share your feedback
&lt;/h2&gt;

&lt;p&gt;The project is open source under the &lt;strong&gt;MIT License&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/IroshPerera/spring-boot-idempotency-starter" rel="noopener noreferrer"&gt;View Spring Boot Idempotency Starter on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feedback, bug reports, and contributions are welcome—especially around concurrency and failure scenarios.&lt;/p&gt;

&lt;p&gt;How do you handle duplicate requests in your Spring Boot applications?&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
      <category>opensource</category>
      <category>backend</category>
    </item>
    <item>
      <title>I Built a Java Library to Transliterate Sinhala Text into Latin Characters</title>
      <dc:creator>IROSH PERERA</dc:creator>
      <pubDate>Sun, 20 Sep 2026 07:16:07 +0000</pubDate>
      <link>https://dev.to/irosh-perera/built-a-java-library-to-transliterate-sinhala-text-into-latin-characters-439j</link>
      <guid>https://dev.to/irosh-perera/built-a-java-library-to-transliterate-sinhala-text-into-latin-characters-439j</guid>
      <description>&lt;p&gt;I’m sharing &lt;strong&gt;Sinhala Transliterator&lt;/strong&gt;, an open-source Java library I built to convert Sinhala script into Latin characters using predefined mapping rules.&lt;/p&gt;

&lt;p&gt;If you’re building a Java application that works with Sinhala text, this library provides a simple way to add transliteration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it do?
&lt;/h2&gt;

&lt;p&gt;Transliteration represents text in another writing system. It does not translate the meaning into English.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;සිංහල → siṁhala&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The library includes mappings for Sinhala vowels, consonants, and diacritics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add it to your project
&lt;/h2&gt;

&lt;p&gt;Add this dependency to your Maven &lt;code&gt;pom.xml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&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.github.iroshperera&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;sinhala-transliterator&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;1.1.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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it in Java
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.webmotech.transliterator.SinhalaToLatinTransliterator&lt;/span&gt;&lt;span class="o"&gt;;&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;Main&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&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;[]&lt;/span&gt; &lt;span class="n"&gt;args&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;input&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="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nc"&gt;SinhalaToLatinTransliterator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transliterate&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&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="n"&gt;result&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;Expected output, as shown in the project README:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;siṁhala
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where could you use it?
&lt;/h2&gt;

&lt;p&gt;Potential uses include displaying Latin-script versions alongside Sinhala text and experimenting with Sinhala text-processing tools.&lt;/p&gt;

&lt;p&gt;Because the conversion uses predefined rules, test it with your application's actual text samples to check whether the output matches your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback and contributions
&lt;/h2&gt;

&lt;p&gt;The project is available under the &lt;strong&gt;Apache License 2.0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’d welcome feedback on transliteration accuracy, edge cases, and documentation. If you find an unexpected result, please open a GitHub issue with the input, actual output, and expected output.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/IroshPerera/sinhala-transliterator" rel="noopener noreferrer"&gt;Explore Sinhala Transliterator on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you worked with Sinhala text in Java? What challenges did you encounter?&lt;/p&gt;

</description>
      <category>java</category>
      <category>opensource</category>
      <category>maven</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
