<?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: Matsu</title>
    <description>The latest articles on DEV Community by Matsu (@devmatsu).</description>
    <link>https://dev.to/devmatsu</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%2F1252052%2Faad6ebe9-eaa8-4f3c-9f0c-091b75ddd03d.png</url>
      <title>DEV Community: Matsu</title>
      <link>https://dev.to/devmatsu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devmatsu"/>
    <language>en</language>
    <item>
      <title>The AI Engineering Concepts I Wish Someone Explained Simply</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Wed, 21 Oct 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/devmatsu/the-ai-engineering-concepts-i-wish-someone-explained-simply-5aoc</link>
      <guid>https://dev.to/devmatsu/the-ai-engineering-concepts-i-wish-someone-explained-simply-5aoc</guid>
      <description>&lt;p&gt;It’s fascinating how AI is changing the day-to-day work of software engineers.&lt;/p&gt;

&lt;p&gt;We used to spend a lot of time learning syntax (or should I say memorizing it? haha) and understanding the abstractions behind frameworks and libraries.&lt;/p&gt;

&lt;p&gt;Then AI-assisted coding became part of our daily work, and we started hearing about the "vibe coding": using AI to build something while focusing mostly on the outcome, sometimes without paying enough attention to the bigger picture—architecture, reliability, security, and best practices.&lt;/p&gt;

&lt;p&gt;Then came agentic coding, which I think is where many developers are right now: using agents to generate code, navigate repositories, run commands, and help implement changes.&lt;/p&gt;

&lt;p&gt;Now there’s this idea of &lt;strong&gt;Agentic Engineering&lt;/strong&gt;, which goes a bit further. Instead of just asking an agent to write code, it's about optimizing our day-to-day work by delegating tasks to agents that are configured with the right context.&lt;/p&gt;

&lt;p&gt;I was watching an IBM video about Agentic Engineering linked in this &lt;a href="https://www.ibm.com/think/topics/agentic-engineering" rel="noopener noreferrer"&gt;article&lt;/a&gt;, and one idea that stuck with me was this shift from writing to shaping. &lt;/p&gt;

&lt;p&gt;Instead of writing everything ourselves, we start shaping the environment around agents—defining rules, skills, context, tools, and what we actually expect from them - so they can work in sync with what we need. And IMO, this is where the future of software engineering is going.&lt;/p&gt;

&lt;p&gt;Agentic Engineering goes way beyond just writing code. With the right setup and context, you can have agents handle many of the tasks that are part of your everyday engineering work. Need to understand what happened with a specific request? Have an agent investigate the logs. Want to check if an implementation actually follows the tech spec? Let an agent compare them. Need to investigate a bug, review some code, or figure out why something isn't working as expected? Those are tasks you can delegate to an agent too.&lt;/p&gt;

&lt;p&gt;The idea is simple: instead of using agents only to write code, you can use them to do the engineering work around the code. The interesting part is that our job starts becoming less about writing everything ourselves and more about shaping how the work gets done.&lt;/p&gt;

&lt;p&gt;But once you start exploring this, you run into a bunch of terms: agents, tokens, context engineering, skills, MCP, orchestration... and it isn't always obvious what each one means or how they fit together. And that's exactly why I wanted to write this post.&lt;/p&gt;

&lt;p&gt;I've been learning about these concepts while exploring different tools and ways of working with AI, and I realized that some of them sound way more complicated than they actually are.&lt;/p&gt;

&lt;p&gt;So I decided to put together a glossary of the AI Engineering concepts I think every SWE should at least be familiar with. Nothing too academic or overly technical, just simple explanations, practical examples, and how these concepts connect to each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's get into it!&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Foundation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  LLM (Large Language Model)
&lt;/h3&gt;

&lt;p&gt;An LLM is a type of AI model trained on large amounts of data to understand and generate language. At its core, it works by predicting tokens based on the context it receives. That might sound simple, but this ability allows LLMs to write code, explain complex topics, summarize documents, reason through problems, and much more.&lt;/p&gt;

&lt;p&gt;Think of an LLM as the engine behind tools like ChatGPT, Claude, and other AI assistants.&lt;/p&gt;

&lt;h3&gt;
  
  
  Models
&lt;/h3&gt;

&lt;p&gt;You've probably heard names like GPT, Claude, Gemini, or DeepSeek. These are different families of AI models, developed by different organizations, with different capabilities, limitations, and costs.&lt;/p&gt;

&lt;p&gt;And choosing a model isn't always about picking the "smartest" one. Some models are better at complex reasoning, others are faster, cheaper, or more suitable for specific tasks.&lt;/p&gt;

&lt;p&gt;For example, you probably don't need the most expensive reasoning model just to summarize a log file. But investigating a complex issue across multiple services might benefit from a more capable one.&lt;/p&gt;

&lt;p&gt;If you're curious about how models compare in terms of performance, pricing and speed, &lt;a href="https://artificialanalysis.ai/models" rel="noopener noreferrer"&gt;Artificial Analysis&lt;/a&gt; is a useful resource.&lt;/p&gt;

&lt;h3&gt;
  
  
  System One Models (Jev)
&lt;/h3&gt;

&lt;p&gt;Here's something interesting: not every AI model is designed to generate text.&lt;/p&gt;

&lt;p&gt;In September 2026, TypeSafe AI announced &lt;a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev" rel="noopener noreferrer"&gt;Jev&lt;/a&gt;, a different kind of model they call a &lt;strong&gt;System One Model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While traditional LLMs generate text token by token, Jev is designed to make fast, structured decisions. Instead of asking it to write an explanation, you provide some information and define the possible answers. The model then returns a structured decision with scores that can help the application evaluate the result. &lt;/p&gt;

&lt;p&gt;For example, imagine you're building a system that processes incoming support tickets. Instead of asking an LLM to read every ticket and generate a response explaining which team should handle it, you could use Jev to classify the ticket directly into categories like &lt;code&gt;billing&lt;/code&gt;, &lt;code&gt;technical&lt;/code&gt;, or &lt;code&gt;account&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And because the possible outputs are defined in advance, your application can use the result without having to interpret free-form text. The interesting part is that Jev doesn't generate text autoregressively like traditional LLMs. It's designed to produce structured decisions in parallel, making it potentially faster and cheaper for certain constrained decision tasks. Those benefits depend on the workload and should be benchmarked rather than assumed.&lt;/p&gt;

&lt;p&gt;Of course, this doesn't mean it replaces LLMs. You wouldn't use Jev to write an entire application or explain a complex architecture. &lt;strong&gt;Think of general-purpose LLMs as flexible language engines and Jev as an example of a model designed for constrained decisions.&lt;/strong&gt; “System One Model” is TypeSafe AI’s terminology here, not a universally adopted model category.&lt;/p&gt;

&lt;p&gt;And this is another reason why choosing the right model for the right task matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tokens
&lt;/h3&gt;

&lt;p&gt;Tokens are the units of text that language models process. A token isn't necessarily a word. It can be a whole word, part of a word, punctuation, or even whitespace.&lt;/p&gt;

&lt;p&gt;For example, a sentence might be split into several tokens depending on the model's tokenizer. Why does this matter?&lt;/p&gt;

&lt;p&gt;Because tokens affect cost, performance, and how much information a model can process. When you send a prompt, include documentation, attach logs, or receive a response, you're consuming tokens. That's why dumping thousands of lines of logs into an agent isn't always the best idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;Context is the information available to a model when it's generating a response. It can include your instructions, conversation history, source code, documentation, logs, tool results, and anything else provided to help it understand the task. For example, imagine asking an agent: Why is this API request failing?&lt;/p&gt;

&lt;p&gt;Without context, the model can only make assumptions or suggest generic debugging steps. But if you provide relevant logs, architecture documentation, and request details, it has a much better chance of finding the actual problem. And this leads to something we'll explore later: Context Engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Window
&lt;/h3&gt;

&lt;p&gt;The context window is the maximum amount of information a model can process at once, measured in tokens.&lt;/p&gt;

&lt;p&gt;Think of it as the model's available working space. Your instructions, conversation history, code, documentation, and tool responses all compete for that space.&lt;/p&gt;

&lt;p&gt;And here's something important: a larger context window doesn't automatically mean better results. Even when a model can technically handle a huge amount of information, irrelevant or poorly organized context can make it harder to find what's actually important.&lt;/p&gt;

&lt;p&gt;That's one of the reasons why managing context becomes so important when working with agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Anatomy of an AI Agent
&lt;/h2&gt;

&lt;p&gt;Now that we've covered the basics, let's talk about agents.&lt;/p&gt;

&lt;p&gt;We've been using this word a lot, but what actually makes something an agent? And how is it different from simply asking ChatGPT a question?&lt;/p&gt;

&lt;p&gt;To understand that, let's break down the concepts behind an agent, how it works, and how agents can collaborate with each other.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;p&gt;An AI agent is a system that uses an AI model to work toward a goal, make decisions about what to do next, and interact with tools or its environment to accomplish a task.&lt;/p&gt;

&lt;p&gt;The important part here is that &lt;strong&gt;an agent doesn't just generate a response. It can take actions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, when you ask an LLM to investigate a bug, it might suggest where to look or what could be causing the problem. But an agent with the right tools and permissions could actually inspect the code, search through logs, run tests, identify a possible cause, and suggest or implement a fix.&lt;/p&gt;

&lt;p&gt;And it doesn't necessarily have to follow a fixed sequence of steps. Based on what it discovers, it can decide what to investigate next. Of course, that doesn't mean agents are always correct or should have unlimited permissions. Their work still needs appropriate boundaries and verification.&lt;/p&gt;

&lt;p&gt;But here's something interesting: &lt;strong&gt;agents can also delegate work to other agents.&lt;/strong&gt; And that's where subagents come in.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subagent
&lt;/h4&gt;

&lt;p&gt;A subagent is simply an agent that receives a task delegated by another agent or a coordinating system. Think about how we work in engineering teams.&lt;/p&gt;

&lt;p&gt;When you're investigating a complex issue, you might ask another engineer to check the logs while you inspect the code. You're both working toward the same goal, but focusing on different parts of the problem. Agents can work in a similar way.&lt;/p&gt;

&lt;p&gt;For example, imagine an agent investigating why an API request is failing. Instead of doing everything itself, it could delegate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log analysis to one subagent.&lt;/li&gt;
&lt;li&gt;Code inspection to another.&lt;/li&gt;
&lt;li&gt;Documentation review to a third.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each subagent works on its assigned task and returns its findings to the main agent, which can then combine the results. &lt;strong&gt;A subagent isn't necessarily a different kind of AI. It's still an agent, but operating as part of a delegated workflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It might use the same model as the main agent, a different model, or even have a completely different set of tools and instructions. And depending on the system, subagents can work sequentially or in parallel.&lt;/p&gt;

&lt;h4&gt;
  
  
  Scout
&lt;/h4&gt;

&lt;p&gt;A scout is an agent specialized in exploration, research, or gathering information.&lt;/p&gt;

