<?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: Altair Lage</title>
    <description>The latest articles on DEV Community by Altair Lage (@altairlage).</description>
    <link>https://dev.to/altairlage</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%2F3462854%2F0e9c166e-909e-40b3-8881-cf96fa18e64e.png</url>
      <title>DEV Community: Altair Lage</title>
      <link>https://dev.to/altairlage</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/altairlage"/>
    <language>en</language>
    <item>
      <title>35 years of Linux!</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Mon, 31 Aug 2026 14:18:47 +0000</pubDate>
      <link>https://dev.to/altairlage/35-years-of-linux-2h</link>
      <guid>https://dev.to/altairlage/35-years-of-linux-2h</guid>
      <description>&lt;p&gt;On 25 August 1991, Linus Torvalds announced a new operating-system project, describing it as “just a hobby, won’t be big and professional”.&lt;/p&gt;

&lt;p&gt;Years later, Linux has become one of the most important foundations of modern IT infrastructure. It runs servers, cloud platforms, data centers, embedded systems, billions of smartphones, and many of the services companies around the world depend on every day.&lt;/p&gt;

&lt;p&gt;I am personally grateful for Linux. Knowing Linux was the differential that enabled me to find work and take on new roles at the beginning of my career. For me, it is not only the interface I use every day on my computer, but also a reliable companion throughout my professional journey. Wherever I go, it is there, enabling me to do my best work.&lt;/p&gt;

&lt;p&gt;Thank you, Linux!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl3n77ophm7f5n2ctzjhc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl3n77ophm7f5n2ctzjhc.png" alt=" " width="800" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>software</category>
      <category>webdev</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to explain your PM adding more devs won't make everything faster</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Tue, 21 Jul 2026 15:11:47 +0000</pubDate>
      <link>https://dev.to/altairlage/how-to-explain-your-pm-adding-more-devs-wont-make-everything-faster-4e8b</link>
      <guid>https://dev.to/altairlage/how-to-explain-your-pm-adding-more-devs-wont-make-everything-faster-4e8b</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6emgx9hsgfg6y3r4s9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd6emgx9hsgfg6y3r4s9t.png" alt=" " width="504" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is for sure a joke, I think the market has already moved beyond that idea: Adding more developers doesn’t automatically make software development faster.&lt;br&gt;
New team members need context, onboarding, support, and time to understand the codebase. More developers also mean more communication, coordination, reviews, dependencies, processes, and the more important: MORE MANAGEMENT.&lt;br&gt;
More people can increase capacity, but only with the right planning, architecture, and timing.&lt;br&gt;
Also, I believe some tasks simply can’t be split.&lt;/p&gt;

&lt;p&gt;Now that AI is part of the development process, the equation is even more complex. AI can improve productivity, but it doesn’t replace technical judgment, clear requirements, good architecture, or effective teamwork.&lt;br&gt;
Speed still doesn't mean just about adding more people. It’s about creating the right environment for the team to deliver.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>product</category>
      <category>software</category>
    </item>
    <item>
      <title>Docker vs Podman</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Tue, 21 Jul 2026 15:06:44 +0000</pubDate>
      <link>https://dev.to/altairlage/docker-vs-podman-564j</link>
      <guid>https://dev.to/altairlage/docker-vs-podman-564j</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii8cug95j3xjtj802gm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fii8cug95j3xjtj802gm1.png" alt=" " width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we talk about containers, Docker is still the most well-known tool in the market. However, in recent years, many companies have started evaluating Podman as an alternative, mainly due to licensing, governance, and security concerns.&lt;/p&gt;

&lt;p&gt;Docker remains free for personal use, education, open-source projects, and small businesses. However, larger organizations need paid Docker Desktop subscriptions to stay compliant with licensing requirements.&lt;/p&gt;

&lt;p&gt;Podman, on the other hand, is a fully open-source project, maintained by the community and Red Hat, with no need for commercial licenses for its use.&lt;/p&gt;

&lt;p&gt;Key differences:&lt;br&gt;
Docker&lt;br&gt;
• Mature ecosystem&lt;br&gt;
• Widely adopted by the market&lt;br&gt;
• Docker Desktop with a graphical interface&lt;br&gt;
• Commercial licensing for certain companies&lt;br&gt;
• Daemon-based architecture using dockerd&lt;/p&gt;

&lt;p&gt;Podman&lt;br&gt;
• 100% open source&lt;br&gt;
• No licensing costs&lt;br&gt;
• Daemonless architecture, with no central service&lt;br&gt;
• Rootless execution by default, improving security&lt;br&gt;
• Compatible with Docker commands in most cases&lt;/p&gt;

&lt;p&gt;Both use images compatible with OCI, the Open Container Initiative.&lt;/p&gt;

&lt;p&gt;When should you consider Podman?&lt;/p&gt;

&lt;p&gt;Corporate environments with licensing restrictions&lt;br&gt;
Organizations that prioritize open-source software&lt;br&gt;
Environments with high security requirements&lt;br&gt;
Linux servers where a graphical interface is not required&lt;br&gt;
In the end, both solve the problem of packaging and running applications very well. The choice depends more on governance, compliance, cost, and security requirements than on the technology itself.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>containers</category>
      <category>programming</category>
      <category>devops</category>
    </item>
    <item>
      <title>JWT (JSON Web Token) flow</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Tue, 21 Jul 2026 15:04:39 +0000</pubDate>
      <link>https://dev.to/altairlage/jwt-json-web-token-flow-4l7h</link>
      <guid>https://dev.to/altairlage/jwt-json-web-token-flow-4l7h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuv577wmd23e9crm1lzkc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuv577wmd23e9crm1lzkc.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Authentication and authorization are the foundation of modern web security. They prove who a user is and ensure they can only access what they are allowed to.&lt;/p&gt;

&lt;p&gt;The traditional session-based authentication stored this login information in servers. While this worked well for simple websites, it became slow and complicated when apps grew to use multiple servers, as sharing that session data across them was difficult.&lt;/p&gt;

&lt;p&gt;JSON Web Tokens (JWTs) solve this by being stateless and self-contained. A JWT acts like a digital ID card that carries all the user's information inside it, so servers can instantly verify the user without needing to constantly check a database.&lt;/p&gt;

&lt;p&gt;Today, JWTs are the standard way to identify logged-in users, issued by a login server and checked by your APIs or frontend apps.&lt;/p&gt;

&lt;p&gt;Authentication and authorization are the foundation of modern web security. They ensure that users are who they claim to be and that they can only access resources they are allowed to.&lt;/p&gt;

&lt;p&gt;Traditional session-based authentication stores user information on the server. While this worked well for early monolithic apps, it introduced scaling challenges in distributed systems, where maintaining session state across multiple servers or microservices quickly became complex and inefficient.&lt;/p&gt;

&lt;p&gt;JSON Web Tokens (JWTs) solve this by being stateless, self-contained, and easily verifiable. A JWT acts like a digital ID card that carries all the user's information inside it, eliminating the need for frequent database lookups and enabling fast, scalable authentication across APIs, mobile apps, and microservices.&lt;/p&gt;

&lt;p&gt;JWTs are most commonly used to identify authenticated users, issued by an authentication server and consumed by your APIs or frontend applications.&lt;/p&gt;

&lt;p&gt;A JWT is a standard for authentication and information exchange defined by RFC 7519. It allows for the secure and compact storage of JSON objects. This token is a Base64-encoded string and can be signed using a secret or a public/private key pair.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>RabbitMQ vs Kafka</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Wed, 08 Jul 2026 19:53:07 +0000</pubDate>
      <link>https://dev.to/altairlage/rabbitmq-vs-kafka-3842</link>
      <guid>https://dev.to/altairlage/rabbitmq-vs-kafka-3842</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feviknm17nzphrhdl9ms1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feviknm17nzphrhdl9ms1.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
RabbitMQ and Kafka are frequently compared as similar systems, but they are not interchangeable tools.&lt;/p&gt;

&lt;p&gt;Both were designed to handle the communication between systems, but they solve different architectural problems.&lt;/p&gt;

&lt;p&gt;RabbitMQ is a great fit when you need reliable message delivery, low latency, routing flexibility, and task distribution between services.&lt;/p&gt;

&lt;p&gt;Kafka is better when you need high throughput, event retention, replayability, real-time analytics, and scalable event streaming.&lt;/p&gt;

&lt;p&gt;A simple way to think about it:&lt;/p&gt;

&lt;p&gt;RabbitMQ delivers messages.&lt;br&gt;
Kafka stores and distributes events.&lt;/p&gt;

&lt;p&gt;Choosing the right one depends less on popularity and more on the problem your system needs to solve.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;p&gt;RabbitMQ:&lt;br&gt;
Order processing in an e-commerce system, or Sending e-mails asynchronously.&lt;/p&gt;