&lt;p&gt;The term isn't universally standardized, so its exact meaning can vary depending on the tool or framework you're using. But the general idea is simple: &lt;strong&gt;instead of having the main agent explore everything, you delegate the discovery work to a scout.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you're working in a large codebase and need to understand how authentication works. You could ask a scout to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Find the files responsible for authentication.&lt;/li&gt;
&lt;li&gt;Identify the relevant services and dependencies.&lt;/li&gt;
&lt;li&gt;Locate related technical documentation.&lt;/li&gt;
&lt;li&gt;Report how the authentication flow is implemented.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scout explores the codebase and returns a summary of its findings. This can help the main agent focus on the actual task without having to perform every investigation itself. And here's an important distinction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subagent describes the relationship between agents. Scout describes what an agent specializes in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A scout can be used as a subagent, but it doesn't necessarily have to be one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Persona
&lt;/h3&gt;

&lt;p&gt;A persona defines the role, behavior, or perspective we want an agent to adopt.&lt;/p&gt;

&lt;p&gt;For example, you might configure an agent to behave like a senior backend engineer, a security reviewer, an SRE, or a technical lead. But a persona isn't just saying "You are a senior engineer" and expecting magic to happen. 😅&lt;/p&gt;

&lt;p&gt;A useful persona can also define responsibilities, constraints, priorities, and how the agent should communicate its findings. For example, an SRE-oriented persona might instruct an agent to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prioritize evidence from logs and metrics.&lt;/li&gt;
&lt;li&gt;Avoid making production changes without approval.&lt;/li&gt;
&lt;li&gt;Clearly distinguish confirmed findings from hypotheses.&lt;/li&gt;
&lt;li&gt;Provide a structured incident investigation report.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's something that can be confusing at first: &lt;strong&gt;A persona isn't the same thing as an agent.&lt;/strong&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; The system that performs the work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persona:&lt;/strong&gt; The role and behavior assigned to that system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could have two agents using exactly the same LLM but with different personas, tools, and responsibilities. One might act as a code reviewer, while the other acts as an incident investigator.&lt;/p&gt;

&lt;p&gt;And depending on the framework, a persona might be defined in a Markdown file, a system prompt, or another configuration format. But simply creating a persona doesn't necessarily create a new runnable agent. That depends on how the system is configured to load and execute agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools
&lt;/h3&gt;

&lt;p&gt;Tools are what allow agents to interact with the world outside the model.&lt;/p&gt;

&lt;p&gt;An LLM by itself doesn't automatically have access to your terminal, filesystem, databases, APIs, or monitoring systems.&lt;br&gt;
But when connected to tools, an agent can perform actions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading and editing files.&lt;/li&gt;
&lt;li&gt;Running terminal commands.&lt;/li&gt;
&lt;li&gt;Searching documentation.&lt;/li&gt;
&lt;li&gt;Querying logs and databases.&lt;/li&gt;
&lt;li&gt;Calling external APIs.&lt;/li&gt;
&lt;li&gt;Executing tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, imagine an agent investigating a production issue. It might use one tool to search application logs, another to inspect the relevant source code, and another to retrieve technical documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The model can select actions, while tools provide the capabilities to carry them out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course, the agent can only use the capabilities exposed to it, and those capabilities should be restricted according to the task and required permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tool Calling
&lt;/h3&gt;

&lt;p&gt;Okay, but how does an agent actually use those tools? That's where tool calling comes in.&lt;/p&gt;

&lt;p&gt;Tool calling is the mechanism that allows a model to request the execution of a tool, usually by producing a structured call containing the tool name and its arguments. The application running the agent receives that request, executes the tool, and returns the result to the model. For example, imagine asking an agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Find out why request ABC failed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The process might look like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The model decides it needs to search the logs.&lt;/li&gt;
&lt;li&gt;It generates a tool call to query the logging system.&lt;/li&gt;
&lt;li&gt;The agent's runtime executes that call and returns the results.&lt;/li&gt;
&lt;li&gt;The model analyzes the logs and decides what to investigate next.&lt;/li&gt;
&lt;li&gt;If necessary, it makes additional tool calls until it has enough information to provide an answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process can repeat multiple times until the agent reaches a conclusion, encounters a limit, or needs human input. One important detail: &lt;strong&gt;the model doesn't execute the tool itself. The surrounding software handles the execution.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And this distinction becomes important when we talk about Agent Harnesses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Agent Harness
&lt;/h3&gt;

&lt;p&gt;This is one of those terms that sounds more complicated than it needs to be.&lt;/p&gt;

&lt;p&gt;An agent harness is the software environment around the model that makes agentic behavior possible. Remember when we talked about tool calling?&lt;/p&gt;

&lt;p&gt;The model can request a tool, but something needs to actually execute it, return the result, manage the conversation, and determine when the agent should continue or stop.&lt;/p&gt;

&lt;p&gt;That's part of what the harness does. Depending on the implementation, a harness can manage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent's execution loop.&lt;/li&gt;
&lt;li&gt;Tool availability and execution.&lt;/li&gt;
&lt;li&gt;Context and conversation history.&lt;/li&gt;
&lt;li&gt;Permissions and safety boundaries.&lt;/li&gt;
&lt;li&gt;State and persistence.&lt;/li&gt;
&lt;li&gt;Error handling and retries.&lt;/li&gt;
&lt;li&gt;Delegation to other agents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of the model as the reasoning engine and the harness as the system that allows that engine to operate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The same model can behave very differently depending on the harness it's running in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's an important idea because improving an agent isn't always about switching to a more powerful model. Sometimes, improving the environment around it makes a bigger difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  Orchestration
&lt;/h3&gt;

&lt;p&gt;Now that we know agents can delegate work to subagents, how do we coordinate everything?&lt;/p&gt;

&lt;p&gt;That's where orchestration comes in. Orchestration is the process of coordinating tasks, agents, tools, and their results to accomplish a larger goal.&lt;/p&gt;

&lt;p&gt;Imagine you're investigating a production incident involving multiple services. Instead of having one agent investigate everything sequentially, you could organize the work like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A main agent analyzes the incident and creates an investigation plan.&lt;/li&gt;
&lt;li&gt;A scout explores the codebase to identify the relevant services.&lt;/li&gt;
&lt;li&gt;Another subagent searches logs for errors related to the incident.&lt;/li&gt;
&lt;li&gt;A third subagent checks recent deployments and changes.&lt;/li&gt;
&lt;li&gt;The main agent collects their findings, compares the evidence, and decides whether more investigation is needed.&lt;/li&gt;
&lt;li&gt;Finally, it produces a report explaining the likely root cause and supporting evidence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's an example of a multi-agent workflow. But orchestration doesn't necessarily require multiple agents. It can also coordinate tools and tasks within a single-agent workflow. And here's another important distinction: &lt;strong&gt;Orchestration isn't an agent or a persona. It's the coordination of the work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can have an agent responsible for orchestration, often called an &lt;em&gt;orchestrator agent&lt;/em&gt;, with a persona that defines how it should plan, delegate, and validate tasks.&lt;/p&gt;

&lt;p&gt;Orchestration can also be handled by the harness or by predefined application logic. So, to summarize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; The system doing the work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagent:&lt;/strong&gt; An agent working on a delegated task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scout:&lt;/strong&gt; An agent specialized in exploration and information gathering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persona:&lt;/strong&gt; The role and behavior assigned to an agent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration:&lt;/strong&gt; How tasks and agents are coordinated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the interesting part is that these concepts can work together. An orchestrator agent can have a technical lead persona, delegate investigations to scouts and other subagents, and use tools to validate their findings. All of this without requiring every agent to use the same model or have the same capabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Engineering the Agent's Environment
&lt;/h2&gt;

&lt;p&gt;So, we have models, agents, tools, and a harness that connects everything together.&lt;/p&gt;

&lt;p&gt;But here's the thing: having a powerful model and a bunch of tools doesn't automatically mean you'll have a useful agent.&lt;/p&gt;

&lt;p&gt;The agent still needs to understand your project, know where to find information, follow your team's conventions, and have clear instructions about what it's supposed to do.&lt;/p&gt;

&lt;p&gt;And this is where some of the most interesting AI Engineering concepts come in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt Engineering
&lt;/h3&gt;

&lt;p&gt;You've probably heard this one a thousand times already. Prompt engineering is the practice of designing instructions that help an AI model produce better results.&lt;/p&gt;

&lt;p&gt;Instead of just asking: &lt;code&gt;Review this code.&lt;/code&gt;&lt;br&gt;
You could be more specific: &lt;code&gt;Review this implementation for potential bugs, security issues, and performance problems. Follow our team's coding standards, explain your findings, and prioritize them by severity.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The second prompt gives the model a clearer objective and expectations. But there's a limitation: a good prompt alone doesn't guarantee a good result.&lt;/p&gt;

&lt;p&gt;If the model doesn't have access to the relevant code, documentation, or tools, there's only so much it can do.&lt;/p&gt;

&lt;p&gt;And that's where Context Engineering comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Engineering
&lt;/h3&gt;

&lt;p&gt;This is one of my favorite concepts because it changes how we think about working with AI. While Prompt Engineering focuses on how we ask, Context Engineering focuses on what information the model has available when it needs to do the work.&lt;/p&gt;

&lt;p&gt;Context engineering is the practice of selecting, organizing, and delivering the right information to a model at the right time.&lt;/p&gt;

&lt;p&gt;And it's not just about adding more context. &lt;/p&gt;

&lt;p&gt;Imagine asking an agent to investigate why an API request failed. You could dump thousands of lines of logs, the entire codebase, and all your documentation into the context window. But would that actually help?&lt;/p&gt;

&lt;p&gt;Maybe. Or maybe the important information would get buried under a bunch of irrelevant data.&lt;/p&gt;

&lt;p&gt;A better approach might be to provide the request ID, the relevant service architecture, and tools that allow the agent to retrieve specific logs or documentation as needed.&lt;/p&gt;

&lt;p&gt;The goal isn't to give the agent all the information. It's to give it the right information.&lt;/p&gt;

&lt;p&gt;This can involve retrieving documents, summarizing previous interactions, filtering tool results, managing conversation history, and deciding what should remain in the context window.&lt;/p&gt;

&lt;h3&gt;
  
  
  Harness Engineering
&lt;/h3&gt;

&lt;p&gt;Remember the Agent Harness we talked about earlier? Harness Engineering is the practice of designing and improving that environment so agents can work more effectively, reliably, and safely.&lt;/p&gt;

&lt;p&gt;If Context Engineering is about managing the information available to the model, Harness Engineering is about designing the system in which the agent operates.&lt;/p&gt;

&lt;p&gt;For example, imagine you're building an agent that reviews pull requests. You might configure its harness to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the PR description and changed files.&lt;/li&gt;
&lt;li&gt;Load the team's coding standards.&lt;/li&gt;
&lt;li&gt;Provide tools to inspect the repository and run tests.&lt;/li&gt;
&lt;li&gt;Restrict which commands the agent can execute.&lt;/li&gt;
&lt;li&gt;Require evidence for every issue it reports.&lt;/li&gt;
&lt;li&gt;Run automated checks to validate its findings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notice that we haven’t changed the underlying model. We’ve improved the environment around it.&lt;/p&gt;

&lt;p&gt;And that's the interesting part: sometimes the biggest improvement doesn't come from a better model, but from a better setup.&lt;/p&gt;

&lt;p&gt;Context Engineering and Harness Engineering overlap quite a bit, but they're not exactly the same thing.&lt;/p&gt;

&lt;p&gt;Context Engineering focuses on the information the model receives, while Harness Engineering covers the broader execution environment, including tools, permissions, workflows, and feedback loops.&lt;/p&gt;

&lt;h3&gt;
  
  
  RAG (Retrieval-Augmented Generation)
&lt;/h3&gt;

&lt;p&gt;Okay, another acronym, haha. RAG stands for Retrieval-Augmented Generation. It's a technique that allows an AI system to retrieve relevant information from external sources and use it when generating a response.&lt;/p&gt;

&lt;p&gt;Instead of relying only on what the model learned during training, the system can look up information from documents, databases, knowledge bases, or other sources.&lt;/p&gt;

&lt;p&gt;For example, imagine you have hundreds of internal technical specifications.&lt;/p&gt;

&lt;p&gt;You ask: Does this implementation follow the authentication specification?&lt;/p&gt;

&lt;p&gt;A RAG-based system could search those documents, retrieve the relevant sections, and provide them to the model so it can compare the implementation against the requirements.&lt;/p&gt;

&lt;p&gt;A common approach uses embeddings and vector databases to find semantically similar content, but RAG isn't limited to vector search. Keyword search, hybrid search, and other retrieval methods can also be used.&lt;/p&gt;

&lt;p&gt;RAG is one way of providing relevant context to a model without putting everything into the prompt upfront.&lt;/p&gt;

&lt;p&gt;And while RAG can help ground responses in real information, the model can still misinterpret what it retrieves. The quality of the sources and retrieval process matters.&lt;/p&gt;

&lt;h3&gt;
  
  
  MCP (Model Context Protocol)
&lt;/h3&gt;

&lt;p&gt;MCP is another term you'll hear everywhere when working with agents. And I think it's easy to misunderstand at first. MCP is a standard protocol that allows AI applications to connect to external systems that expose tools, resources, and prompts.&lt;/p&gt;

&lt;p&gt;Think of it as a common interface between AI applications and external capabilities.&lt;/p&gt;

&lt;p&gt;Without a shared protocol, each AI application might need a custom integration for every service it wants to use.&lt;/p&gt;

&lt;p&gt;With MCP, a compatible client can communicate with MCP servers through a standardized protocol.&lt;/p&gt;

&lt;p&gt;For example, you could have MCP servers that provide access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub repositories and pull requests. &lt;/li&gt;
&lt;li&gt;Jira tickets.&lt;/li&gt;
&lt;li&gt;Internal documentation.&lt;/li&gt;
&lt;li&gt;Observability platforms.&lt;/li&gt;
&lt;li&gt;Databases and other services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An agent using an MCP-compatible application could discover available tools and call them to perform tasks, subject to the application's permissions and configuration.&lt;/p&gt;

&lt;p&gt;But here's an important distinction: MCP isn't the tool itself. It's the protocol used to expose and access capabilities. And not every tool needs MCP. Agents can also use tools through native integrations, APIs, or other mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skills
&lt;/h3&gt;

&lt;p&gt;Skills are one of the concepts I find particularly useful for everyday engineering work.&lt;/p&gt;

&lt;p&gt;A skill is a reusable package of instructions, workflows, and sometimes supporting resources that helps an agent perform a specific kind of task.&lt;/p&gt;

&lt;p&gt;Think about a task you perform regularly, like investigating an incident.&lt;/p&gt;

&lt;p&gt;You probably have a process in your head: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify the affected services and request.&lt;/li&gt;
&lt;li&gt;Retrieve the relevant logs.&lt;/li&gt;
&lt;li&gt;Check for related errors or recent deployments.&lt;/li&gt;
&lt;li&gt;Compare the behavior against the expected implementation.&lt;/li&gt;
&lt;li&gt;Summarize the findings with supporting evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of explaining that process to an agent every single time, you could define it as a skill.&lt;/p&gt;

&lt;p&gt;Depending on the agent platform, skills might be stored as Markdown files with instructions, scripts, templates, or other resources that the agent can load when relevant.&lt;/p&gt;

&lt;p&gt;And here's a distinction I think is worth remembering: Tools give agents capabilities. Skills teach agents how to use those capabilities to accomplish a task.&lt;/p&gt;

&lt;p&gt;For example, a logging tool gives an agent the ability to search logs. An incident investigation skill tells it how to approach the investigation, which information to collect, what to verify, and how to report the results.&lt;/p&gt;

&lt;p&gt;Skills don't necessarily provide new capabilities on their own, although some can include scripts or other executable resources. And when you combine skills with the right context and tools, you can start building agents that understand and follow your team's engineering workflows.&lt;/p&gt;

&lt;p&gt;At this point, we have most of the building blocks. We have models that can reason about tasks, tools that let agents interact with external systems, context that provides relevant information, skills that guide how work should be done, and a harness that brings everything together.&lt;/p&gt;

&lt;p&gt;But what happens when a task is too large or complex for a single agent? That's where subagents, scouts, and orchestration come into the picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. What Counter-Strike Can Teach Us About AI Agents 🎮
&lt;/h2&gt;

&lt;p&gt;Okay, actually nothing... Let's use Counter-Strike as an analogy. And if you've never played CS, don't worry, the idea is pretty simple. 😅&lt;/p&gt;

&lt;p&gt;Imagine you're playing a match with a team of bots.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Agent Is Your Player
&lt;/h3&gt;

&lt;p&gt;Think of an AI agent as a bot playing Counter-Strike.&lt;/p&gt;

&lt;p&gt;The bot has an objective, can make decisions, interact with the environment, and use the equipment available to it. But the bot doesn't magically know everything that's happening in the match. It needs information, capabilities, and a system that allows it to act.&lt;/p&gt;

&lt;p&gt;Sound familiar? That's basically what we've been discussing about AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Model Is the Brain, and the Harness Is the Game System
&lt;/h3&gt;

&lt;p&gt;The LLM is like the decision-making engine behind your bot. It analyzes the available information and decides what to do next.&lt;/p&gt;

&lt;p&gt;The harness is the software that connects those decisions to actions, similar to how the game system allows a bot to move, shoot, use equipment, and interact with the map.&lt;/p&gt;

&lt;p&gt;And just like two bots with different decision-making capabilities might perform differently, different AI models can produce different results.&lt;/p&gt;

&lt;p&gt;But even a great model won't be very useful if the environment around it doesn't provide the capabilities it needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personas Are the Roles on Your Team
&lt;/h3&gt;

&lt;p&gt;In Counter-Strike, players have different roles. You might have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;IGL (In-Game Leader):&lt;/strong&gt; Coordinates the team and calls strategies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entry Fragger:&lt;/strong&gt; Takes the first fights and creates space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWPer:&lt;/strong&gt; Focuses on holding angles and getting picks with the AWP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support:&lt;/strong&gt; Uses utility to help teammates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lurker:&lt;/strong&gt; Operates separately to gather information, control areas, or catch rotations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These roles don't create new players. They describe how the players are expected to behave. It's the same idea with personas.&lt;/p&gt;

&lt;p&gt;You can configure an agent to behave like a technical lead, an SRE, a code reviewer, or an orchestrator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The agent is the player. The persona is the role assigned to that player.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And here's an important detail: giving a bot an AWPer persona doesn't automatically spawn another bot.&lt;/p&gt;

&lt;p&gt;You still need an actual player configured and running.&lt;/p&gt;

&lt;p&gt;Similarly, installing a persona doesn't necessarily create a new runnable AI agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools Are Your Weapons and Equipment
&lt;/h3&gt;

&lt;p&gt;An AK-47, an AWP, a smoke grenade, or a flashbang gives a player different capabilities. But having an AWP doesn't automatically make someone a good sniper, right? haha&lt;/p&gt;

&lt;p&gt;The same applies to AI agents.&lt;/p&gt;

&lt;p&gt;Giving an agent access to a terminal, a logging platform, or a database doesn't automatically mean it knows how to use those tools effectively.&lt;/p&gt;

&lt;p&gt;It still needs the right instructions, context, and decision-making capabilities. And &lt;strong&gt;tool calling&lt;/strong&gt; is like the bot deciding when and how to use its equipment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Context Is Your Game Information
&lt;/h3&gt;

&lt;p&gt;Imagine playing Mirage without knowing where your teammates are, how much time is left, or whether the enemy team is stacking A or B.&lt;/p&gt;

&lt;p&gt;Good luck with that.&lt;/p&gt;

&lt;p&gt;In Counter-Strike, information comes from your radar, teammate callouts, sound cues, the economy, and what you've observed during the round.&lt;/p&gt;

&lt;p&gt;That information helps you make better decisions. For AI agents, context plays a similar role.&lt;/p&gt;

&lt;p&gt;An agent investigating a production issue needs relevant logs, request details, architecture documentation, and other information to understand what's happening.&lt;/p&gt;

&lt;p&gt;And &lt;strong&gt;Context Engineering&lt;/strong&gt; is like making sure your team receives the right callouts at the right time. You don't need every teammate shouting everything they see simultaneously. You need useful information that helps you make the next decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skills Are Your Strategies and Playbooks
&lt;/h3&gt;

&lt;p&gt;Think about a well-practiced A-site execute on Mirage.&lt;/p&gt;

&lt;p&gt;Everyone knows the strategy: where to position, which smokes to throw, when to flash, and how to enter the bombsite. You don't need to explain the entire strategy from scratch every round. &lt;/p&gt;

&lt;p&gt;That's similar to how skills work with AI agents. A skill provides reusable instructions and workflows for accomplishing a particular task.&lt;/p&gt;

&lt;p&gt;For example, an incident investigation skill could define how to retrieve logs, correlate errors, inspect recent deployments, and report findings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools give you the equipment. Skills give you the playbook for using it.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Subagents and Scouts Are Your Teammates
&lt;/h3&gt;

&lt;p&gt;Now imagine you're the IGL.&lt;/p&gt;

&lt;p&gt;You don't need to personally check every corner of the map. You can ask one teammate to watch mid, another to check B apartments, and another to prepare utility for an A execute.&lt;/p&gt;

&lt;p&gt;In our analogy, those teammates represent subagents working on delegated tasks. And a scout is like the teammate you send to gather information before deciding what to do.&lt;/p&gt;

&lt;p&gt;For example, you might ask a scout to check whether enemies are holding mid before committing to a strategy.&lt;/p&gt;

&lt;p&gt;In AI Engineering, a scout might explore a codebase, locate relevant documentation, or investigate which services are involved in a request.&lt;/p&gt;

&lt;p&gt;Remember: &lt;strong&gt;subagent describes the delegation relationship, while scout describes the specialization.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Orchestration Is Your IGL Calling the Round
&lt;/h3&gt;