&lt;p&gt;Kafka:&lt;br&gt;
Tracking clicks on a website, Tracking delivery status, or Saving payment events.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Programming languages and their IDEs</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Mon, 01 Jun 2026 19:48:34 +0000</pubDate>
      <link>https://dev.to/altairlage/programming-languages-and-their-ides-575a</link>
      <guid>https://dev.to/altairlage/programming-languages-and-their-ides-575a</guid>
      <description>&lt;p&gt;Choosing the right IDE/editor can make your development workflow faster, cleaner, and more productive.&lt;/p&gt;

&lt;p&gt;Of course these are not the only options. Many developers use different editors depending on their project, workflow, team standards, and personal preference.&lt;/p&gt;

&lt;p&gt;The best IDE is the one that helps you code better.&lt;/p&gt;

&lt;p&gt;Which language and IDE/editor do you use the most?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouyykwpuqtgjoz5sv0kv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fouyykwpuqtgjoz5sv0kv.png" alt=" " width="800" height="855"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>coding</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Docker Compose: Speed Up Your Workflow with Profiles, Extends, and Depends_on</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Fri, 08 May 2026 20:53:10 +0000</pubDate>
      <link>https://dev.to/altairlage/docker-compose-speed-up-your-workflow-with-profiles-extends-and-dependson-5cg0</link>
      <guid>https://dev.to/altairlage/docker-compose-speed-up-your-workflow-with-profiles-extends-and-dependson-5cg0</guid>
      <description>&lt;p&gt;If you are reading this article, probably you have already found yourself wrestling with a &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Whether you are a backend developer, DevOps engineer, cloud engineer, or just getting started with Docker, it is common for Docker Compose to become more challenging in day-to-day work as a project grows. Maybe you have services that are only needed occasionally, like debugging or testing tools, repeated configuration across different services, or errors caused by one container starting before another one is actually ready.&lt;/p&gt;

&lt;p&gt;Fortunately, Docker Compose provides advanced features to help with these scenarios and make your development environment more organized and flexible. Three of the main features are &lt;strong&gt;profiles&lt;/strong&gt;, &lt;strong&gt;extends&lt;/strong&gt;, and &lt;strong&gt;depends_on&lt;/strong&gt;. That is what we will explore in this article.&lt;/p&gt;

&lt;p&gt;In this article, we will look at each of these features with explanations and practical examples. You will learn how to use profiles to enable or disable optional services when needed, extends to prevent redundancy and repeated code by following the DRY principle (&lt;em&gt;Don’t Repeat Yourself&lt;/em&gt;) and &lt;code&gt;depends_on&lt;/code&gt; to manage the container startup sequence.&lt;/p&gt;

&lt;p&gt;We will also cover a few best practices and how these features can simplify the workflow of development teams.&lt;/p&gt;

&lt;h1&gt;
  
  
  Profiles: Controlling Optional Services
&lt;/h1&gt;

&lt;p&gt;In many projects, besides the main services, such as your web application and database, there are auxiliary services used only in specific situations, like an integration testing container, a monitoring tool, or a debugging utility. Including all these services in your Docker Compose file and starting them every time can waste resources and time. This is where Docker Compose profiles come in.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;profiles&lt;/strong&gt; feature allows you to enable services selectively. We can assign one or more profiles to specific services, making them &lt;strong&gt;start only when the corresponding profile is enabled&lt;/strong&gt;. Services without a defined profile always start by default, while services assigned to a profile only start when you explicitly request that profile. This is excellent for keeping both essential services and optional debugging, testing, or tooling services in the same Docker Compose file, without having them running all the time.&lt;/p&gt;

&lt;p&gt;Imagine you have a main application and a database that should always run in development, but you also have a container for running integration tests and another one for a fake SMTP server, used to capture emails in development. These extra services are not essential. We can mark them as optional:&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;  
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;app&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;my-application:1.0&lt;/span&gt;  
    &lt;span class="c1"&gt;# ... (web application settings, ports, volumes, etc.) Example:  &lt;/span&gt;
    &lt;span class="c1"&gt;# ports:  &lt;/span&gt;
    &lt;span class="c1"&gt;#   - "8000:8000"  &lt;/span&gt;
    &lt;span class="c1"&gt;# depends_on:  &lt;/span&gt;
    &lt;span class="c1"&gt;#   - db  &lt;/span&gt;

  &lt;span class="na"&gt;db&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&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;POSTGRES_DB=mydatabase&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=user&lt;/span&gt;  
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=password&lt;/span&gt;  
    &lt;span class="c1"&gt;# Database service always required during development  &lt;/span&gt;

  &lt;span class="na"&gt;tests_runner&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;my-tests:latest&lt;/span&gt;  
    &lt;span class="na"&gt;profiles&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;test"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;  
    &lt;span class="c1"&gt;# Non-essential service for running integration tests on demand  &lt;/span&gt;

  &lt;span class="na"&gt;mailhog&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;mailhog/mailhog&lt;/span&gt;  
    &lt;span class="na"&gt;profiles&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;devtools"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;  
    &lt;span class="c1"&gt;# Optional service for capturing and viewing emails sent by the app in development&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the YAML above, &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;db&lt;/code&gt; do not have a profile, so they will always be started. &lt;code&gt;tests_runner&lt;/code&gt;, on the other hand, is associated with the &lt;code&gt;"test"&lt;/code&gt; profile, and &lt;code&gt;mailhog&lt;/code&gt; with the &lt;code&gt;"devtools"&lt;/code&gt; profile. This means that, by default, these two services are not executed unless you explicitly specify them.&lt;/p&gt;

&lt;p&gt;In practice, you can control this through the Docker Compose command line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running &lt;code&gt;docker compose up&lt;/code&gt; without profiles would start only the default services: &lt;code&gt;app&lt;/code&gt; and &lt;code&gt;db&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;docker compose --profile test up&lt;/code&gt; would start &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;, and also the &lt;code&gt;tests_runner&lt;/code&gt; service, because the test profile was enabled.&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;docker compose --profile devtools up&lt;/code&gt; would start &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;db&lt;/code&gt;, and &lt;code&gt;mailhog&lt;/code&gt;. You can also enable multiple profiles at once, for example: &lt;code&gt;docker compose --profile test --profile devtools up&lt;/code&gt; to include both, or use &lt;code&gt;docker compose --profile "*"&lt;/code&gt; to start all services from all profiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This way, profiles allow you to keep a single Docker Compose file with everything your project may need, while turning services on or off depending on the situation. This makes your development environment lighter and faster for everyday work. For example, one team member may run &lt;code&gt;docker compose up&lt;/code&gt; and focus only on the essentials, while another, debugging a specific problem, may enable the &lt;code&gt;devtools&lt;/code&gt; profile to inspect detailed logs or capture emails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important best practices:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do not put your main containers inside a profile.&lt;/strong&gt; Leave them without a profile so they always start by default. Reserve profiles for optional components or scenario-specific services, such as &lt;em&gt;testing&lt;/em&gt;, &lt;em&gt;debugging&lt;/em&gt;, &lt;em&gt;monitoring&lt;/em&gt;, and so on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name profiles clearly:&lt;/strong&gt; Choose names that make their purpose obvious, such as &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;debug&lt;/code&gt;, &lt;code&gt;monitoring&lt;/code&gt;, or &lt;code&gt;ci&lt;/code&gt;. Avoid generic terms so everyone on the team understands when to use them. Document the available profiles and how to enable them in the project README.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reusing Configuration with extends and Removing Repetition
&lt;/h1&gt;

&lt;p&gt;As your Docker Compose configuration grows, you may notice that several services share common settings. For example, imagine we have two services inside a web application: a &lt;code&gt;web&lt;/code&gt; service and a background processing &lt;code&gt;worker&lt;/code&gt; service. Both use the same &lt;strong&gt;base image&lt;/strong&gt;, mount the &lt;strong&gt;same volume&lt;/strong&gt;, and need the &lt;strong&gt;same environment variables&lt;/strong&gt;, such as database connection strings, credentials, and so on. Repeating identical configuration blocks for each service makes the Compose file longer, more repetitive, and harder to maintain. Every change requires editing multiple places, which goes against the &lt;strong&gt;DRY (&lt;em&gt;Don’t Repeat Yourself&lt;/em&gt;)&lt;/strong&gt; principle.&lt;/p&gt;