&lt;p&gt;Now let's imagine your IGL is an AI agent.&lt;/p&gt;

&lt;p&gt;The objective is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Win this round on Mirage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The IGL might coordinate the team like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask the scout to gather information about mid.&lt;/li&gt;
&lt;li&gt;Tell the support player to prepare smokes for A.&lt;/li&gt;
&lt;li&gt;Ask the entry fragger to get ready.&lt;/li&gt;
&lt;li&gt;Wait for the scout's callout.&lt;/li&gt;
&lt;li&gt;Decide whether to execute A or rotate B.&lt;/li&gt;
&lt;li&gt;Coordinate the team's actions based on what happens.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's orchestration.&lt;/p&gt;

&lt;p&gt;The IGL isn't necessarily doing every task. It's planning, delegating, collecting information, and adapting the strategy.&lt;/p&gt;

&lt;p&gt;And this is exactly what an orchestrator agent can do in an engineering workflow.&lt;/p&gt;

&lt;p&gt;For example, imagine asking an agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Investigate why our API is returning 500 errors.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It could delegate log analysis to one subagent, code inspection to another, and deployment investigation to a third. Then it collects their findings, compares the evidence, and produces a report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The orchestrator is an agent performing a coordination role. Orchestration is the activity of coordinating the work.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's the distinction.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, What's the Point?
&lt;/h3&gt;

&lt;p&gt;The interesting thing is that you don't necessarily need a completely different AI model for each role.&lt;/p&gt;

&lt;p&gt;Just like players on the same Counter-Strike team can have different responsibilities, agents using the same model can behave differently depending on their personas, tools, skills, and context.&lt;/p&gt;

&lt;p&gt;And sometimes you don't even need multiple agents. A single well-configured agent might be enough for the task.&lt;/p&gt;

&lt;p&gt;The goal isn't to build the biggest team of agents possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's to give the right responsibilities, information, and capabilities to the right agents, and make sure their work is coordinated effectively.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's where Agentic Engineering starts to make a lot more sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Tools Worth Exploring
&lt;/h2&gt;

&lt;p&gt;Okay, enough theory. What if you actually want to try some of this stuff?&lt;/p&gt;

&lt;p&gt;There are plenty of tools out there for working with AI agents, and now that we've covered the concepts, I think it's easier to understand what these tools actually do.&lt;/p&gt;

&lt;p&gt;Here are two interesting examples.&lt;/p&gt;

&lt;h3&gt;
  
  
  OMP (Oh My Pi) — An Agent Harness
&lt;/h3&gt;

&lt;p&gt;Remember when we talked about Agent Harnesses?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/can1357/oh-my-pi" rel="noopener noreferrer"&gt;Oh My Pi (OMP)&lt;/a&gt; is a practical example of one.&lt;/p&gt;

&lt;p&gt;It provides an environment where AI models can interact with tools, execute commands, manage context, and work on engineering tasks.&lt;/p&gt;

&lt;p&gt;And one of the interesting things is that you can configure specialized agents with different models, personas, tools, and permissions.&lt;/p&gt;

&lt;p&gt;For example, you could have an orchestrator agent responsible for planning and delegating tasks, while other agents focus on implementation, investigation, or code review.&lt;/p&gt;

&lt;p&gt;The important part is that &lt;strong&gt;OMP provides the environment where those agents can actually operate&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Herd — Multi-Agent Orchestration
&lt;/h3&gt;

&lt;p&gt;Now, remember when we talked about subagents, scouts, and orchestration?&lt;/p&gt;

&lt;p&gt;Herd is an example worth exploring when looking at multi-agent workflows. (Check the project’s current documentation and availability before adopting it.)&lt;/p&gt;

&lt;p&gt;The idea is to coordinate multiple specialized agents working toward a common goal, rather than relying on a single agent to handle everything.&lt;/p&gt;

&lt;p&gt;Think about our Counter-Strike analogy: instead of one player trying to do everything, you have an IGL coordinating teammates with different responsibilities.&lt;/p&gt;

&lt;p&gt;That's the kind of problem multi-agent orchestration aims to solve.&lt;/p&gt;

&lt;p&gt;And the interesting part is that &lt;strong&gt;orchestration isn't about having more agents just for the sake of it. It's about organizing the work so each agent can focus on what it does best.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Which One Should You Use?
&lt;/h3&gt;

&lt;p&gt;I wouldn't focus too much on choosing the perfect tool right away.&lt;/p&gt;

&lt;p&gt;The important thing is understanding the concepts behind them.&lt;/p&gt;

&lt;p&gt;Once you understand models, harnesses, personas, tools, skills, and orchestration, it becomes much easier to explore different setups and understand what each one brings to the table.&lt;/p&gt;

&lt;p&gt;And remember: &lt;strong&gt;you don't need a whole army of agents to practice Agentic Engineering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes, a single well-configured agent with the right context and tools is exactly what you need.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Where to Start
&lt;/h2&gt;

&lt;p&gt;If all of this sounds interesting but a little overwhelming, start small. You don't need a multi-agent system on day one.&lt;/p&gt;

&lt;p&gt;Pick a task you already do regularly—investigating a failed request, reviewing a pull request, or checking an implementation against a technical specification. Give one agent a clear objective, access to only the tools it needs, and a simple checklist of what a good result looks like.&lt;/p&gt;

&lt;p&gt;Then review what it produces. Did it find useful evidence? Did it make assumptions? Could you reproduce its conclusions? Improve the instructions, context, and permissions based on what you learn.&lt;/p&gt;

&lt;p&gt;Only introduce subagents or orchestration when there's a real reason to split the work. More agents can also mean more cost, coordination overhead, and opportunities for mistakes.&lt;/p&gt;

&lt;p&gt;For me, that's the most exciting part of Agentic Engineering. We're not just learning how to ask AI to write code. We're learning how to design better engineering workflows around it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal isn't to automate judgment away. It's to give engineers better tools to investigate, build, and verify software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm still exploring these ideas myself, so I'd love to hear how you're using agents in your day-to-day engineering work.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
    </item>
    <item>
      <title>Transactional Outbox Pattern - Improving how we deal with atomicity</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Wed, 21 Oct 2026 11:18:47 +0000</pubDate>
      <link>https://dev.to/devmatsu/transactional-outbox-pattern-improving-how-we-deal-with-atomicity-1j5a</link>
      <guid>https://dev.to/devmatsu/transactional-outbox-pattern-improving-how-we-deal-with-atomicity-1j5a</guid>
      <description>&lt;h1&gt;
  
  
  Transactional Outbox Pattern: Solving the Dual-Write Problem with Atomicity
&lt;/h1&gt;

&lt;p&gt;When building distributed systems, we often need to perform multiple operations as part of a single business action.&lt;/p&gt;

&lt;p&gt;Imagine you're developing an e-commerce application using Node.js, PostgreSQL, and Kafka.&lt;/p&gt;

&lt;p&gt;When a customer creates an order, your application needs to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the order in PostgreSQL.&lt;/li&gt;
&lt;li&gt;Publish an &lt;code&gt;OrderCreated&lt;/code&gt; event to Kafka so other services can react.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Sounds simple, right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OrderCreated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;orderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what happens if PostgreSQL successfully creates the order and Kafka becomes unavailable?&lt;/p&gt;

&lt;p&gt;We now have an order in our database, but the other services don't know about it.&lt;/p&gt;

&lt;p&gt;This is where things start getting interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Dual-Write Problem
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;dual-write problem&lt;/strong&gt; happens when an application needs to write to two independent systems as part of the same logical operation.&lt;/p&gt;

&lt;p&gt;In our example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL stores the order.&lt;/li&gt;
&lt;li&gt;Kafka distributes the event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is that these systems don't share the same transaction.&lt;/p&gt;

&lt;p&gt;Let's consider two scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 1: Database first&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create order in PostgreSQL  ✅
Publish event to Kafka     ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The order exists, but the event was never published.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario 2: Kafka first&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Publish event to Kafka     ✅
Create order in PostgreSQL ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now other services might receive an event about an order that doesn't exist.&lt;/p&gt;

&lt;p&gt;Reversing the operations doesn't solve the problem. It just changes which inconsistency we might encounter.&lt;/p&gt;

&lt;p&gt;So how do we guarantee that our business operation and the intent to publish its event succeed or fail together?&lt;/p&gt;

&lt;p&gt;Before answering that, we need to understand atomicity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is Atomicity?
&lt;/h2&gt;

&lt;p&gt;Atomicity is one of the four ACID properties of database transactions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity:&lt;/strong&gt; All operations within a transaction succeed, or none of them do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; Transactions preserve the database's integrity constraints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation:&lt;/strong&gt; Concurrent transactions follow defined rules about how their operations interact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Durability:&lt;/strong&gt; Once committed, changes survive failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's focus on atomicity.&lt;/p&gt;

&lt;p&gt;Imagine transferring $100 between two bank accounts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account A: -$100
Account B: +$100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both operations belong to the same logical transaction.&lt;/p&gt;

&lt;p&gt;We cannot accept a situation where Account A loses $100 but Account B never receives it.&lt;/p&gt;

&lt;p&gt;That's why databases support transactions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;accounts&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an operation fails before the transaction commits, the database can roll back the entire transaction.&lt;/p&gt;

&lt;p&gt;But here's the catch:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A PostgreSQL transaction cannot normally control a Kafka publication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Even if we write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;orderData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OrderCreated&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kafka is still an independent system.&lt;/p&gt;

&lt;p&gt;If Kafka accepts the event but the database transaction later fails to commit, we have an inconsistent state.&lt;/p&gt;

&lt;p&gt;We need another approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the Transactional Outbox Pattern
&lt;/h2&gt;

&lt;p&gt;The Transactional Outbox Pattern solves this problem with a simple idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instead of publishing the event directly to Kafka, persist the event in the same database transaction as the business operation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We introduce a new table called &lt;code&gt;outbox&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Our transaction becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;orders&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'CREATED'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;payload&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'evt-123'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'OrderCreated'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s1"&gt;'{"orderId": 42}'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both operations happen inside PostgreSQL.&lt;/p&gt;

&lt;p&gt;That means we have two possible outcomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order created ✅
Outbox event created ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Order created ❌
Outbox event created ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We no longer have a committed order without its corresponding outbox record.&lt;/p&gt;

&lt;p&gt;That's the fundamental benefit of the pattern.&lt;/p&gt;

&lt;p&gt;Notice that we didn't make PostgreSQL and Kafka atomic.&lt;/p&gt;

&lt;p&gt;Instead, we moved the atomicity boundary to something PostgreSQL can actually guarantee.&lt;/p&gt;

&lt;h2&gt;
  
  
  But How Does the Event Reach Kafka?
&lt;/h2&gt;

&lt;p&gt;Good question!&lt;/p&gt;

&lt;p&gt;We introduce another component, usually called an &lt;strong&gt;Outbox Relay&lt;/strong&gt; or &lt;strong&gt;Outbox Publisher&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Its responsibility is to read unpublished events from the outbox table and forward them to our messaging system.&lt;/p&gt;

&lt;p&gt;Our architecture becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      Node.js Application
              |
              v
     PostgreSQL Transaction
       /             \
      v               v
  Orders Table     Outbox Table
                        |
                        v
                   Outbox Relay
                        |
                        v
                       Kafka
                        |
                        v
                 Other Services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simplified relay could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;publishPendingEvents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findPending&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kafka&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;outbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;markAsPublished&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intentionally simplified. A production implementation needs to handle concurrent workers, failures, retries, and message ordering.&lt;/p&gt;

&lt;p&gt;The important part is that the event is persisted before we attempt to publish it.&lt;/p&gt;

&lt;p&gt;If Kafka becomes unavailable, the event remains in our database and can be retried later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polling vs. Event-Driven Relays
&lt;/h2&gt;

&lt;p&gt;A common implementation uses a background worker that periodically queries the outbox table.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what if we don't want to wait for the next polling interval?&lt;/p&gt;

&lt;p&gt;With PostgreSQL, we can use &lt;code&gt;LISTEN/NOTIFY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When an outbox event is inserted, the database can emit a notification to wake up the relay.&lt;/p&gt;

&lt;p&gt;The relay then queries the outbox and publishes pending events.&lt;/p&gt;

&lt;p&gt;However, there's an important distinction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The notification is not the event itself. It's just a signal that new work might be available.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Notifications aren't a durable queue. If the relay is disconnected, it may miss them.&lt;/p&gt;

&lt;p&gt;That's why the outbox table remains our source of truth, and the relay should also query for pending events on startup, reconnection, and periodically.&lt;/p&gt;

&lt;p&gt;Another approach is Change Data Capture (CDC), using tools such as Debezium to observe committed database changes and forward outbox events without application-level polling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Duplicate Events?
&lt;/h2&gt;

&lt;p&gt;Here's another interesting problem.&lt;/p&gt;

&lt;p&gt;Imagine the relay performs these operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Read event from outbox        ✅
2. Publish event to Kafka       ✅
3. Mark event as published      ❌
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if the relay crashes immediately after Kafka accepts the message?&lt;/p&gt;

&lt;p&gt;The event was published, but the database still considers it pending.&lt;/p&gt;

&lt;p&gt;When the relay restarts, it might publish the same event again.&lt;/p&gt;

&lt;p&gt;This is why the Transactional Outbox Pattern commonly provides &lt;strong&gt;at-least-once delivery&lt;/strong&gt;, assuming the relay continues retrying and the underlying infrastructure eventually recovers.&lt;/p&gt;

&lt;p&gt;That means an event can be delivered more than once.&lt;/p&gt;

&lt;p&gt;To handle this safely, consumers should be &lt;strong&gt;idempotent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, a consumer can track processed event IDs and avoid applying the same business operation twice.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Receive evt-123
      |
      v
Already processed?
   /       \
  Yes       No
   |         |
 Ignore    Process
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In practice, the consumer should atomically record the event ID and apply its business changes, so concurrent duplicate deliveries don't create duplicate effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  What About Multiple Relay Workers?
&lt;/h2&gt;

&lt;p&gt;As our system grows, we might want multiple relay workers processing events concurrently.&lt;/p&gt;

&lt;p&gt;But imagine two workers querying the same pending event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Worker A → evt-123
Worker B → evt-123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without coordination, both workers might publish it.&lt;/p&gt;

&lt;p&gt;PostgreSQL provides a useful mechanism called &lt;code&gt;FOR UPDATE SKIP LOCKED&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;outbox&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;published_at&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;SKIP&lt;/span&gt; &lt;span class="n"&gt;LOCKED&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When used inside a transaction, this allows workers to lock available rows while skipping rows locked by other transactions.&lt;/p&gt;

&lt;p&gt;This helps distribute work across workers.&lt;/p&gt;

&lt;p&gt;For longer publishing operations, we can instead claim rows in a short transaction and use leases or timeouts to recover work from crashed workers.&lt;/p&gt;

&lt;p&gt;There's also message ordering to consider. If &lt;code&gt;OrderCreated&lt;/code&gt; and &lt;code&gt;OrderPaid&lt;/code&gt; belong to the same order, we may need to preserve their relative order, even while processing different orders concurrently.&lt;/p&gt;

&lt;p&gt;These are important implementation decisions, but they don't change the fundamental purpose of the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should We Use Transactional Outbox?
&lt;/h2&gt;

&lt;p&gt;Transactional Outbox is especially useful when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A business database change must reliably produce an event.&lt;/li&gt;
&lt;li&gt;Losing an event could leave other services inconsistent.&lt;/li&gt;
&lt;li&gt;We need reliable asynchronous communication between services.&lt;/li&gt;
&lt;li&gt;We want to tolerate temporary messaging infrastructure failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, the pattern also introduces additional complexity: outbox storage, relays, retries, monitoring, cleanup, idempotency, and potentially ordering guarantees.&lt;/p&gt;

&lt;p&gt;Not every event requires that complexity.&lt;/p&gt;

&lt;p&gt;For example, losing an occasional non-critical analytics event may be acceptable.&lt;/p&gt;

&lt;p&gt;As with most architectural patterns, the decision should depend on the business requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The biggest lesson I've learned about the Transactional Outbox Pattern is that &lt;strong&gt;we don't need to make every component of a distributed system participate in one giant transaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead, we can use the atomicity guarantees of a local database transaction to persist both our business changes and the intent to publish an event.&lt;/p&gt;

&lt;p&gt;Then we rely on asynchronous delivery, retries, and idempotent consumers to propagate that change safely.&lt;/p&gt;

&lt;p&gt;The mental model I like is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Atomic locally.
Eventually propagated globally.
Duplicates handled safely.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Transactional Outbox doesn't eliminate every challenge in distributed systems, but it gives us a reliable foundation for handling one of the most common problems: keeping business state and event publication consistent.&lt;/p&gt;

&lt;p&gt;And sometimes, the most valuable architectural patterns aren't about introducing something complex. They're about moving the problem into a boundary where we already have strong guarantees.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>database</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>How Relational Databases Find Database: Understanding Table and Index Scans</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Thu, 12 Mar 2026 10:08:04 +0000</pubDate>
      <link>https://dev.to/devmatsu/how-relational-databases-find-database-understanding-table-and-index-scans-49d9</link>
      <guid>https://dev.to/devmatsu/how-relational-databases-find-database-understanding-table-and-index-scans-49d9</guid>
      <description>&lt;p&gt;When creating indexes it's important to understand how they work. &lt;a href="https://devmatsu.com/blog/post/2541326" rel="noopener noreferrer"&gt;In my previous post&lt;/a&gt;, I've explained the basics of indexes and the &lt;code&gt;EXPLAIN&lt;/code&gt; command. Now we can go a step further and look at the different types of reads a database can perform.&lt;/p&gt;

&lt;p&gt;Understanding these access patterns is crucial because it helps us evaluate the trade-offs of creating (or not creating) an indexes. It also gives us insight into what happens under the hood when a query is executed.&lt;/p&gt;

&lt;p&gt;At a high level, databases retrieve data in two main ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scanning the table directly (reading rows sequentially);&lt;/li&gt;
&lt;li&gt;Using an index to locate rows more efficiently;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The query planner decides which strategy to use based on statistics, table size, and how selective the query conditions are.&lt;/p&gt;

&lt;p&gt;Since different databases use slightly different terminology, I've included the names used by each database engine for reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Full table scan (FTS)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oracle DB: Full table scan&lt;br&gt;
SQL Server: Table Scan&lt;br&gt;
MySQL: Table Scan&lt;br&gt;
PostgreSQL: Sequential scan (Seq Scan)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is generally the least efficient scan, with O(n) complexity. The database reads the entire table sequentially, checking each row to see if it matches the query conditions.&lt;/p&gt;

&lt;p&gt;When is it used?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For small tables, the query optimizer may decide that a full table scan is actually more efficient than using an index;&lt;/li&gt;
&lt;li&gt;For queries that need most of the rows in the table;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sequential scans are not always bad. Modern databases can read tables very efficiently using sequential disk access, which can sometimes outperform index lookups when a large percentage of rows must be returned.&lt;/p&gt;

&lt;p&gt;Full table scans can lead to high I/O, increased CPU usage, and slower response times, especially on large datasets. Monitoring queries and minimizing unnecessary full table scans is a key part of database performance tuning.&lt;/p&gt;

&lt;p&gt;-&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Index Scan&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oracle DB: Index Range Scan&lt;br&gt;
SQL Server: Index Seek&lt;br&gt;
MySQL: Index Lookup / Range Scan&lt;br&gt;
PostgreSQL: Index Scan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An Index Scan uses an index to locate relevant rows and then fetches the full row from the table (often called the heap in PostgreSQL).&lt;/p&gt;

&lt;p&gt;This means the database performs two steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find matching entries in the index&lt;/li&gt;
&lt;li&gt;Follow pointers to retrieve the actual rows in the table&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When is it used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries filtering on columns with an index;&lt;/li&gt;
&lt;li&gt;When only a small subset of rows matches the criteria;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because the database must jump between the index and the table, index scans can involve random I/O. For queries that return many rows, this can become slower than a sequential scan.&lt;/p&gt;

&lt;p&gt;-&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Covering Index Scan&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oracle DB: Index Fast Full Scan&lt;br&gt;
SQL Server: Index Seek (covering)&lt;br&gt;
MySQL: Covering Index&lt;br&gt;
PostgreSQL: Index Only Scan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A covering index scan can satisfy the query using only the index, without reading the main table. This avoids additional I/O and can be extremely fast.&lt;/p&gt;

&lt;p&gt;In PostgreSQL, this appears as an Index Only Scan, although the database may still access the table if it needs to check row visibility.&lt;/p&gt;

&lt;p&gt;When is it used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries that only request columns included in the index;&lt;/li&gt;
&lt;li&gt;Read-heavy queries where performance is critical;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Indexes require additional storage. They are most effective when queries are frequent and selective, and less useful if the query needs columns that are not part of the index.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Bitmap Index Scan&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Oracle DB: Bitmap Index Scan&lt;br&gt;
SQL Server: Bitmap Filter&lt;br&gt;
MySQL: Not implemented the same way&lt;br&gt;
PostgreSQL: Bitmap Index Scan &amp;amp; Bitmap Heap Scan&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The database first scans one or more indexes and builds a bitmap representing the locations of matching rows. It then reads the table pages in a more optimized order.&lt;/p&gt;

&lt;p&gt;When is it used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries with multiple indexed conditions (e.g., WHERE status='active' AND type='premium');&lt;/li&gt;
&lt;li&gt;Medium to large tables where reading rows individually would be slow;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More memory usage to build the bitmap. Very efficient for combining multiple indexes, but not ideal for very small or highly selective queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the right scan
&lt;/h2&gt;