&lt;p&gt;To avoid duplication, Docker Compose allows you to &lt;strong&gt;extend common configuration across services&lt;/strong&gt;. The &lt;code&gt;extends&lt;/code&gt; feature works like inheritance: you define a base service, which may even live in another file, with the shared options, and then other services “inherit” that base while overriding or adding parameters as needed. In YAML, we can also use anchors and aliases to achieve a similar effect in a simple way inside the same file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;We have two services, &lt;code&gt;web&lt;/code&gt; and &lt;code&gt;worker&lt;/code&gt;, which share a large part of their configuration. Let’s create a reusable base configuration and apply it to both.&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;# We define a YAML anchor with the shared settings  &lt;/span&gt;
&lt;span class="na"&gt;x-base-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;&amp;amp;common_config&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-application:1.0&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;.:/app&lt;/span&gt;  &lt;span class="c1"&gt;# mounts the current directory into the container (useful for development)  &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;DATABASE_URL=postgres://user:password@db:5432/mydatabase&lt;/span&gt;  
  &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;always"&lt;/span&gt;  
  &lt;span class="c1"&gt;# ... (any other shared option, e.g., network, log settings, etc.)  &lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*common_config&lt;/span&gt;      &lt;span class="c1"&gt;# Imports all settings defined in common_config  &lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm start&lt;/span&gt;     &lt;span class="c1"&gt;# Specific command to run the web application  &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;db&lt;/span&gt;                 &lt;span class="c1"&gt;# (example: web depends on db being running)  &lt;/span&gt;

  &lt;span class="na"&gt;worker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;*common_config&lt;/span&gt;      &lt;span class="c1"&gt;# Reuses the same base configuration  &lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run worker&lt;/span&gt;  &lt;span class="c1"&gt;# Specific command to run the background worker  &lt;/span&gt;

  &lt;span class="na"&gt;db&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&lt;/span&gt;  
    &lt;span class="c1"&gt;# ... (database settings)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code snippet above, we use a special key, &lt;code&gt;x-base-service&lt;/code&gt;, at the top of the YAML file to define a shared configuration block identified by &lt;code&gt;&amp;amp;common_config&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, in the web and worker services, we use &lt;code&gt;&amp;lt;&amp;lt;: *common_config&lt;/code&gt; to merge those shared settings into each service.&lt;br&gt;&lt;br&gt;
As a result, both services get identical &lt;code&gt;image&lt;/code&gt;, &lt;code&gt;volumes&lt;/code&gt;, &lt;code&gt;environment&lt;/code&gt;, and &lt;code&gt;restart&lt;/code&gt; values from the template, and we only add what changes in each one. In this case, the specific command and, in the web service, the database dependency.&lt;/p&gt;

&lt;p&gt;If tomorrow you need to change an environment variable or a logging option for &lt;strong&gt;&lt;em&gt;all&lt;/em&gt;&lt;/strong&gt; services, you only need to edit one place, the anchor block, and &lt;strong&gt;the web and worker containers will automatically receive the update&lt;/strong&gt;. Much simpler than remembering to change the same setting in two or three different places.&lt;/p&gt;

&lt;p&gt;It is worth noting that Compose also supports the native &lt;code&gt;**extends**&lt;/code&gt; directive. With it, you could, for example, have a &lt;code&gt;common-services.yml&lt;/code&gt; file that defines a base service and then, in your &lt;code&gt;docker-compose.yml&lt;/code&gt;, make a service extend that external definition. The effect is the same: configuration reuse. It also allows you to override some values when needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Example:
&lt;/h2&gt;

&lt;p&gt;Imagine the &lt;code&gt;common-services.yml&lt;/code&gt; file in this example has the following configuration:&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;webapp&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;8000:8000"&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/data"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could then extend these settings in your &lt;code&gt;docker-compose.yml&lt;/code&gt; using the &lt;code&gt;extends&lt;/code&gt; directive in the desired services:&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;web&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;alpine&lt;/span&gt;  
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;  
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;common-services.yml&lt;/span&gt;  
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp&lt;/span&gt;  
  &lt;span class="na"&gt;webapp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
    &lt;span class="na"&gt;extends&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;common-services.yml&lt;/span&gt;  
      &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Result
&lt;/h2&gt;

&lt;p&gt;You will get exactly the same result as if you had written a &lt;code&gt;docker-compose.yaml&lt;/code&gt; file with the same build, ports, and volumes configuration values defined directly, or hardcoded.&lt;/p&gt;

&lt;p&gt;Use the approach you prefer: YAML anchors are great within a single file, while &lt;code&gt;extends&lt;/code&gt; shines when splitting Compose files across multiple files.&lt;/p&gt;

&lt;h1&gt;
  
  
  Benefits for the workflow
&lt;/h1&gt;

&lt;p&gt;By removing duplication, you reduce errors and keep your Compose code cleaner. In development teams, this means all members share consistent settings. If several microservices use the same image or variables, you make sure they are all using exactly the same values. The file also becomes smaller and easier to understand. New developers can quickly identify what is common to all services and what is specific to each one.&lt;/p&gt;

&lt;h1&gt;
  
  
  Orchestrating Startup Order with depends_on
&lt;/h1&gt;

&lt;p&gt;Another classic challenge in multi-container environments is &lt;strong&gt;making sure certain services only start when others are already ready&lt;/strong&gt;. Imagine your web API depends on a database. If the API container starts &lt;em&gt;before&lt;/em&gt; the database is up, the application will probably fail when trying to connect, and its startup may even be compromised. These situations are frustrating, but Docker Compose helps us with the &lt;code&gt;depends_on&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;depends_on&lt;/code&gt; allows you to declare &lt;strong&gt;explicit dependencies between services&lt;/strong&gt;, making Compose start containers in the correct order. In the short syntax, you simply list the names of the services that another service depends on, and Compose will make sure to start the dependency containers first and stop them last. For example:&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;api&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;my-api:latest&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;db&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;db&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;mysql:8.0&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the example above, when running &lt;code&gt;docker compose up&lt;/code&gt;, Compose will first start the &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;redis&lt;/code&gt; services, and only then start the &lt;code&gt;api&lt;/code&gt; container. Likewise, when stopping the containers, it would stop &lt;code&gt;api&lt;/code&gt; first before shutting down &lt;code&gt;db&lt;/code&gt; and &lt;code&gt;redis&lt;/code&gt;. This helps avoid many startup and shutdown ordering problems.&lt;/p&gt;

&lt;p&gt;But what if we want to make sure the database is &lt;strong&gt;really&lt;/strong&gt; ready for connections before starting the API?&lt;br&gt;&lt;br&gt;
The good news is that newer versions of Compose support the long syntax for &lt;code&gt;depends_on&lt;/code&gt;, which includes conditions. We can specify a condition such as &lt;code&gt;service_healthy&lt;/code&gt; to indicate that the dependency service only counts as “ready” when its &lt;em&gt;healthcheck&lt;/em&gt; is OK. Let’s improve the example by adding a healthcheck to the database:&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;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
  &lt;span class="na"&gt;api&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;my-api:latest&lt;/span&gt;  
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
        &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_healthy&lt;/span&gt;   &lt;span class="c1"&gt;# waits for the db healthcheck to pass  &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;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_started&lt;/span&gt;   &lt;span class="c1"&gt;# waits for redis to start (container started only)  &lt;/span&gt;
    &lt;span class="c1"&gt;# ... (remaining API config, ports, etc.)  &lt;/span&gt;

  &lt;span class="na"&gt;db&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;mysql:8.0&lt;/span&gt;  
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  
      &lt;span class="na"&gt;test&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;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mysqladmin"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ping"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-h"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# checks whether MySQL responds  &lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;  
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt;  
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5&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="c1"&gt;# (we can also include a healthcheck here if we want to monitor readiness)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Compose will &lt;strong&gt;wait for the MySQL healthcheck to return success&lt;/strong&gt;. In this case, the &lt;code&gt;mysqladmin ping&lt;/code&gt; command indicates that the server is responding before starting the &lt;code&gt;api&lt;/code&gt; service.&lt;br&gt;&lt;br&gt;
For Redis, we use &lt;code&gt;service_started&lt;/code&gt; simply to make sure the container has started. There is no wait for a “Healthy” status, because we may not have defined a healthcheck for it.&lt;/p&gt;

&lt;p&gt;This configuration reflects a common scenario: waiting for the database to become available and also making sure the Redis cache has started &lt;strong&gt;before the application goes online&lt;/strong&gt;. In practice, &lt;code&gt;api&lt;/code&gt; only starts initializing when Compose verifies that &lt;code&gt;db&lt;/code&gt; is healthy and &lt;code&gt;redis&lt;/code&gt; is already running, avoiding immediate “could not connect to the database” failures.&lt;/p&gt;

&lt;h1&gt;
  
  
  Important tips:
&lt;/h1&gt;

&lt;p&gt;To use &lt;code&gt;condition: service_healthy&lt;/code&gt;, make sure to define an appropriate &lt;code&gt;healthcheck&lt;/code&gt; on the dependency service. Otherwise, Compose will have no way to know its health status and will treat the container as ready as soon as the process starts.&lt;/p&gt;

&lt;p&gt;In the example, we use a native MySQL command, &lt;code&gt;mysqladmin ping&lt;/code&gt;, to check availability. For PostgreSQL, for example, there is &lt;code&gt;pg_isready&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Also keep in mind that, although Compose waits for the healthcheck OK, it is still recommended that your application have connection retry logic.&lt;br&gt;&lt;br&gt;
This gives you extra robustness if an unexpected condition occurs, such as a slight delay even after the healthcheck or a temporary connection loss. In short, &lt;code&gt;depends_on&lt;/code&gt; handles the initial orchestration, and it already helps a lot, but good resilience practices in the application are never too much.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In a team development context&lt;/strong&gt;, using &lt;code&gt;depends_on&lt;/code&gt;, especially with healthchecks, standardizes how everyone starts the environment. New developers do not need to “guess” the order for starting each service manually or run wait scripts. A simple &lt;code&gt;docker compose up&lt;/code&gt; already does everything in the right sequence. This greatly reduces the kind of “it works on my machine” errors caused by startup race conditions, making everyone’s workflow more reliable.&lt;/p&gt;

&lt;h1&gt;
  
  
  How do these features speed up teamwork?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Profiles
&lt;/h2&gt;

&lt;p&gt;Flexibility for different scenarios: They allow each team member to run only the set of services needed for their task. This speeds up the development cycle.&lt;br&gt;&lt;br&gt;
For example, running integration tests without starting the entire stack, or running debugging tools only when they are actually needed. Teams can define standard profiles, such as &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, and &lt;code&gt;debug&lt;/code&gt;, and avoid the need for multiple Compose files for environment variations. The result is a customizable environment that is still centralized in a single file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extends
&lt;/h2&gt;

&lt;p&gt;Consistent configuration and less repeated code: By reusing settings with &lt;code&gt;extends&lt;/code&gt; or anchors, you make sure related services share identical parameters where it makes sense: the same base image, the same credentials, the same logging policies, and so on.&lt;br&gt;&lt;br&gt;
This prevents discrepancies that could cause “it works here but not there” problems. Reducing repetition also makes editing the Compose file faster. A change to a shared port or variable is reflected everywhere, saving time and avoiding forgotten updates. In teams, this consistency means fewer configuration bugs and smoother onboarding for anyone reading or editing the Compose file for the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Depends_on
&lt;/h2&gt;

&lt;p&gt;Ordered startup and fewer failures: With dependencies properly defined and healthcheck conditions used when applicable, starting the environment becomes much more reliable. Developers do not need to perform manual steps to make sure “the database is already up” before running the application, for example. In CI pipelines and local demos, everything starts in the right order automatically. This reduces time wasted on silly troubleshooting like “oh, never mind, I just had to start service X first…” and keeps the focus on the application logic.&lt;/p&gt;

&lt;p&gt;In short, these advanced Docker Compose features work as small &lt;em&gt;productivity multipliers&lt;/em&gt; for teams: less time spent adjusting configuration and more time working on the application itself.&lt;/p&gt;

&lt;h1&gt;
  
  
  tha-tha-tha-that's all, folks!
&lt;/h1&gt;

&lt;p&gt;Docker Compose can look simple at first, but features like &lt;strong&gt;profiles&lt;/strong&gt;, &lt;strong&gt;extends&lt;/strong&gt;, and &lt;strong&gt;depends_on&lt;/strong&gt; make a real difference when a project starts to grow. With profiles, you keep optional services under control. With extends and YAML anchors, you reduce repetition and make configuration easier to maintain. With depends_on and healthchecks, you make local and team environments more predictable.&lt;/p&gt;

&lt;p&gt;Used together, these features help keep your Compose files cleaner, your development workflow faster, and your team less exposed to avoidable configuration problems. And that is exactly the kind of small improvement that pays off every day.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>cloud</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Essential Linux Commands Map</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Wed, 15 Apr 2026 13:12:52 +0000</pubDate>
      <link>https://dev.to/altairlage/essential-linux-commands-map-2c72</link>
      <guid>https://dev.to/altairlage/essential-linux-commands-map-2c72</guid>
      <description>&lt;h1&gt;
  
  
  Essential Linux Commands Map
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewyxowp0g2fow7mk62vz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fewyxowp0g2fow7mk62vz.png" alt=" " width="800" height="1021"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the evolution of operational systems visual environments, the majority of users don't ever need to use the command terminal for their daily activities. Most users do not execute any advanced system tasks, and when they do it, the configuration apps are more than enough. You probably know some Windows users that never opened the "black screen" for anything.&lt;br&gt;
The same happens with Linux. It evolved its visual environments, also known as Desktop environments (DEs), to a point that the terminal is not necessary for almost 100% of an average user needs. The most popular choices, GNOME, KDE, and XFCE, allow system configurations and troubleshooting from the UI. But when you need advanced troubleshooting and system administration, the terminal is always your best friend.&lt;/p&gt;

&lt;p&gt;You may feel intimidated the first time you open a Linux terminal. That black screen with thousands of commands, many options, and sometimes, many ways to do the same thing. Beginners often feel lost, and even experienced users sometimes fall back on the same small set of commands every day.&lt;/p&gt;

&lt;p&gt;That's why a visual command map like the main image of this article is useful. It is superficial, but focuses on the commands people use most often in real life. The main image organizes the commands into functional groups to make it easier to understand the kind of tasks they solve. Further in this article, all the groups and commands are explained briefly for reference.&lt;/p&gt;

&lt;p&gt;In practice, most terminal work is the same you perform on a UI. You move through folders, inspect files, edit content, check running processes, review system details, manage users, troubleshoot networks, and install software. Once you understand that terminal and a visual interfaces are only faces of the same coin, Linux terminal feels more practical and less overwhelming.&lt;/p&gt;

&lt;p&gt;A list of commands is not a good way to learn something. People remember things better when they make associations with other things, happenings or feelings. Grouping it by purpose works better because you create associations, for an example, "I have no internet connection" relates to networking, which can relate to IP misconfiguration, so maybe &lt;code&gt;ipconfig&lt;/code&gt; command may help to diagnose the issue. That is what makes the presented map helpful. It gives structure to the learning process.&lt;/p&gt;

&lt;p&gt;Instead of thinking, “I need to memorize all Linux commands”, you can think “I need these few commands for files, a few for processes, and a few for networking”.&lt;br&gt;
It reflects real life. Most users do not need hundreds of commands every day. They need a small set they can use with confidence for the day-by-day tasks, the same way most users don't need to know and perform multiple advanced tasks via the UI. Once that core is familiar, learning more advanced tools becomes much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  File and Directory Management
&lt;/h2&gt;

&lt;p&gt;These commands allow you move/browse around the filesystem and manage files and folders.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ls&lt;/code&gt; - List files and directories in the current location.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;ls -la&lt;/code&gt;: Lists all files (including hidden ones) in long format, showing permissions, owner, size, and modification date.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;pwd&lt;/code&gt; - Show the full path of the current working directory.

&lt;ul&gt;
&lt;li&gt;Example output: &lt;code&gt;# /home/myuser/projects/my-app&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Useful when you've navigated deep into a directory tree and need to confirm where you are.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; - Change, or moves, from one directory to another.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd /var/log&lt;/code&gt;                              # Move to an absolute path&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd ..&lt;/code&gt;                                    # Move one level up&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd ~&lt;/code&gt;                                     # Move to the current user home directory&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mkdir&lt;/code&gt; - Create a new directory.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mkdir my-folder&lt;/code&gt;                          # Create the "my-folder" folder in current directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mkdir -p parent/child/grandchild&lt;/code&gt;         # Create nested directories in one go

&lt;ul&gt;
&lt;li&gt;The -p flag creates intermediate directories as needed, so you don't have to create each level manually.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;rmdir&lt;/code&gt; - Remove an empty directory.