&lt;p&gt;The query planner decides which scan to use based on several factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Table size&lt;/li&gt;
&lt;li&gt;Index availability&lt;/li&gt;
&lt;li&gt;Selectivity of the query&lt;/li&gt;
&lt;li&gt;Table statistics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of this, adding an index does not guarantee it will be used. If the planner estimates that most rows will be returned, it may choose a sequential scan instead.&lt;/p&gt;

&lt;p&gt;Understanding these access methods helps interpret &lt;code&gt;EXPLAIN&lt;/code&gt; output and design indexes that actually improve performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>relationaldb</category>
      <category>index</category>
      <category>scan</category>
      <category>performance</category>
    </item>
    <item>
      <title>"The API Is Slow, Fix It!" – What I Learned About `EXPLAIN` and Indexing</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Thu, 29 May 2025 13:52:40 +0000</pubDate>
      <link>https://dev.to/devmatsu/the-api-is-slow-fix-it-what-i-learned-about-explain-and-indexing-99k</link>
      <guid>https://dev.to/devmatsu/the-api-is-slow-fix-it-what-i-learned-about-explain-and-indexing-99k</guid>
      <description>&lt;p&gt;During a technical interview, the situation was something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Your manager tells you: the API is too slow. Fix it!”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I started walking through what I’d do — checking logs, measuring response time, analyzing the stack. Eventually, we narrowed it down to the database, suspecting a slow query.&lt;/p&gt;

&lt;p&gt;I mentioned I’d try to optimize it based on “feeling” and maybe throw in some indexes. Then the interviewer dropped a simple but powerful tip:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Have you tried running it with EXPLAIN?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s when I learned something new and honestly, it changed the way I look at query performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does &lt;code&gt;EXPLAIN&lt;/code&gt; Actually Show?
&lt;/h2&gt;

&lt;p&gt;When you write a query, the database doesn’t just run it blindly, it builds an &lt;strong&gt;execution plan&lt;/strong&gt;. And &lt;code&gt;EXPLAIN&lt;/code&gt; reveals exactly how it plans to execute that query.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of it like saying: “Show me how you're going to fetch these results before you actually do it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With it, you can discover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it’s doing a full table scan;&lt;/li&gt;
&lt;li&gt;If your indexes are being used or totally ignored;&lt;/li&gt;
&lt;li&gt;What kind of join is being applied (Nested Loop, Hash Join, etc.);&lt;/li&gt;
&lt;li&gt;How many rows it &lt;strong&gt;thinks&lt;/strong&gt; it will read;&lt;/li&gt;
&lt;li&gt;And how “expensive” the query is, cost-wise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s simple to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;EXPLAIN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'hi@devmatsu.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why Not Add Indexes Everywhere?
&lt;/h2&gt;

&lt;p&gt;Another key part of the interview was when we discussed indexing. I first said, "maybe because of storage cost?" — but the better answer was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Indexes speed up reads, but make writes more expensive."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every time you run an &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, or &lt;code&gt;DELETE&lt;/code&gt;, the database also has to update every related index. So the trade-off is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too many indexes → fast reads, but slow writes.&lt;/li&gt;
&lt;li&gt;Too few indexes → fast writes, but slow reads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why indexing is a design choice, not a default solution. And again, &lt;code&gt;EXPLAIN&lt;/code&gt; helps you check if your index is actually being used or if it’s just sitting there eating up space.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Took from That Interview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;EXPLAIN&lt;/code&gt; isn’t optional, it’s your ally for understanding performance;&lt;/li&gt;
&lt;li&gt;Indexing is powerful, but it comes at a cost. Use it with intention;&lt;/li&gt;
&lt;li&gt;And most of all: interviews aren’t just tests. Sometimes, they’re great learning moments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>sql</category>
      <category>index</category>
      <category>performance</category>
    </item>
    <item>
      <title>Setting a Default Node Version for Your Project with .nvmrc</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Thu, 24 Apr 2025 20:12:08 +0000</pubDate>
      <link>https://dev.to/devmatsu/setting-a-default-node-version-for-your-project-with-nvmrc-4j81</link>
      <guid>https://dev.to/devmatsu/setting-a-default-node-version-for-your-project-with-nvmrc-4j81</guid>
      <description>&lt;p&gt;I used to switch between projects and wonder why some things just... broke.&lt;/p&gt;

&lt;p&gt;Then I realized the issue: each project was using a different Node.js version.&lt;br&gt;&lt;br&gt;
Sometimes one needed Node 18 for a modern API, while another was still running on 16.&lt;/p&gt;

&lt;p&gt;That’s when I found out about &lt;code&gt;.nvmrc&lt;/code&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  What is &lt;code&gt;.nvmrc&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;It’s a simple file that you add to the root of your project to define the &lt;strong&gt;Node.js version&lt;/strong&gt; that should be used.&lt;/p&gt;

&lt;p&gt;No JSON. No config object. Just the version number.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;18.16.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;When using &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM (Node Version Manager)&lt;/a&gt;, you can run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm use
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And NVM will automatically switch your Node.js version to the one specified in &lt;code&gt;.nvmrc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is super helpful when you clone a repo and want to make sure you're using the right environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keeps your local version consistent with the project&lt;/li&gt;
&lt;li&gt;Prevents bugs caused by incompatible Node versions&lt;/li&gt;
&lt;li&gt;Makes onboarding easier for teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're working with multiple Node projects, &lt;strong&gt;this tiny file can save you hours&lt;/strong&gt; of debugging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>node</category>
    </item>
    <item>
      <title>How JavaScript Gets Updated: ECMAScript, V8 and Your Runtime Explained</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Sun, 13 Apr 2025 19:37:10 +0000</pubDate>
      <link>https://dev.to/devmatsu/how-javascript-gets-updated-ecmascript-v8-and-your-runtime-explained-2hmd</link>
      <guid>https://dev.to/devmatsu/how-javascript-gets-updated-ecmascript-v8-and-your-runtime-explained-2hmd</guid>
      <description>&lt;p&gt;I remember when I started coding in JavaScript, I used to think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Okay... so JavaScript gets updated like any language... just update and that's it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that's not exactly how things work here. JavaScript runs in different environments like browser, Node.js, Deno — and what actually decides if you can use that new fancy feature you saw on X (the old Twitter) is your runtime.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explain how new JavaScript features are released, how ECMAScript fits into this process and why your runtime decides what features you can use (or not).&lt;/p&gt;




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

&lt;p&gt;ECMAScript is the official specification of the language and JavaScript is just an implementation of that spec.&lt;/p&gt;

&lt;p&gt;Every year, a group called &lt;strong&gt;TC39&lt;/strong&gt; (the committee that defines the language) releases a new ECMAScript version — adding new features, syntax, and behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of features introduced by ECMAScript versions:
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Features example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ES6&lt;/td&gt;
&lt;td&gt;2015&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt;, arrow functions, classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ES2020&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;Optional chaining &lt;code&gt;?.&lt;/code&gt;, Nullish coalescing &lt;code&gt;??&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ES2022&lt;/td&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;#privateFields&lt;/code&gt; in classes, top-level &lt;code&gt;await&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  But How Do We Get Those Features?
&lt;/h2&gt;

&lt;p&gt;That's the point. It's not about updating JavaScript. It depends on the JavaScript Engine you’re running.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a JavaScript Engine?
&lt;/h2&gt;

&lt;p&gt;A JavaScript Engine is what reads, parses, and executes your JavaScript code. Each environment (browser, Node.js) uses an engine.&lt;/p&gt;

&lt;p&gt;Popular engines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;V8&lt;/strong&gt; → used by Chrome and Node.js
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SpiderMonkey&lt;/strong&gt; → used by Firefox
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScriptCore (Nitro)&lt;/strong&gt; → used by Safari
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When Do You Get New JavaScript Features?
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Environment&lt;/th&gt;
&lt;th&gt;How do you get new features?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;By updating the browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;By updating your Node.js version&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It's simple as that. If you want to use new features just need to update the browser or the Node.js version&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Is This Important?
&lt;/h2&gt;

&lt;p&gt;Because when you’re writing code locally — in your machine — you can probably use everything that your Node.js or browser supports. But when you're writing code for production (especially frontend), you need to care about your users' environment.&lt;/p&gt;




&lt;h3&gt;
  
  
  Example:
&lt;/h3&gt;

&lt;p&gt;If your users still use old browsers like IE11 (hope not) or very old Android versions — you can’t use optional chaining &lt;code&gt;?.&lt;/code&gt; directly.&lt;/p&gt;

&lt;p&gt;The browser wouldn’t even understand that syntax.&lt;/p&gt;

&lt;p&gt;That’s why tools like: Babel, TypeScript, Webpack, Vite and others exist — to transpile your code and convert modern JavaScript to old compatible syntax.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;JavaScript is updated every year through ECMAScript but you only get those new features when your environment supports them — either by updating the engine (browser, Node.js) or transpiling your code for compatibility.&lt;/p&gt;

&lt;p&gt;Now every time you see a new JavaScript feature, remember:&lt;br&gt;&lt;br&gt;
It’s not about "updating JavaScript" — it’s about your engine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>concept</category>
      <category>fundamentals</category>
    </item>
    <item>
      <title>Closures vs Classes in JavaScript: What I Learned Solving LeetCode #2622</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Tue, 08 Apr 2025 13:56:07 +0000</pubDate>
      <link>https://dev.to/devmatsu/closures-vs-classes-in-javascript-what-i-learned-solving-leetcode-2622-2mkb</link>
      <guid>https://dev.to/devmatsu/closures-vs-classes-in-javascript-what-i-learned-solving-leetcode-2622-2mkb</guid>
      <description>&lt;p&gt;I was solving &lt;a href="https://leetcode.com/problems/cache-with-time-limit/" rel="noopener noreferrer"&gt;LeetCode #2622 – Cache With Time Limit&lt;/a&gt; and the goal was to create a function that returns a caching system with TTL (time-to-live).&lt;/p&gt;

&lt;p&gt;My first instinct? Use a &lt;strong&gt;closure&lt;/strong&gt;. It's a common pattern — just define a variable outside the function and the inner function can reference it.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔁 Closure-style cache:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createCache&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;expiry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ttl&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiry&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Easy. It works, it's scoped and no one can touch &lt;code&gt;store&lt;/code&gt; from the outside — classic closure encapsulation. But the LeetCode problem expected us to extend a function via its prototype — and that threw me off. I was like: "How the heck do I create a private variable across prototype methods?"&lt;br&gt;
That’s when the light bulb went on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Using &lt;code&gt;this&lt;/code&gt; + Classes = Encapsulation
&lt;/h2&gt;

&lt;p&gt;I realized I needed to treat it like a class and that’s when I remembered: when using prototypes (or classes), you can store shared data inside this.&lt;br&gt;
So I did:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;TimeLimitedCache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;TimeLimitedCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;existed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;TimeLimitedCache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now everything lives inside &lt;code&gt;this.cache&lt;/code&gt;. No need for an external closure and it works great across all methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Private Fields in Classes
&lt;/h3&gt;