&lt;ul&gt;
&lt;li&gt;Example: &lt;code&gt;rmdir old-folder&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This only works if the directory is completely empty. If it contains files, you'll need &lt;code&gt;rm -r&lt;/code&gt; instead.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;touch&lt;/code&gt; - Create an empty file or updates a file timestamp.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;touch notes.txt&lt;/code&gt;                          # Create a new empty file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;touch existing-file.log&lt;/code&gt;                  # Update the modification timestamp to now&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;cp&lt;/code&gt; - Copie files or directories.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cp report.txt report-backup.txt&lt;/code&gt;          # Copy the &lt;code&gt;report.txt&lt;/code&gt; file and name it to &lt;code&gt;report-backup.txt&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cp -r src/ src-backup/&lt;/code&gt;                   # Copy the &lt;code&gt;src&lt;/code&gt; directory recursively&lt;/li&gt;
&lt;li&gt;The -r (recursive) flag is required when copying directories, otherwise cp will skip them.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;mv&lt;/code&gt; - Move or renames files and directories.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mv old-name.txt new-name.txt&lt;/code&gt;             # Rename a file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mv file.txt ~/Documents/&lt;/code&gt;                 # Move a file to another directory&lt;/li&gt;
&lt;li&gt;Unlike &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt; works on directories without needing any extra flags.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;rm&lt;/code&gt; - Remove files or directories.

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rm unwanted-file.txt&lt;/code&gt;                     # Remove the file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rm -r old-project/&lt;/code&gt;                       # Remove a directory and everything inside it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rm -ri important-folder/&lt;/code&gt;                 # Remove recursively but ask for confirmation on each file&lt;/li&gt;
&lt;li&gt;Be careful with &lt;code&gt;rm -r&lt;/code&gt; there is no trash can in the terminal. Once removed, files are gone for good.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These are often the first commands people learn, and for good reason. They are the foundation of daily terminal use. If you think about it, this is also the most frequent actions you perform in a visual interface, like Windows.&lt;/p&gt;

&lt;h2&gt;
  
  
  File Viewing and Editing
&lt;/h2&gt;

&lt;p&gt;Once you find a file, the next step is usually to read or edit it. These commands handle these actions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;cat&lt;/code&gt; - Print file content directly in the terminal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cat server.log&lt;/code&gt;                          # Display the entire file in the terminal&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cat -n server.log&lt;/code&gt;                       # Display with line numbers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cat file1.txt file2.txt &amp;gt; combined.txt&lt;/code&gt;  # Concatenate two files into a new one&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;less&lt;/code&gt; - Open a file for scrolling and reading page by page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;less /var/log/syslog&lt;/code&gt;                    # Open a log file for browsing (use q to quit)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;less -N app.log&lt;/code&gt;                         # Open with line numbers shown&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dmesg | less&lt;/code&gt;                            # Pipe command output into less for easy scrolling&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;more&lt;/code&gt; - Display file content one screen at a time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;more readme.txt&lt;/code&gt;                         # View the file one screenful at a time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;more -10 config.yaml&lt;/code&gt;                    # Display 10 lines at a time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ls -la /etc | more&lt;/code&gt;                      # Pipe a long directory listing through more&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;nano&lt;/code&gt; - A simple terminal-based text editor.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nano notes.txt&lt;/code&gt;                          # Open (or create) a file for editing&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nano +15 script.sh&lt;/code&gt;                      # Open a file and jump directly to line 15&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nano -B /etc/hosts&lt;/code&gt;                      # Open a file and automatically create a backup before editing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;vim&lt;/code&gt; - A powerful terminal-based text editor with advanced features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim deploy.sh&lt;/code&gt;                           # Open a file for editing (press i to enter insert mode, Esc then :wq to save and quit)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim +42 main.py&lt;/code&gt;                         # Open a file and jump to line 42&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vim -d file-v1.txt file-v2.txt&lt;/code&gt;          # Open two files side by side in diff mode&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;gedit&lt;/code&gt; - A graphical text editor often found on desktop Linux systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gedit todo.txt&lt;/code&gt;                          # Open a file in the graphical editor&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gedit +25 app.conf&lt;/code&gt;                      # Open a file and place the cursor on line 25&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gedit file1.txt file2.txt&lt;/code&gt;               # Open multiple files in separate tabs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This group is useful for everything from reading logs to editing config files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process Management
&lt;/h2&gt;

&lt;p&gt;Linux is always running processes in the background and foreground. These commands help you inspect and control them. It is similar to the Windows Task Manager, but in text mode.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ps&lt;/code&gt; - Show a snapshot of running processes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ps aux&lt;/code&gt;                         # List all running processes with detailed info&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ps -ef | grep nginx&lt;/code&gt;            # Find all processes related to nginx&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ps -u jdoe&lt;/code&gt;                     # Show all processes owned by user jdoe&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;top&lt;/code&gt; - Display live system activity and active processes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top&lt;/code&gt;                            # Launch the interactive process viewer&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top -u www-data&lt;/code&gt;                # Show only processes owned by the www-data user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;top -p 1234,5678&lt;/code&gt;              # Monitor only specific PIDs&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;kill&lt;/code&gt; - Send a signal to stop or control a process by PID.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kill 1234&lt;/code&gt;                      # Gracefully terminate process with PID 1234 (sends SIGTERM)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kill -9 1234&lt;/code&gt;                   # Force-kill a stubborn process (sends SIGKILL)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kill -STOP 1234&lt;/code&gt;               # Pause a running process without ending it&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;killall&lt;/code&gt; - Stop processes by name.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;killall firefox&lt;/code&gt;                # Terminate all Firefox processes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;killall -9 node&lt;/code&gt;               # Force-kill all Node.js processes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;killall -u jdoe python&lt;/code&gt;        # Kill all Python processes owned by user jdoe&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;pstree&lt;/code&gt; - Display processes in a tree structure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pstree&lt;/code&gt;                         # Show all processes as a tree from init/systemd&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pstree -p&lt;/code&gt;                      # Show the tree with PIDs next to each process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pstree -u jdoe&lt;/code&gt;                # Show the process tree for a specific user&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;htop&lt;/code&gt; - An interactive process viewer with a cleaner interface than &lt;code&gt;top&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;htop&lt;/code&gt;                           # Launch the interactive viewer with color-coded output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;htop -u www-data&lt;/code&gt;              # Filter to show only a specific user's processes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;htop -p 1234,5678&lt;/code&gt;            # Monitor only specific PIDs in the interactive viewer&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;When a system is slow or an app freezes, this is usually where you start troubleshooting.&lt;/p&gt;

&lt;h2&gt;
  
  
  System Information
&lt;/h2&gt;

&lt;p&gt;These commands help you learn more about the machine itself, including hardware, storage, and memory usage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;uname&lt;/code&gt; - Show basic system information such as kernel and OS name and version.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;uname -a&lt;/code&gt;                       # Display all system info (kernel, hostname, architecture, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;uname -r&lt;/code&gt;                       # Show only the kernel release version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;uname -m&lt;/code&gt;                       # Print the machine hardware architecture (e.g., x86_64)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;df&lt;/code&gt; - Report disk space usage by filesystem.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;df -h&lt;/code&gt;                          # Show disk usage in human-readable format (GB, MB)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;df -h /home&lt;/code&gt;                    # Check available space on the /home partition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;df -T&lt;/code&gt;                          # Include the filesystem type in the output (ext4, xfs, etc.)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;du&lt;/code&gt; - Estimate disk usage for files and directories.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;du -sh /var/log&lt;/code&gt;                # Show total size of the /var/log directory in human-readable format&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;du -h --max-depth=1 /home&lt;/code&gt;     # Show sizes of immediate subdirectories under /home&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;du -ah /tmp | sort -rh | head -10&lt;/code&gt;  # Find the 10 largest files and folders in /tmp&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;free&lt;/code&gt; - Display memory and swap usage.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;free -h&lt;/code&gt;                        # Show RAM and swap usage in human-readable format&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;free -m&lt;/code&gt;                        # Display memory values in megabytes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;free -h -s 5&lt;/code&gt;                  # Refresh memory stats every 5 seconds&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;lscpu&lt;/code&gt; - Show CPU architecture details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lscpu&lt;/code&gt;                          # Display full CPU info (cores, threads, model, cache, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lscpu | grep "Model name"&lt;/code&gt;     # Show only the CPU model name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lscpu | grep "CPU(s)"&lt;/code&gt;         # Check the total number of CPUs/cores available&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;lshw&lt;/code&gt; - List detailed hardware information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo lshw -short&lt;/code&gt;              # Show a compact summary of all hardware components&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo lshw -class network&lt;/code&gt;      # Display only network adapter details&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo lshw -class memory&lt;/code&gt;       # Show RAM module details (size, speed, slots)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;lsblk&lt;/code&gt; - Display block devices such as disks and partitions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lsblk&lt;/code&gt;                          # List all block devices in a tree view&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lsblk -f&lt;/code&gt;                       # Include filesystem type and UUIDs in the output&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lsblk -o NAME,SIZE,TYPE,MOUNTPOINT&lt;/code&gt;  # Show only specific columns for a cleaner view&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This category is especially helpful for troubleshooting and performance checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  User and Group Management
&lt;/h2&gt;

&lt;p&gt;Linux is built around users, groups, and permissions. These commands support account administration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;passwd&lt;/code&gt; - Changes a user password.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;passwd&lt;/code&gt;                         # Change the password for the currently logged-in user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo passwd jdoe&lt;/code&gt;              # Reset the password for user jdoe (requires root)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;passwd -e jdoe&lt;/code&gt;                # Force user jdoe to change password on next login&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;useradd&lt;/code&gt; - Creates a new user account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo useradd jdoe&lt;/code&gt;             # Create a new user with default settings&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo useradd -m -s /bin/bash jdoe&lt;/code&gt;  # Create a user with a home directory and bash shell&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo useradd -G developers,docker jdoe&lt;/code&gt;  # Create a user and add them to multiple groups&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;userdel&lt;/code&gt; - Deletes a user account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo userdel jdoe&lt;/code&gt;             # Remove the user account but keep the home directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo userdel -r jdoe&lt;/code&gt;          # Remove the user and delete their home directory&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo userdel -f jdoe&lt;/code&gt;          # Force removal even if the user is currently logged in&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;usermod&lt;/code&gt; - Modifies an existing user account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo usermod -aG docker jdoe&lt;/code&gt;  # Add user jdoe to the docker group without removing other groups&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo usermod -s /bin/zsh jdoe&lt;/code&gt; # Change the default shell for user jdoe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo usermod -l jsmith jdoe&lt;/code&gt;   # Rename the user account from jdoe to jsmith&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;groupadd&lt;/code&gt; - Creates a new group.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupadd developers&lt;/code&gt;      # Create a new group called developers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupadd -g 1500 devops&lt;/code&gt;  # Create a group with a specific GID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupadd --system appusers&lt;/code&gt;  # Create a system group for service accounts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;groupdel&lt;/code&gt; - Deletes a group.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupdel developers&lt;/code&gt;      # Remove the developers group&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupdel old-team&lt;/code&gt;        # Delete a group that is no longer needed&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo groupdel temp-project&lt;/code&gt;    # Clean up a temporary project group&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;groups&lt;/code&gt; - Shows the groups a user belongs to.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;groups&lt;/code&gt;                         # Show the groups for the currently logged-in user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;groups jdoe&lt;/code&gt;                   # List all groups that user jdoe belongs to&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;groups root&lt;/code&gt;                   # Check which groups the root user is a member of&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;id&lt;/code&gt; - Displays user ID, group ID, and related group information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt;                             # Show UID, GID, and groups for the current user&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id jdoe&lt;/code&gt;                       # Display the full identity info for user jdoe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;id -gn jdoe&lt;/code&gt;                   # Print only the primary group name of user jdoe&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Specially if you manage shared systems or servers, you will use these commands very often.&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Configuration and Monitoring
&lt;/h2&gt;

&lt;p&gt;Networking is a big part of Linux administration. These commands help you inspect connections and test communication.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ifconfig&lt;/code&gt; - Displays or configures network interfaces on older systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ifconfig&lt;/code&gt;                       # Show all active network interfaces and their IPs&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ifconfig eth0&lt;/code&gt;                  # Display details for a specific interface&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo ifconfig eth0 down&lt;/code&gt;       # Disable the eth0 network interface&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;ip&lt;/code&gt; - Modern command for viewing and managing network interfaces, routes, and addresses.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ip addr show&lt;/code&gt;                   # List all interfaces with their IP addresses&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ip route show&lt;/code&gt;                  # Display the routing table&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ip link set eth0 up&lt;/code&gt;           # Bring the eth0 interface up&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;ping&lt;/code&gt; - Test the connectivity to another host.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ping google.com&lt;/code&gt;                # Continuously ping Google to check internet connectivity&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ping -c 4 192.168.1.1&lt;/code&gt;        # Send exactly 4 ping packets to a host&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ping -i 2 server.local&lt;/code&gt;       # Ping every 2 seconds instead of the default 1 second&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;netstat&lt;/code&gt; - Show network connections, routing tables, and interface stats.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netstat -tulnp&lt;/code&gt;                 # Show all listening TCP/UDP ports with process names&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netstat -an | grep :80&lt;/code&gt;        # Check if anything is listening on port 80&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;netstat -r&lt;/code&gt;                     # Display the kernel routing table&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;ss&lt;/code&gt; - Display socket and network connection information, often faster than &lt;code&gt;netstat&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ss -tulnp&lt;/code&gt;                      # List all listening ports with associated processes&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ss -s&lt;/code&gt;                          # Show a summary of socket statistics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ss -t state established&lt;/code&gt;       # Display only established TCP connections&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;traceroute&lt;/code&gt; - Show the path packets take to reach a destination.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;traceroute google.com&lt;/code&gt;          # Trace the route to Google showing each hop&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;traceroute -n 8.8.8.8&lt;/code&gt;        # Trace without resolving hostnames (faster output)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;traceroute -m 15 example.com&lt;/code&gt;  # Set a maximum of 15 hops&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;ssh&lt;/code&gt; - Connect securely to a remote machine.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ssh jdoe@192.168.1.50&lt;/code&gt;        # Connect to a remote host as user jdoe&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ssh -p 2222 jdoe@server.com&lt;/code&gt;  # Connect using a non-default SSH port&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ssh -i ~/.ssh/mykey.pem ec2-user@10.0.0.5&lt;/code&gt;  # Connect using a specific private key&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;nc&lt;/code&gt; - Netcat, a flexible tool for testing ports, sending data, and debugging network services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nc -zv server.com 443&lt;/code&gt;         # Test if port 443 is open on a remote host&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nc -l 8080&lt;/code&gt;                    # Listen for incoming connections on port 8080&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nc -zv 192.168.1.10 20-100&lt;/code&gt;   # Scan a range of ports on a host&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This is the part of Linux that becomes essential the moment something stops connecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Package Management
&lt;/h2&gt;

&lt;p&gt;Linux distributions use package managers to install, update, and remove software. The exact tool depends on the distro.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;apt-get&lt;/code&gt; - Package management tool used on Debian-based systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo apt-get update&lt;/code&gt;            # Refresh the list of available packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo apt-get install nginx&lt;/code&gt;    # Install the nginx web server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo apt-get remove --purge nginx&lt;/code&gt;  # Remove nginx and its configuration files&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;apt&lt;/code&gt; - A more user-friendly package command for Debian-based systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade&lt;/code&gt;  # Update package list and upgrade all packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo apt install git curl wget&lt;/code&gt; # Install multiple packages at once&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;apt search image editor&lt;/code&gt;       # Search for packages related to image editing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;yum&lt;/code&gt; - Older package manager for RPM-based distributions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo yum install httpd&lt;/code&gt;         # Install the Apache web server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo yum update&lt;/code&gt;               # Update all installed packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yum list installed&lt;/code&gt;            # Show all currently installed packages&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;dnf&lt;/code&gt; - Modern package manager used in newer RPM-based distributions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo dnf install nodejs&lt;/code&gt;        # Install Node.js&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo dnf upgrade --refresh&lt;/code&gt;    # Refresh metadata and upgrade all packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dnf search python3&lt;/code&gt;            # Search for packages matching python3&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;rpm&lt;/code&gt; - Low-level tool for managing RPM packages directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo rpm -ivh package.rpm&lt;/code&gt;      # Install a local RPM package file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rpm -qa | grep java&lt;/code&gt;           # List all installed packages containing "java"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rpm -qi nginx&lt;/code&gt;                 # Show detailed info about an installed package&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;dpkg&lt;/code&gt; - Low-level tool for managing Debian packages directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo dpkg -i package.deb&lt;/code&gt;       # Install a local .deb package file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dpkg -l | grep python&lt;/code&gt;         # List installed packages matching "python"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dpkg -L nginx&lt;/code&gt;                 # Show all files installed by the nginx package&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;snap&lt;/code&gt; - Installs and manages snap packages across supported distributions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo snap install code --classic&lt;/code&gt;  # Install VS Code as a snap package&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;snap list&lt;/code&gt;                      # Show all installed snap packages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo snap refresh&lt;/code&gt;             # Update all installed snaps to their latest versions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;code&gt;zypper&lt;/code&gt; - Package manager used on openSUSE and SUSE systems.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Examples:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo zypper install git&lt;/code&gt;        # Install git on an openSUSE system&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sudo zypper refresh&lt;/code&gt;           # Refresh all configured repositories&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zypper search docker&lt;/code&gt;          # Search for packages related to docker&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Not every Linux system uses all of these, but knowing the distro family you use will help you to know which commands to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Learning
&lt;/h2&gt;

&lt;p&gt;Start learning the commands in small groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start with navigation: &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then learn file handling: &lt;code&gt;touch&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add file reading and editing: &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;less&lt;/code&gt;, &lt;code&gt;nano&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Move into process and system checks: &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;top&lt;/code&gt;, &lt;code&gt;df&lt;/code&gt;, &lt;code&gt;free&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finish with network basics: &lt;code&gt;ip&lt;/code&gt;, &lt;code&gt;ping&lt;/code&gt;, &lt;code&gt;ssh&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Th-Th-That's all, folks!
&lt;/h2&gt;