&lt;p&gt;At that point I thought: "Wait, so this whole thing is basically behaving like a class!". And if it’s a class, can we go one step further? What about private fields?&lt;br&gt;
In the past, we'd use a naming convention like &lt;code&gt;_cache&lt;/code&gt;, but that was just a signal, not actual protection.&lt;br&gt;
But now with modern JavaScript (since ES2022), we can use native private fields with the &lt;code&gt;#&lt;/code&gt; symbol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimeLimitedCache&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;existed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;expiredAt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s real encapsulation!&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Closures are a great way to encapsulate state, especially for factory functions;&lt;/li&gt;
&lt;li&gt;Classes with &lt;code&gt;this&lt;/code&gt; are a powerful alternative when you want to work with prototypes or build something that feels more like an object;&lt;/li&gt;
&lt;li&gt;Modern JavaScript gives us native private fields (&lt;code&gt;#&lt;/code&gt;);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No matter what pattern you choose, closures or classes, the key is to understand the trade-offs and when each tool fits better.&lt;/p&gt;

&lt;p&gt;Solving this problem gave me a new perspective on how classes and closures can often solve the same thing in different ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>What happens when both try and finally return in JavaScript?</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Mon, 07 Apr 2025 03:05:26 +0000</pubDate>
      <link>https://dev.to/devmatsu/what-happens-when-both-try-and-finally-return-in-javascript-49i6</link>
      <guid>https://dev.to/devmatsu/what-happens-when-both-try-and-finally-return-in-javascript-49i6</guid>
      <description>&lt;p&gt;What do you think will happen if we run this code?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;oops&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;catch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;finally&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first you might think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Okay, it throws an error, so it goes into the catch block and returns 'catch'... right?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But not quite! Actually this code will return &lt;code&gt;finally&lt;/code&gt;! But why? Let me explain. &lt;/p&gt;

&lt;h2&gt;
  
  
  How &lt;code&gt;try&lt;/code&gt;, &lt;code&gt;catch&lt;/code&gt; and &lt;code&gt;return&lt;/code&gt; Work
&lt;/h2&gt;

&lt;p&gt;We usually think of &lt;code&gt;return&lt;/code&gt; as an immediate exit, but in JavaScript, that’s not exactly how it works under the hood. When the JS engine hits a &lt;code&gt;return&lt;/code&gt;, it creates something called a Completion Record.&lt;/p&gt;

&lt;p&gt;Think of it as a sticky note that says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hey, we're done here. The reason is return and here's the value to give back"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This record is kept internally by the JavaScript engine until the function truly finishes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The flow with &lt;code&gt;finally&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Here's a real-world metaphor:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You go to the market (that's your function)&lt;/p&gt;

&lt;p&gt;You try to buy apples (try), but if they’re out of stock, you get bananas instead (catch).&lt;/p&gt;

&lt;p&gt;As you're about to check out, your mom calls and says:&lt;br&gt;
“Forget that — just buy milk!” (finally).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So no matter what you were planning to bring home (apples or bananas), you end up bringing milk.&lt;/p&gt;

&lt;p&gt;Here's the code version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;goToMarket&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No apples today!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Apples&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bananas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Milk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;goToMarket&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// 'Milk'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Does This Happen?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;try&lt;/code&gt; block tries to return &lt;code&gt;'Apples'&lt;/code&gt;, but an error is thrown.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;catch&lt;/code&gt; block handles it and returns &lt;code&gt;'Bananas'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Before the function can return &lt;code&gt;'Bananas'&lt;/code&gt;, the &lt;code&gt;finally&lt;/code&gt; block runs and its &lt;code&gt;return 'Milk'&lt;/code&gt; overrides everything.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So &lt;code&gt;'Milk'&lt;/code&gt; is the final return value.&lt;/p&gt;

&lt;h2&gt;
  
  
  ECMAScript Spec (in simple terms)
&lt;/h2&gt;

&lt;p&gt;According to the ECMAScript spec:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;return&lt;/code&gt; in &lt;code&gt;try&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt; doesn't immediately return — it creates a Completion Record;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;finally&lt;/code&gt; block is always executed, regardless of what happened in &lt;code&gt;try&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;finally&lt;/code&gt; block has its own &lt;code&gt;return&lt;/code&gt;, it overwrites any previous return;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why &lt;code&gt;finally&lt;/code&gt; becomes the actual return value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;This behavior follows the ECMAScript specification, which details how CompletionRecords are handled during function execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;finally&lt;/code&gt; block isn't just a "cleanup" section — it can take control of your function's return value if you’re not careful. Even if &lt;code&gt;try&lt;/code&gt; or &lt;code&gt;catch&lt;/code&gt; has a &lt;code&gt;return&lt;/code&gt;, a &lt;code&gt;return&lt;/code&gt; inside &lt;code&gt;finally&lt;/code&gt; will override it.&lt;/p&gt;

&lt;p&gt;So next time you're writing error handling, think twice before returning inside a &lt;code&gt;finally&lt;/code&gt; block, it might silently change your function’s behavior.&lt;/p&gt;

&lt;p&gt;Understanding this little quirk helps you avoid unexpected bugs and gives you more control over your code flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>fundamentals</category>
    </item>
    <item>
      <title>What is Immutability in JavaScript?</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Sun, 06 Apr 2025 03:43:58 +0000</pubDate>
      <link>https://dev.to/devmatsu/what-is-immutability-in-javascript-fnm</link>
      <guid>https://dev.to/devmatsu/what-is-immutability-in-javascript-fnm</guid>
      <description>&lt;p&gt;Immutability is a powerful concept in programming and especially important in JavaScript, even if we don't always think about it. It affects how we manage data, state and side effects in our applications.&lt;/p&gt;

&lt;p&gt;In this post, we'll break down what immutability means, why it matters and how you can work with it in practice.&lt;/p&gt;

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

&lt;p&gt;Basically &lt;strong&gt;Immutability&lt;/strong&gt; means something cannot be changed after it's created. For example in JavaScript, &lt;strong&gt;primitive values&lt;/strong&gt; like numbers, strings and booleans are immutable. This doesn't mean the variable can't be reassigned, it means the value itself can't be changed in place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example with a string:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matsu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Trying to change just one character (this won't work)&lt;/span&gt;
&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'Matsu' → Still the same&lt;/span&gt;

&lt;span class="c1"&gt;// But we can reassign the variable&lt;/span&gt;
&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'John'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the string itself is immutable but the variable name can be reassigned to a new string. In contrast, objects and arrays are mutable by default, which means you can change their contents directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example with an object:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matsu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Modifying the object&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'John' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can lead to unintended side effects, especially when multiple parts of your code are referencing and modifying the same object or array, such as shared data or state.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Can Immutability Do?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avoid side effects (accidentally changing shared data);&lt;/li&gt;
&lt;li&gt;Make debugging easier (state doesn't change in hidden ways);&lt;/li&gt;
&lt;li&gt;Improve performance in some cases (e.g. with reference checks);&lt;/li&gt;
&lt;li&gt;Work better with frameworks like React, which rely on state changes via new objects;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Working with Immutability in JavaScript
&lt;/h2&gt;

&lt;p&gt;To keep data immutable, we usually create new copies instead of modifying the original.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copying Arrays
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Instead of: numbers.push(4)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// [1, 2, 3]&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newNumbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// [1, 2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Copying Objects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matsu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Instead of: user.age = 29&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatedUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;29&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// { name: 'Matsu', age: 28 }&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { name: 'Matsu', age: 29 }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Attention with Deep Copy vs Shallow Copy
&lt;/h3&gt;

&lt;p&gt;Most techniques (like spread (&lt;code&gt;...&lt;/code&gt;) and &lt;code&gt;Object.assign&lt;/code&gt;) create shallow copies. This means only top-level properties are copied. If the object contains nested objects, those nested references remain shared between the original and the copy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Matsu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Tokyo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Osaka&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 😱 'Osaka'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though we used the spread operator, &lt;code&gt;person.address&lt;/code&gt; and &lt;code&gt;clone.address&lt;/code&gt; still point to the same object in memory, so changing one affects the other.&lt;/p&gt;

&lt;p&gt;To truly copy all levels of an object, you need a deep clone. One common approach is using &lt;code&gt;cloneDeep&lt;/code&gt; from Lodash:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deepClone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cloneDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new object where even the nested structures are fully cloned, breaking the reference between the original and the copy.&lt;/p&gt;

&lt;p&gt;You can check my post about &lt;a href="https://dev.to/devmatsu/exploring-object-cloning-techniques-in-javascript-380c"&gt;Exploring Object Cloning Techniques in JavaScript&lt;/a&gt; to dive deeper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enforcing Immutability in JavaScript
&lt;/h2&gt;

&lt;p&gt;You might think using &lt;code&gt;const&lt;/code&gt; would make an object or array immutable, but that's not the case. &lt;code&gt;const&lt;/code&gt; only prevents reassignment, not mutation.&lt;br&gt;
By default, JavaScript objects and arrays are mutable. But there are ways to partially enforce immutability at runtime using built-in methods like:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Object.freeze()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevents adding, removing or modifying properties of an object making the object shallowly immutable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;apiUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;retries&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 3 — change is ignored or throws in strict mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ Note: This only works on the first level. If the object has nested properties, they’re still mutable unless you recursively freeze them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Freezing an Array
&lt;/h3&gt;

&lt;p&gt;You can also use &lt;code&gt;Object.freeze()&lt;/code&gt; to prevent changes to an array, for example, if you want to enforce a fixed set of values (e.g. length, content):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;roles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;viewer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// ❌ won't work&lt;/span&gt;
&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;superadmin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// ❌ won't work&lt;/span&gt;
&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// ❌ won't work&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [ 'admin', 'editor', 'viewer' ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful when you want to protect reference lists, roles, or static options in your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;Object.seal()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevents adding or removing properties, but you can still modify existing ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// ✅ allowed&lt;/span&gt;
&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;language&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// ❌ can't add new property&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// ❌ can't delete property&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// { theme: 'light' }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These methods are great for protecting config objects, shared constants or preventing accidental mutations especially in larger codebases.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Immutability?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;When managing application state (especially in React or Redux);&lt;/li&gt;
&lt;li&gt;When writing pure functions;&lt;/li&gt;
&lt;li&gt;When you want predictable and reliable behavior in your code;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Immutability is not about never changing anything, it's about changing things safely by creating new versions instead of modifying existing ones. You can also "lock" objects and arrays using &lt;code&gt;Object.freeze()&lt;/code&gt; or &lt;code&gt;Object.seal()&lt;/code&gt; to help prevent accidental changes.&lt;/p&gt;

&lt;p&gt;It leads to better, cleaner and more bug-resistant code, especially as your project grows. So embrace immutability and you'll avoid a lot of hidden side effects and unexpected behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>immutability</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Programming Paradigms Explained with Code Examples</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Fri, 04 Apr 2025 14:12:18 +0000</pubDate>
      <link>https://dev.to/devmatsu/programming-paradigms-explained-with-code-examples-1ib0</link>
      <guid>https://dev.to/devmatsu/programming-paradigms-explained-with-code-examples-1ib0</guid>
      <description>&lt;p&gt;When you're learning to code or expanding your knowledge, you'll often hear the term &lt;strong&gt;"programming paradigms"&lt;/strong&gt; but what does that actually mean?&lt;/p&gt;

&lt;p&gt;A programming paradigm is a way to approach problem-solving using code. It's about how you structure your logic and instructions. Different paradigms shape the way you think and organize your solutions.&lt;/p&gt;

&lt;p&gt;Let's explore some of the main ones with simple examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Imperative Programming
&lt;/h2&gt;

&lt;p&gt;This is one of the most common and intuitive paradigms. You tell the computer how to do something, step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (in JavaScript):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Declarative Programming
&lt;/h2&gt;

&lt;p&gt;You focus on what you want instead of how to do it. SQL and even parts of React are declarative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (SQL):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example (React - .jsx file):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Greeting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hello&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;world&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may not look declarative at first, but the point is: React uses JavaScript under the hood, the way you define UI with JSX is declarative because you're describing what should be rendered based on the current state or props, not how to manually build or update the DOM.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Object-Oriented Programming (OOP)
&lt;/h2&gt;

&lt;p&gt;This paradigm organizes code that encapsulate both data and behavior. It's great for modeling real-world entities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (TypeScript):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; makes a sound.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; barks.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Dog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;speak&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Rex barks.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Functional Programming
&lt;/h2&gt;

&lt;p&gt;In functional programming, you use pure functions and avoid mutating data. It's about composition, immutability and statelessness.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example (JavaScript):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;double&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [2, 4, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Modern languages like JavaScript, Python and TypeScript are multi-paradigm so you can combine functional, object-oriented and imperative styles depending on what fits best.&lt;/p&gt;

&lt;p&gt;Here are some languages commonly associated with each paradigm:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Paradigm&lt;/th&gt;
&lt;th&gt;Languages&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Imperative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JavaScript, TypeScript, Go, Python, Java, Rust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Declarative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SQL, JavaScript (JSX), Elixir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Object-Oriented&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;TypeScript, Python, C#, Java, Kotlin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Functional&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JavaScript, TypeScript, Python, Kotlin, Elixir&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you're aiming to grow as a developer, understanding paradigms is a powerful step. Knowing the fundamentals helps you understand what you're doing and why you're doing it that way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>fundamentals</category>
    </item>
    <item>
      <title>Memoization and Caching: Are they the same in JavaScript?</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Tue, 01 Apr 2025 01:55:47 +0000</pubDate>
      <link>https://dev.to/devmatsu/memoization-and-caching-are-they-the-same-in-javascript-3ann</link>
      <guid>https://dev.to/devmatsu/memoization-and-caching-are-they-the-same-in-javascript-3ann</guid>
      <description>&lt;p&gt;At first glance, &lt;strong&gt;Memoization&lt;/strong&gt; and &lt;strong&gt;Caching&lt;/strong&gt; might seen like the same thing. After all, both techniques involve saving results to avoid doing the same work again. But while they are related, they're not exactly the same and understanding the difference between them will make you have a strong fundamentals.&lt;/p&gt;

&lt;p&gt;In this post, we'll break down what memoization and caching really are, compare them side by side and walk through practical examples so you'll never confuse them again.&lt;/p&gt;




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

&lt;p&gt;&lt;strong&gt;Memoization&lt;/strong&gt; is a specific form of caching that's focused on &lt;strong&gt;functions&lt;/strong&gt;. It stores the result of a function &lt;strong&gt;based on its inputs arguments&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the function is called again with the same arguments, the stores result is returned instead of running the function again.&lt;br&gt;
It's typically used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure Functions (functions that always return the same output for the same input);&lt;/li&gt;
&lt;li&gt;Expensive calculations that are repeated often;&lt;/li&gt;
&lt;li&gt;Variables in outer functions that are preserved through closures (e.g., for storing cached values);&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It usually stores values &lt;strong&gt;in memory&lt;/strong&gt;, like in a plain object or closure.&lt;/p&gt;


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

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt; is a broader concept. It referes to storing any kind of data so it can be accessed faster in the future, not just functions results.&lt;/p&gt;

&lt;p&gt;It's used everywhere&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API responses;&lt;/li&gt;
&lt;li&gt;Database query results;&lt;/li&gt;
&lt;li&gt;Images, files, computed reports;&lt;/li&gt;
&lt;li&gt;Session data, user info, etc;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it can be stored anywhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In memory;&lt;/li&gt;
&lt;li&gt;In a Redis store;&lt;/li&gt;
&lt;li&gt;In the browser (localStorage, indexedDB);&lt;/li&gt;
&lt;li&gt;On disk&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Key differences
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Memoization&lt;/th&gt;
&lt;th&gt;Caching&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function-level&lt;/td&gt;
&lt;td&gt;Global / application-level&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Store function results&lt;/td&gt;
&lt;td&gt;Store any reusable data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Based On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function arguments&lt;/td&gt;
&lt;td&gt;Keys like URL, ID, custom cache key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typical Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;In-memory (object or closure)&lt;/td&gt;
&lt;td&gt;Memory, Redis, disk, browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Recursive calculations, pure logic&lt;/td&gt;
&lt;td&gt;API calls, DB queries, static files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Invalidation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rare (input-based)&lt;/td&gt;
&lt;td&gt;TTL, manual purge, cache strategy needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;factorial(n)&lt;/code&gt;, &lt;code&gt;fibonacci(n)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Cached API response by user ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Memoization in code
&lt;/h2&gt;

&lt;p&gt;Let's look at a simple example using the factorial function, which is a great case for memoization because each result depends on the previous one.&lt;/p&gt;

&lt;p&gt;Without Memoization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function factorial(n) {
  if (n &amp;lt;= 1) return 1;
  return n * factorial(n - 1);
}

console.log(factorial(5)); // 120
console.log(factorial(5)); // Recalculates everything again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Memoization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function memoizedFactorial() {
  const cache = {};

  return function factorial(n) {
    if (n in cache) {
      console.log('From cache:', n);
      return cache[n];
    }

    if (n &amp;lt;= 1) return 1;

    const result = n * factorial(n - 1);
    cache[n] = result;
    return result;
  };
}

const factorial = memoizedFactorial();

console.log(factorial(5)); // Calculated
console.log(factorial(5)); // Cached!
console.log(factorial(6)); // Uses cached factorial(5)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows how we avoid redundant work by reusing previous results.&lt;/p&gt;




&lt;h2&gt;
  
  
  Caching in code (Example with Redis)
&lt;/h2&gt;

&lt;p&gt;Now let's say we have a function that fetches user data, possibly expensive if it hits a DB or API.&lt;br&gt;
Instead of recalculating or re-fetching it every time we cache it using Redis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function getUser(userId) {
  const key = `user:${userId}`;
  const cached = await redis.get(key);

  if (cached) {
    console.log('Returned from Redis cache');
    return JSON.parse(cached);
  }

  const user = await fetchUserFromDB(userId);
  await redis.set(key, JSON.stringify(user), 'EX', 60); // Cache for 60s
  return user;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is &lt;strong&gt;not memoization&lt;/strong&gt;, but it is caching. It's not tied directly to a function's input/output relationship in memory. It's stored in an external cache layer and used across multiple calls.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use Each
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Use memoization when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're working with pure functions;&lt;/li&gt;
&lt;li&gt;You want to optimize repeated calculations;&lt;/li&gt;
&lt;li&gt;You don't want to introduce external storage (just use in-memory);&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use caching when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You want to store data fetched or computed from external sources;&lt;/li&gt;
&lt;li&gt;You need to share results between processes or requests;&lt;/li&gt;
&lt;li&gt;You need expiration, invalidation or disk/network-level persistence;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Memoization and caching are related but they solve different problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Memoization is about functions calls: if I call this again with the same input, don't recompute it.&lt;/p&gt;

&lt;p&gt;Caching is about data reuse: if I already fetched this, let's avoid doing it again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Quick recap:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Memoization is a type of caching;&lt;/li&gt;
&lt;li&gt;All memoization is caching, but not all caching is memoization;&lt;/li&gt;
&lt;li&gt;Both can drastically improve performance if used in the right context;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>fundamentals</category>
    </item>
    <item>
      <title>What is an IIFE in JavaScript and Why Would You Use It?</title>
      <dc:creator>Matsu</dc:creator>
      <pubDate>Fri, 28 Mar 2025 21:32:28 +0000</pubDate>
      <link>https://dev.to/devmatsu/what-is-an-iife-in-javascript-and-why-would-you-use-it-17al</link>
      <guid>https://dev.to/devmatsu/what-is-an-iife-in-javascript-and-why-would-you-use-it-17al</guid>
      <description>&lt;p&gt;In JavaScript, you might have seen a function that seems to call itself right after it's defined. That’s called an IIFE, short for Immediately Invoked Function Expression. It might look weird at first, but it has some interesting use cases. Let’s explore what it is, how it works, and when to use it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an IIFE?
&lt;/h2&gt;

&lt;p&gt;An IIFE is a function that runs immediately after it’s defined. The main idea is to create a new scope without polluting the global one.&lt;/p&gt;

&lt;p&gt;Here’s how it looks:&lt;br&gt;
&lt;code&gt;(function () { console.log('This runs immediately!'); })();&lt;/code&gt;&lt;br&gt;
Or, with arrow function syntax:&lt;br&gt;
&lt;code&gt;(() =&amp;gt; { console.log('Arrow IIFE runs immediately!'); })();&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Work?
&lt;/h2&gt;

&lt;p&gt;In JavaScript, when you define a function like:&lt;br&gt;
&lt;code&gt;function sayHi() {}&lt;/code&gt;&lt;br&gt;
…it’s just a declaration, and it won’t run until you call it.&lt;/p&gt;

&lt;p&gt;But to make the function run immediately, you need to turn it into an expression. That’s why we wrap it in parentheses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first () turns the function into a function expression.&lt;/li&gt;
&lt;li&gt;The second () calls it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avoiding Global Scope Pollution
IIFEs help keep variables inside their own scope so they don’t interfere with other parts of your code.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(function () { const secret = 'I stay local'; console.log(secret); // Works here })();

console.log(secret); // Error: secret is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Running Setup Code Once
If you want to run some initialization logic right away (like setting up configs), IIFE can be a clean solution.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const app = (() =&amp;gt; { const config = { env: 'production' }; console.log('App is starting...'); return { getConfig: () =&amp;gt; config }; })();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Using await in Non-Async Environments (Async IIFE)
In environments where you can't use top-level await (like older Node.js or CommonJS modules), an async IIFE allows you to run asynchronous code with await.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(async () =&amp;gt; { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); })();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is super useful for running async logic without needing to define and then manually call a separate async function.&lt;/p&gt;

&lt;p&gt;IIFEs are a handy JavaScript pattern that allow you to execute functions immediately while keeping variables scoped locally. While not as common in ES6+ codebases thanks to modules and let/const, they're still worth knowing — especially when you stumble across them in older code or want a quick isolated block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Console You Later!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>fundamentals</category>
    </item>
  </channel>
</rss>