&lt;p&gt;Linux becomes much easier once you stop seeing it as a wall of commands and start seeing it as a set of tools for clear tasks. This map is a good reminder that the terminal is not about complexity for the sake of complexity. It is about control, speed, and understanding what your system is doing.&lt;/p&gt;

&lt;p&gt;You do not need to master every command today. Learn the ones that solve the problems in front of you. Use them often. Repeat them in real situations. That is how confidence grows.&lt;/p&gt;

&lt;p&gt;And after a while, the terminal stops feeling technical and starts feeling natural.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>softwaredevelopment</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Apache Kafka tutorial – What is Apache Kafka?</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Tue, 14 Apr 2026 22:18:13 +0000</pubDate>
      <link>https://dev.to/altairlage/apache-kafka-tutorial-what-is-apache-kafka-4edl</link>
      <guid>https://dev.to/altairlage/apache-kafka-tutorial-what-is-apache-kafka-4edl</guid>
      <description>&lt;p&gt;Apache Kafka is an open-source distributed event streaming platform used by thousands of companies to publish, store, and process streams of records in real time. It was originally developed by LinkedIn before moving into the open-source world in early 2011. It was built because LinkedIn needed a better way to handle massive amounts of data to track site events, like page views and user clicks, and to gather all their log data in one place.&lt;/p&gt;

&lt;p&gt;Kafka is designed for distributed high throughput systems. Kafka tends to work very well as a replacement for a more traditional message broker. In comparison to other messaging systems, Kafka has better throughput, built-in partitioning, replication and inherent fault-tolerance, which makes it a good fit for large-scale message processing applications.&lt;br&gt;
In this tutorial, we are going to dive into what Kafka actually is and walk through the most common definitions you'll run into when working with it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who is using Kafka?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Twitter&lt;/strong&gt; uses Kafka to power its mobile application performance management and analytics platform. In 2015, this system was already handling around five billion sessions per day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Netflix&lt;/strong&gt; relies on Kafka as the messaging backbone for its Keystone pipeline, a unified platform for publishing, collecting, and routing events across both batch and stream processing. As of 2016, Keystone included more than 4,000 brokers running entirely in the cloud, handling over 700 billion events every single day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tumblr&lt;/strong&gt; uses Kafka as a core part of its event processing pipeline. In 2012, it was already capturing up to 500 million page views per day through this system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Square&lt;/strong&gt; uses Kafka as its central data bus. It supports stream processing, website activity tracking, metrics collection, monitoring, log aggregation, real-time analytics, and complex event processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pinterest&lt;/strong&gt; runs Kafka as part of its real-time advertising platform. The system includes over 100 clusters and more than 2,000 brokers deployed on AWS. It processes more than 800 billion events per day, with peaks reaching up to 15 million events per second.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uber&lt;/strong&gt; is one of the most well-known Kafka adopters. The company processes over a trillion events per day using Kafka, mainly for data ingestion, event stream processing, database changelogs, log aggregation, and general-purpose publish-subscribe messaging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kafka architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnitnqcq9nxo73g5953q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnitnqcq9nxo73g5953q7.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kafka is a publish/subscribe system built around event data. It involves four main actors: producers, consumers, brokers, and ZooKeeper nodes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Broker nodes&lt;/strong&gt;: These handle most of the I/O work and are responsible for durable data storage within the cluster. A Kafka broker receives messages from producers and writes them to disk, organizing them by partition and indexing them with a unique &lt;strong&gt;offset&lt;/strong&gt;. Consumers can then fetch messages by topic, partition, and offset. Brokers also work together to form a Kafka cluster, sharing information either directly or indirectly through ZooKeeper.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ZooKeeper nodes&lt;/strong&gt;: Kafka relies on ZooKeeper to manage the overall state of the cluster. It keeps track of broker health, maintains metadata about topics, and helps coordinate cluster operations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Producers&lt;/strong&gt;: Producers are responsible for sending messages to Kafka brokers, typically organized by topic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consumers&lt;/strong&gt;: Consumers are client applications that read messages from Kafka topics.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the diagram above, a topic is divided into three partitions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Partition 1 contains two offsets: 0 and 1
&lt;/li&gt;
&lt;li&gt;Partition 2 contains four offsets: 0, 1, 2, and 3
&lt;/li&gt;
&lt;li&gt;Partition 3 contains a single offset: 0
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;strong&gt;replica&lt;/strong&gt; is simply a copy of a partition, including the same data, offsets, and partition ID.&lt;/p&gt;

&lt;p&gt;Now, consider a scenario where the &lt;strong&gt;replication factor&lt;/strong&gt; is set to 3. Kafka will create three identical copies of each partition and distribute them across the cluster to ensure availability and fault tolerance. In the example shown, the replication factor is 1, meaning each partition has only one copy.&lt;/p&gt;

&lt;p&gt;To balance load across the cluster, partitions are distributed among brokers, and each broker can store one or more partitions. At the same time, multiple producers and consumers can publish and read messages concurrently, making Kafka highly scalable and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kafka component concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Broker nodes
&lt;/h3&gt;

&lt;p&gt;A broker acts as the middle layer between producers and consumers, helping move data across the system. It stores messages in partitions and ensures that data is safely persisted for a configurable amount of time. This design also helps Kafka handle failure scenarios without losing data.&lt;/p&gt;

&lt;p&gt;In Kafka, a broker is a key unit of scalability. By increasing the number of brokers in a cluster, you can improve I/O throughput, availability, and overall durability. Brokers also coordinate with each other and communicate with ZooKeeper to maintain cluster state and consistency.&lt;/p&gt;

&lt;p&gt;In most setups, each server runs a single broker. While it is technically possible to run multiple brokers on the same server, this is generally not recommended in production environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Topic
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Kafka Topic&lt;/strong&gt; is where messages sent by producers are stored. Topics are split into &lt;strong&gt;partitions&lt;/strong&gt;, and each topic has at least one partition. Each partition contains messages in an immutable and ordered sequence. Once a message is written, it cannot be changed. A partition is internally implemented as a set of segment files of equal sizes. So we can imagine a topic as a logical aggregation of partitions. By splitting a topic into multiple partitions, Kafka can process data in parallel, which improves performance and scalability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0ij2as3pxdggo8ourq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0ij2as3pxdggo8ourq8.png" alt=" " width="800" height="891"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a producer publish a record, the producer automatically select a partition based on the record’s key. A producer will digest the byte content of the key using a hash function (Kafka uses murmur2 for this purpose). &lt;/p&gt;

&lt;p&gt;The process works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The key is hashed using murmur2.&lt;/li&gt;
&lt;li&gt;The highest-order bit is masked to ensure the result is a positive integer.&lt;/li&gt;
&lt;li&gt;The final partition number value is calculated using modulo with the number of partitions.
This process determines the target partition for the record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, records with the same key will always be routed to the same partition, ensuring ordering for that key. However, if the number of partitions changes, the hash result will also change. This means Kafka may assign the same key to a different partition after the change.&lt;/p&gt;

&lt;p&gt;The topic structure, contents, and how producers interact with partitions are depicted below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nvr11dywkok9k8z1nw1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nvr11dywkok9k8z1nw1.png" alt=" " width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the nature of hashing: Records with different hashes may still end up in the same partition due to hash collisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consumer groups and load balancing
&lt;/h2&gt;

&lt;p&gt;Kafka’s producer-topic-consumer topology adheres to a flexible and highly scalable model. A multipoint-to-multipoint model, which means multiple producers and multiple consumers can interact with the same topic at the same time.&lt;/p&gt;

&lt;p&gt;A consumer is a process (or thread) that attaches to a Kafka cluster using a client library. When multiple consumers subscribe to a topic and belong to the same &lt;strong&gt;consumer group&lt;/strong&gt;, Kafka distributes the partitions among the consumer in the group. Each consumer reads from a different subset of partitions in the topic.&lt;/p&gt;

&lt;p&gt;Let’s walk through an example.&lt;/p&gt;

&lt;p&gt;Suppose we have a topic called &lt;strong&gt;T1&lt;/strong&gt; with four partitions. If we create a single consumer &lt;strong&gt;C1&lt;/strong&gt; in group &lt;strong&gt;G1&lt;/strong&gt; and subscribe it to topic &lt;strong&gt;T1&lt;/strong&gt;, then &lt;strong&gt;C1&lt;/strong&gt; will receive messages from all four partitions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtu6flnt88it9eki6ygs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtu6flnt88it9eki6ygs.png" alt=" " width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, if we add a second consumer &lt;strong&gt;C2&lt;/strong&gt; to the same group &lt;strong&gt;G1&lt;/strong&gt;, Kafka will rebalance the partitions. Each consumer will now read from two partitions. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C1 reads from partitions 0 and 2
&lt;/li&gt;
&lt;li&gt;C2 reads from partitions 1 and 3
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3ell2mwq95suda6rrve.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3ell2mwq95suda6rrve.png" alt=" " width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we keep adding more consumers to the same group &lt;strong&gt;G1&lt;/strong&gt;, and the number of consumers exceeds the number of partitions, some consumers will remain idle. This happens because Kafka guarantees that &lt;strong&gt;each partition is assigned to only one consumer within a group&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqo9qr4zpqmmeglg4hva.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqo9qr4zpqmmeglg4hva.png" alt=" " width="800" height="669"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if a new consumer group &lt;strong&gt;G2&lt;/strong&gt; is introduced, with a single consumer. This consumer will receive &lt;strong&gt;all&lt;/strong&gt; messages from topic &lt;strong&gt;T1&lt;/strong&gt;, completely independent of what group &lt;strong&gt;G1&lt;/strong&gt; is doing.&lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;G2&lt;/strong&gt; has multiple consumers, Kafka will again split the partitions among them, just like it does for &lt;strong&gt;G1&lt;/strong&gt;. However, the key point is that &lt;strong&gt;each consumer group receives the full stream of messages&lt;/strong&gt;, regardless of other groups.&lt;/p&gt;

&lt;p&gt;This works because of how Kafka manages offsets:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Offsets are managed by consumers, but they are stored in a special Kafka topic called &lt;code&gt;__consumer_offsets&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Offsets are tracked per &lt;strong&gt;(consumer group, topic, partition)&lt;/strong&gt; combination.
&lt;/li&gt;
&lt;li&gt;This combination is used as the key when storing offsets, which allows Kafka to:

&lt;ul&gt;
&lt;li&gt;Keep offsets organized in the same partition of the &lt;code&gt;__consumer_offsets&lt;/code&gt; topic.&lt;/li&gt;
&lt;li&gt;Use log compaction to remove outdated offset records.&lt;/li&gt;
&lt;li&gt;Efficiently manage progress tracking for each consumer group.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By default, the &lt;code&gt;__consumer_offsets&lt;/code&gt; topic is configured with 50 partitions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47jduc3hu02lw6xq8uvz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47jduc3hu02lw6xq8uvz.png" alt=" " width="800" height="835"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Th-th-that's all, folks!
&lt;/h2&gt;

&lt;p&gt;Apache Kafka is much more than just a messaging system. It is a distributed event streaming platform designed to handle large-scale data with high throughput, reliability, and scalability.&lt;/p&gt;

&lt;p&gt;The key takeaway is simple: Kafka is built for &lt;strong&gt;movement, durability, and scalability of data&lt;/strong&gt;. Once you understand these core concepts, everything else, from stream processing to real-time analytics, becomes much easier to reason about.&lt;/p&gt;

&lt;p&gt;If you're starting with Kafka, these fundamentals are the base for everything you will build on top of it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>kafka</category>
      <category>eventdriven</category>
    </item>
    <item>
      <title>Essential AWS services every engineer should know</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Mon, 13 Apr 2026 19:48:38 +0000</pubDate>
      <link>https://dev.to/altairlage/essential-aws-services-every-engineer-should-know-1p5j</link>
      <guid>https://dev.to/altairlage/essential-aws-services-every-engineer-should-know-1p5j</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwiuuy96haflhecmq6xh3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwiuuy96haflhecmq6xh3.png" alt=" " width="800" height="913"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we start learning AWS, the number of services feels overwhelming.&amp;nbsp;But we don't need to learn everything at once. A strong foundation usually starts with a few key groups, like&amp;nbsp;&lt;strong&gt;compute, storage, databases, networking, security, monitoring, etc.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This chart is a simple way to see how the AWS ecosystem is organized. It brings together core services in one place.&lt;/p&gt;

&lt;p&gt;My advice is to start with the basics. Then connect the dots as long as you need.&lt;/p&gt;

&lt;p&gt;A practical start could look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create and manage your networking with &lt;strong&gt;VPC&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Run apps with &lt;strong&gt;EC2&lt;/strong&gt;, &lt;strong&gt;Lambda&lt;/strong&gt;, or &lt;strong&gt;ECS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Store data in &lt;strong&gt;S3&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Store your servers data with&amp;nbsp;&lt;strong&gt;EBS&lt;/strong&gt;, or &lt;strong&gt;EFS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Use&amp;nbsp;&lt;strong&gt;RDS&lt;/strong&gt; and&amp;nbsp;&lt;strong&gt;Aurora&lt;/strong&gt; for your relational databases.&lt;/li&gt;
&lt;li&gt;Refer &lt;strong&gt;DynamoDB&lt;/strong&gt; for your NoSQL DBs.&lt;/li&gt;
&lt;li&gt;Secure access with &lt;strong&gt;IAM&lt;/strong&gt;, &lt;strong&gt;KMS&lt;/strong&gt;, and &lt;strong&gt;Secrets Manager&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Monitor everything with &lt;strong&gt;CloudWatch&lt;/strong&gt;, and troubleshoot with &lt;strong&gt;CloudTrail&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Automate delivery with &lt;strong&gt;CodePipeline&lt;/strong&gt;, &lt;strong&gt;CodeBuild&lt;/strong&gt;, and &lt;strong&gt;CodeDeploy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Make your apps to talk with each other with &lt;strong&gt;SQS&lt;/strong&gt; and &lt;strong&gt;SNS&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Manage your resources with Infrastructure as Code with &lt;strong&gt;CloudFormation&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS gets much easier when you stop seeing isolated services and start seeing how they work together.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>webdev</category>
      <category>softwaredevelopment</category>
      <category>devops</category>
    </item>
    <item>
      <title>DevOps Engineer Routine</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Mon, 13 Apr 2026 14:45:05 +0000</pubDate>
      <link>https://dev.to/altairlage/devops-engineer-routine-54ef</link>
      <guid>https://dev.to/altairlage/devops-engineer-routine-54ef</guid>
      <description>&lt;p&gt;Every DevOps knows this feeling&lt;/p&gt;

&lt;p&gt;On one side, there’s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure melting down at 2 AM.&lt;/li&gt;
&lt;li&gt;CI/CD pipelines stuck in "pending" forever.&lt;/li&gt;
&lt;li&gt;Mysterious server crashes with zero warning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the other side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Is it safe to push to production today?".&lt;/li&gt;
&lt;li&gt;“Why did the app get so slow all of a sudden?”.&lt;/li&gt;
&lt;li&gt;“But everything was fine in staging…”.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s the job, really. DevOps isn't about learning and using the latest fashion tools.&lt;br&gt;
It's about staying calm under fire, bringing order to chaos, and designing systems resilient enough to handle reality, not just theory.&lt;/p&gt;

&lt;p&gt;What really helps in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitoring that raises the flag before users feel the impact.&lt;/li&gt;
&lt;li&gt;CI/CD pipelines clean and simple enough for anyone to follow and trust.&lt;/li&gt;
&lt;li&gt;Automation for repetitive work, so people spend time fixing problems instead of clicking through tasks.&lt;/li&gt;
&lt;li&gt;Clear ownership and documentation that stays useful over time (instead of relying on tribal knowledge).&lt;/li&gt;
&lt;li&gt;Blameless postmortems that turn outages and mistakes into concrete improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're a DevOps, SRE, Cloud, or Platform Engineer, you already know this feeling. We all spend time dealing with fires. But the real goal is not just becoming better at reacting. It’s designing systems where fewer fires happen at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v8kiywbd3hhru81sinh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5v8kiywbd3hhru81sinh.png" alt=" " width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>infrastructure</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>New tutorial, folks!</title>
      <dc:creator>Altair Lage</dc:creator>
      <pubDate>Mon, 30 Mar 2026 17:38:18 +0000</pubDate>
      <link>https://dev.to/altairlage/new-tutorial-folks-3ill</link>
      <guid>https://dev.to/altairlage/new-tutorial-folks-3ill</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/altairlage/rabbitmq-management-interface-24b1" class="crayons-story__hidden-navigation-link"&gt;RabbitMQ Management Interface&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/altairlage" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3462854%2F0e9c166e-909e-40b3-8881-cf96fa18e64e.png" alt="altairlage profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/altairlage" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Altair Lage
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Altair Lage
                
                
              
              &lt;div id="story-author-preview-content-3431788" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/altairlage" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3462854%2F0e9c166e-909e-40b3-8881-cf96fa18e64e.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Altair Lage&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/altairlage/rabbitmq-management-interface-24b1" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 30&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/altairlage/rabbitmq-management-interface-24b1" id="article-link-3431788"&gt;
          RabbitMQ Management Interface
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/altairlage/rabbitmq-management-interface-24b1" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/altairlage/rabbitmq-management-interface-24b1#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            12 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>webdev</category>
      <category>devops</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
