<?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: Edvaldo Freitas</title>
    <description>The latest articles on DEV Community by Edvaldo Freitas (@ed_dfreitas).</description>
    <link>https://dev.to/ed_dfreitas</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F907253%2F0fbd3c4a-4e07-4e65-bf71-2c9c53362339.png</url>
      <title>DEV Community: Edvaldo Freitas</title>
      <link>https://dev.to/ed_dfreitas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ed_dfreitas"/>
    <language>en</language>
    <item>
      <title>.Net Code Review: Best Practices and AI Tools (2026)</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Tue, 26 May 2026 11:24:00 +0000</pubDate>
      <link>https://dev.to/kodus/net-code-review-best-practices-and-ai-tools-2026-3nd9</link>
      <guid>https://dev.to/kodus/net-code-review-best-practices-and-ai-tools-2026-3nd9</guid>
      <description>&lt;p&gt;A good .NET code review process should do more than just quality control. It can be a way to transfer knowledge, reduce risk, and keep the architecture coherent. For many teams, though, it is just a bottleneck. Pull requests sit idle, feedback becomes inconsistent, and senior engineers burn out fixing typos instead of evaluating design decisions. The &lt;a href="https://kodus.io/en/manual-vs-automated-code-review/" rel="noopener noreferrer"&gt;standard review process simply does not scale&lt;/a&gt; with today’s .NET applications.&lt;/p&gt;

&lt;p&gt;The main problem is divided attention. A reviewer has to switch between finding style guide violations, looking for common bugs such as poor &lt;code&gt;async&lt;/code&gt; patterns, and thinking about the architectural impact of a change. AI tools can automate the first two jobs, leaving engineers free to focus on architecture, where their experience actually matters.&lt;/p&gt;

&lt;h2&gt;Why code review in .NET is different&lt;/h2&gt;

&lt;p&gt;Reviewing .NET code is different from reviewing code in other languages. C# is expressive and often gives you several ways to solve the same problem, which leads to inconsistency if you do not have clear standards. The .NET Base Class Library (BCL) is huge, and it takes experience to know which APIs are better for performance and memory usage.&lt;/p&gt;

&lt;p&gt;On top of that, frameworks like ASP.NET Core and Entity Framework Core add their own layers of abstraction. A change that looks good in isolation can generate terrible SQL queries or slow down the middleware pipeline. A good review requires understanding how the code interacts with the runtime and the framework, not just the code itself.&lt;/p&gt;

&lt;h2&gt;Best practices for .NET code review&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;Correct behavior&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Does the code do what the change promises to do, including error, timeout, cancellation, and edge cases? In .NET, this matters a lot for async flows, external integrations, and public API contracts.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Maintainability&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Six months from now, will someone on the team understand this code without opening four files and guessing the intent? Oversized classes, vague names, too many dependencies, and mixed responsibilities tend to become expensive in C#.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Are there obvious signs of unnecessary cost? This includes blocking async calls, poor EF Core queries, bad projections, avoidable allocations in hot paths, and careless use of serialization or I/O.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Does the change create room for a known problem? Unvalidated input, exposed secrets, loose authorization, logs with sensitive data, and new endpoints without proper access control still show up often.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Architectural cohesion&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Does the change respect the way this system is already organized? Does it belong in this service, this layer, and this boundary? In larger .NET codebases, this matters a lot because it is easy to solve a local problem while creating structural mess elsewhere.&lt;/p&gt;

&lt;p&gt;When these criteria are clear, feedback improves a lot. Instead of isolated comments, reviewers can explain why something needs to change.&lt;/p&gt;

&lt;h2&gt;A practical .NET code review checklist&lt;/h2&gt;

&lt;p&gt;A checklist systematizes the review process and helps make sure common issues are not missed. It should be a living document, updated as the team learns and the codebase changes.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Architecture and design&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;responsibility of the change:&lt;/strong&gt; does this class, method, or handler have a clear responsibility, or is it mixing business logic, data access, and external integration?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;architectural cohesion:&lt;/strong&gt; does the change belong in this service, project, and layer? Does it follow the patterns already used by the codebase, or does it create a deviation that will be hard to maintain?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;dependency management:&lt;/strong&gt; are dependencies coming through dependency injection in the right way? Does the lifetime make sense? Is there unnecessary coupling to concrete implementations?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;configuration and secrets:&lt;/strong&gt; are critical configurations strongly typed and validated? Do secrets come from a secure source instead of code or a versioned file?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;error handling:&lt;/strong&gt; are exceptions handled consistently? Does the code distinguish expected errors, domain errors, and unexpected failures? Do logs help with investigation without leaking sensitive information?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;C# and .NET specifics&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;async/await usage:&lt;/strong&gt; is the flow async end-to-end when there is I/O? Look for &lt;code&gt;.Result&lt;/code&gt;, &lt;code&gt;.Wait()&lt;/code&gt;, and &lt;code&gt;.GetAwaiter().GetResult()&lt;/code&gt; in controllers, handlers, jobs, and consumers. In ASP.NET Core, this often turns into blocking and lower throughput.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;cancellation:&lt;/strong&gt; is &lt;code&gt;CancellationToken&lt;/code&gt; being propagated to the database, HTTP, storage, and queues when the operation can be canceled?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;LINQ and EF Core queries:&lt;/strong&gt; is the query executed only when needed? Is there premature materialization with &lt;code&gt;.ToList()&lt;/code&gt; or &lt;code&gt;.ToArray()&lt;/code&gt;? Is there a risk of N+1, lazy loading in a hot path, unnecessary tracking, or poor projection?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;resource management:&lt;/strong&gt; are disposable objects, such as streams, HTTP responses, and readers, being disposed of correctly? Does the code avoid unnecessary resource retention?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;allocations and hot paths:&lt;/strong&gt; in critical paths, does the code avoid unnecessary allocations, repeated string concatenation, large payload copying, and excessive serialization?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;API and ASP.NET Core pipeline&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;HTTP contract:&lt;/strong&gt; do the route, verb, status code, and payload make sense for the case? Does the endpoint make it clear what happens on success, validation error, not found, and conflict?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;input validation:&lt;/strong&gt; is all external input treated as untrusted and validated before use?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;middleware and pipeline:&lt;/strong&gt; do changes in &lt;code&gt;Program.cs&lt;/code&gt; or in the HTTP pipeline respect the correct order of routing, CORS, authentication, and authorization? Is any custom middleware doing too much work?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;authorization:&lt;/strong&gt; does the new endpoint or operation require authentication and authorization at the right level? Is access protected by the appropriate policy, role, or rule?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;data access:&lt;/strong&gt; does the code avoid SQL injection, unsafe concatenation, and uncontrolled dynamic execution? In EF Core, is the query being built safely?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;sensitive data:&lt;/strong&gt; do secrets, tokens, connection strings, and personal information stay out of code, versioned config, exceptions, and logs?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;output and rendered content:&lt;/strong&gt; in applications with rendered HTML, is output encoding preserved to avoid XSS?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Testing and operations&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;coverage for the change:&lt;/strong&gt; does the new endpoint, critical query, or important rule have a test at the right level?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;observability:&lt;/strong&gt; if this fails in production, can the team investigate it? Do logs, metrics, and traces carry enough context?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;operational impact:&lt;/strong&gt; does the change alter timeouts, retries, queues, cache, health checks, or behavior under load without making that clear?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Common .NET problems that AI finds&lt;/h2&gt;

&lt;p&gt;Static analysis tools can find some of these things, but they often do not have enough context to catch subtle problems. AI tools analyze code in a different way. They can recognize anti-patterns by understanding what the developer was trying to do and how data flows through the application. They can automate a good part of the checklist above.&lt;/p&gt;

&lt;p&gt;Here are a few examples of common .NET problems that AI reviewers tend to catch well.&lt;/p&gt;

&lt;h3&gt;1. Blocking async code&lt;/h3&gt;

&lt;p&gt;A classic mistake that can lead to thread pool exhaustion and deadlocks in server applications.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class UserController : ControllerBase
{
    private readonly IUserService _userService;

    public UserController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpGet("{id}")]
    public ActionResult&amp;lt;User&amp;gt; GetUser(int id)
    {
        // This blocks the request thread, waiting for the async operation.
        var user = _userService.GetUserByIdAsync(id).Result; 
        if (user == null)
        {
            return NotFound();
        }
        return Ok(user);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public class UserController : ControllerBase
{
    private readonly IUserService _userService;

    public UserController(IUserService userService)
    {
        _userService = userService;
    }

    [HttpGet("{id}")]
    public async Task&amp;lt;ActionResult&amp;lt;User&amp;gt;&amp;gt; GetUser(int id)
    {
        var user = await _userService.GetUserByIdAsync(id);
        if (user == null)
        {
            return NotFound();
        }
        return Ok(user);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;AI tools can trace the call chain and flag the synchronous call over async code as a high-risk pattern, suggesting the correct implementation with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;2. Inefficient queries with Entity Framework Core&lt;/h3&gt;

&lt;p&gt;Loading a full dataset into memory before filtering is a common problem that destroys performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task&amp;lt;List&amp;lt;ProductDto&amp;gt;&amp;gt; GetActiveProducts(string category)
{
    // Pulls ALL products from the database into memory first.
    var allProducts = await _context.Products.ToListAsync(); 

    // Then filters in-memory.
    return allProducts
        .Where(p =&amp;gt; p.IsActive &amp;amp;&amp;amp; p.Category == category)
        .Select(p =&amp;gt; new ProductDto { Name = p.Name, Price = p.Price })
        .ToList();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task&amp;lt;List&amp;lt;ProductDto&amp;gt;&amp;gt; GetActiveProducts(string category)
{
    // Builds a SQL query with a WHERE clause, only fetching needed data.
    return await _context.Products
        .Where(p =&amp;gt; p.IsActive &amp;amp;&amp;amp; p.Category == category)
        .Select(p =&amp;gt; new ProductDto { Name = p.Name, Price = p.Price })
        .ToListAsync();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An AI with context can recognize that &lt;code&gt;_context.Products&lt;/code&gt; is an EF Core &lt;code&gt;IQueryable&lt;/code&gt; and that calling &lt;code&gt;.ToListAsync()&lt;/code&gt; immediately is almost always a mistake. It understands the semantics of deferred execution.&lt;/p&gt;

&lt;h3&gt;3. Improper use of HttpClient&lt;/h3&gt;

&lt;p&gt;Instantiating &lt;code&gt;HttpClient&lt;/code&gt; inside a &lt;code&gt;using&lt;/code&gt; block is a well-known anti-pattern that can lead to socket exhaustion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public async Task&amp;lt;string&amp;gt; GetExternalData()
{
    using (var client = new HttpClient())
    {
        var response = await client.GetStringAsync("https://api.example.com/data");
        return response;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion using IHttpClientFactory:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// In Startup.cs or Program.cs
services.AddHttpClient();

// In the service class
public class MyService
{
    private readonly HttpClient _client;

    public MyService(IHttpClientFactory clientFactory)
    {
        _client = clientFactory.CreateClient();
    }

    public async Task&amp;lt;string&amp;gt; GetExternalData()
    {
        var response = await _client.GetStringAsync("https://api.example.com/data");
        return response;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;AI tools can identify this pattern and suggest a refactor to use &lt;code&gt;IHttpClientFactory&lt;/code&gt;, which is the standard practice in .NET applications for managing the lifecycle of &lt;code&gt;HttpClient&lt;/code&gt; instances.&lt;/p&gt;

&lt;h3&gt;4. Forgetting to dispose IDisposable resources&lt;/h3&gt;

&lt;p&gt;A simple mistake that can lead to resource leaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void WriteToFile(string filePath, string text)
{
    var stream = new FileStream(filePath, FileMode.Create);
    var writer = new StreamWriter(stream);
    writer.Write(text);
    writer.Flush();
    // stream.Close() and writer.Close() are never called if an exception occurs.
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;public void WriteToFile(string filePath, string text)
{
    using var stream = new FileStream(filePath, FileMode.Create);
    using var writer = new StreamWriter(stream);
    writer.Write(text);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is a direct check that advanced linters can also perform, but AI tools can suggest the more modern C# syntax, with &lt;code&gt;using&lt;/code&gt; declarations, for the fix.&lt;/p&gt;

&lt;h2&gt;Best AI code review tools for .NET&lt;/h2&gt;

&lt;p&gt;The market for &lt;a href="https://kodus.io/en/ai-code-review-tools/" rel="noopener noreferrer"&gt;AI code review tools&lt;/a&gt; is growing. Although many tools offer generic language support, their effectiveness in .NET varies. A tool’s understanding of the CLR, BCL, and common frameworks like ASP.NET Core is what separates a useful assistant from a noisy one.&lt;/p&gt;

&lt;p&gt;Here is a comparison of several tools and how they apply to .NET development.&lt;/p&gt;

&lt;h3&gt;Kodus&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.13.32-1024x545.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.13.32-1024x545.png" alt="Kodus AI Code Review" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io" rel="noopener noreferrer"&gt;Kodus&lt;/a&gt; is the best option for .NET teams when the goal is to improve review inside a real codebase, not just add an AI commenting on pull requests. In C# and ASP.NET Core projects, many problems depend on context: incorrect use of &lt;code&gt;async/await&lt;/code&gt;, poor Entity Framework queries, authorization rules spread across the codebase, services that are too large, or changes that drift away from internal architectural patterns. This is where Kodus stands out. Kody reviews PRs automatically or on demand, comments directly in the Git workflow, and lets teams configure their own rules so the review follows the team’s standards, not just generic best practices.&lt;/p&gt;

&lt;p&gt;The main differentiator for .NET is &lt;a href="https://docs.kodus.io/how_to_use/en/code_review/configs/kody_rules" rel="noopener noreferrer"&gt;Kody Rules&lt;/a&gt;. The team can turn internal standards into review rules, with file scope, severity, and path filters. In a .NET application, this makes it possible to create specific rules for controllers, services, repositories, migrations, tests, or the domain layer. For example: avoiding business logic in controllers, requiring validation on public endpoints, reviewing &lt;code&gt;Include&lt;/code&gt; usage in Entity Framework, or ensuring tests for critical changes.&lt;/p&gt;

&lt;p&gt;Kodus also learns from team feedback, which helps reduce noise over time. This matters a lot in .NET because each codebase usually has its own decisions around architecture, exception handling, service organization, testing, and framework usage. Instead of treating every C# project the same way, Kodus becomes more aligned with the team’s standards as it is used.&lt;/p&gt;

&lt;p&gt;Another important point is control. Kodus is open source, works with GitHub, GitLab, Bitbucket, and Azure DevOps, supports BYOK, and lets the team choose the AI provider and model. For .NET teams that care about cost, privacy, and lock-in, this makes the tool a more flexible option for bringing AI code review into the pull request workflow.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;CodeRabbit&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.14.36-1024x306.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.14.36-1024x306.png" alt="Coderabbit" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/coderabbit-alternative/" rel="noopener noreferrer"&gt;CodeRabbit&lt;/a&gt; is an AI code review platform focused on pull requests, IDE, and CLI. For .NET teams, it can mainly help as an initial review layer in PRs, pointing out bugs, inconsistent patterns, and quality issues before a human reviewer goes deeper. The tool also allows teams to configure guidelines, path filters, and directory-specific instructions, which can be useful in C# projects with a clear separation between APIs, domain, infrastructure, tests, and front-end. In an ASP.NET Core application, for example, the team can use different instructions for controllers, migrations, services, middlewares, and tests. This helps reduce generic comments and brings the review closer to the decisions that actually matter in a .NET codebase.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;GitHub Copilot Code Review&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-05-at-11.23.25-1024x255.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-05-at-11.23.25-1024x255.png" alt="GitHub Copilot Code Review" width="799" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/github-copilot-alternatives/" rel="noopener noreferrer"&gt;Copilot&lt;/a&gt; makes sense when the company is already heavily centered on GitHub and wants to add automated review to the workflow with as little friction as possible. For many teams, this already solves part of the problem. It helps capture basic patterns, localized improvements, and quick comments in smaller PRs.&lt;/p&gt;

&lt;p&gt;The limitation appears when the team wants more control over the process, more model freedom, and more specific rules based on repository context.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Bito&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.15.24-1024x455.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.15.24-1024x455.png" alt="Bito" width="799" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bito positions its AI Code Review Agent as a set of specialized agents that analyze different aspects of the PR, such as performance, code structure, security, optimization, and scalability. This fits well with the kind of care .NET applications often require, since a seemingly simple change can affect Entity Framework performance, authentication flow, dependency injection, API serialization, or async behavior. The documentation also mentions the use of Symbol Indexing, AST, and embeddings to better understand the code and its dependencies. In practice, Bito can work as a review layer that helps the team identify common problems before human review, leaving seniors more focused on architecture, domain, and long-term decisions.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;CodeAnt AI&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.16.08-1024x344.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.16.08-1024x344.png" alt="" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeAnt AI has an approach closer to code health and security, combining AI code review with quality analysis and security risk detection. For .NET teams, this is relevant when review needs to cover not only readability and maintainability, but also vulnerabilities, bad practices, and risks related to authorization, input validation, data exposure, and unsafe dependency usage. The documentation shows that &lt;code&gt;codeant review&lt;/code&gt; analyzes changes with an agentic architecture, reads context around the codebase, and returns suggestions with severity. This kind of approach can be useful in C# projects where the team wants to prioritize findings by risk, especially in APIs, internal systems, financial applications, or products with stronger security and compliance requirements.&lt;/p&gt;

&lt;h2&gt;Comparison of code review tools for .NET&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Best fit in .NET&lt;/th&gt;
&lt;th&gt;Context used in review&lt;/th&gt;
&lt;th&gt;How review is customized&lt;/th&gt;
&lt;th&gt;Before the PR&lt;/th&gt;
&lt;th&gt;Infrastructure and control&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Kodus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams that want to turn internal C#, ASP.NET Core, and EF Core standards into versioned rules in the repository itself&lt;/td&gt;
&lt;td&gt;Diff, repository files, code search, repo-wide semantic context, and MCP plugins for external context&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Repository Rules&lt;/code&gt; in Markdown, rules by path, directory, and severity, sync of existing rule files&lt;/td&gt;
&lt;td&gt;Yes, via CLI on the working tree, staged diff, branch, or commit&lt;/td&gt;
&lt;td&gt;Cloud or self-hosted, BYOK by default, choice of provider and model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CodeRabbit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams with a monorepo or context spread across code, issues, docs, and related repositories&lt;/td&gt;
&lt;td&gt;Diff, knowledge base, linked repos, code guidelines, MCP, web search, issues, and learnings&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.coderabbit.yaml&lt;/code&gt;, &lt;code&gt;path_instructions&lt;/code&gt;, AST rules, custom checks, and code guidelines&lt;/td&gt;
&lt;td&gt;Yes, via IDE and CLI, in addition to PR review&lt;/td&gt;
&lt;td&gt;Flow centered on the CodeRabbit service, with versioned configuration in the repository&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Copilot Code Review&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub-first teams that want to add automatic review to the workflow with little friction&lt;/td&gt;
&lt;td&gt;Diff, additional repository context, and repo instructions&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.github/copilot-instructions.md&lt;/code&gt;, path-specific instructions in &lt;code&gt;.github/instructions/**&lt;/code&gt;, &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;CLAUDE.md&lt;/code&gt;, or &lt;code&gt;GEMINI.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yes, in IDEs like Visual Studio and VS Code; in PRs, it runs directly on GitHub&lt;/td&gt;
&lt;td&gt;Managed service in the GitHub ecosystem; customization through repository files&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bito&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams that want contextual review by repository, with local configuration and the option to run on their own infrastructure&lt;/td&gt;
&lt;td&gt;Diff, repository context, symbol indexes, embeddings, and AST&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.bito.yaml&lt;/code&gt;, general and language-specific guidelines, filters, summaries, secret scanner, and lint feedback&lt;/td&gt;
&lt;td&gt;Yes, via CLI and also in the PR workflow&lt;/td&gt;
&lt;td&gt;Bito-hosted or self-hosted; supports GitHub/GitLab self-managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CodeAnt AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Teams that want to combine PR review with security, code policy, and broader codebase analysis&lt;/td&gt;
&lt;td&gt;Diff, full codebase context, security and quality findings, language rules, and application security&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.codeant/configuration.json&lt;/code&gt;, custom review rules, code governance, and review instructions&lt;/td&gt;
&lt;td&gt;Yes, via IDE and CLI, in addition to automatic PR review&lt;/td&gt;
&lt;td&gt;Cloud and documented self-hosted scenarios for SCM and private deployments&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;How I would set up an AI review workflow for a .NET team&lt;/h2&gt;

&lt;p&gt;If I were setting this up for a .NET team today, I would start with a few rules and a lot of focus. The most common mistake at this stage is trying to turn the tool into a universal reviewer in the first month. That almost always increases comment volume and reduces trust. I would rather start with the areas where C# and ASP.NET Core tend to hide expensive problems: blocking async, EF Core reads, nullability, new endpoints without tests, and changes to the middleware pipeline.&lt;/p&gt;

&lt;p&gt;The second important decision would be to limit automatic review to issues that actually change risk, cost, or maintainability. Too many comments get tiring fast, especially in a &lt;a href="https://kodus.io/en/how-small-pull-requests-improve-team-flow/" rel="noopener noreferrer"&gt;small PR.&lt;/a&gt; It also makes sense to version the rules in the repository itself, so the team reviews the rule with the same care it reviews code. External context, such as a ticket, spec, or internal contract, I would only add when it improves the review decision. And I would measure it from the start: comment usefulness, false positives, and time to merge by PR type.&lt;/p&gt;

&lt;p&gt;If I were doing this with Kodus, an initial rule for C# could be this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;---
title: "Blocking async calls in HTTP and background execution paths"
scope: "file"
path: ["src/**/*.cs", "app/**/*.cs", "api/**/*.cs", "services/**/*.cs", "workers/**/*.cs"]
severity_min: "critical"
languages: ["csharp"]
buckets: ["performance", "error-handling", "public-contract"]
enabled: true
---

## Instructions
Review C# code that runs in ASP.NET Core request paths, background jobs, hosted services, queue consumers, and application services for blocking async calls.
- Flag any use of `.Result`, `.Wait()`, or `.GetAwaiter().GetResult()` on `Task` or `Task`.
- Flag sync wrappers around async I/O, especially database, HTTP, storage, cache, and message broker calls.
- Treat this as critical when the code is reachable from controllers, endpoints, MediatR handlers, background workers, or consumer handlers.
- Prefer async end-to-end, including `async` method signatures, `await`, and propagation of `CancellationToken`.
- If a sync boundary is truly unavoidable, require explicit justification and verify that it is outside latency-sensitive or high-concurrency flows.

## Examples

### Bad example


```csharp
public IActionResult GetCustomer(Guid id)
{
    var customer = _customerService.GetByIdAsync(id).Result;
    return Ok(customer);
}
```



### Good example


```csharp
public async Task GetCustomer(Guid id, CancellationToken ct)
{
    var customer = await _customerService.GetByIdAsync(id, ct);
    return Ok(customer);
}
```

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

&lt;p&gt;After that, I would add three more rules: one for EF Core reads, focused on N+1, lazy loading, and poor projections; another to require tests when the PR creates or changes an endpoint; and a third to review changes in the middleware pipeline, since order in ASP.NET Core affects authentication, authorization, CORS, and observability.&lt;/p&gt;

&lt;h2&gt;The future of code quality in .NET&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;Where AI helps, and where human review is still irreplaceable&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;AI tools help a lot when the problem is pattern recognition. In .NET, this includes blocking async, poor use of &lt;code&gt;CancellationToken&lt;/code&gt;, suspicious EF Core queries, unresolved nullability, and new endpoints without tests. This type of error shows up often, costs a lot, and, with the right rule, can be caught early.&lt;/p&gt;

&lt;p&gt;What AI still does not do well is the hardest part of review. It does not understand with the same depth whether a change respects the architectural direction of the system, whether the business rule was translated correctly, or whether that trade-off between simplicity and performance makes sense for the current product moment. It also does not replace the role of review as mentorship. When a more senior engineer explains why a solution is technically correct, but still a bad idea in that context, that kind of learning does not come from a checklist.&lt;/p&gt;

&lt;p&gt;When the tool takes over the repetitive, rule-driven part, the PR conversation moves up a level. Instead of spending time on mechanical details, the team can discuss production impact, public contracts, behavior under load, and long-term consequences.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;How I would improve the .NET review process from here&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;I would not start by trying to automate everything. I would start with a tool running in consultative mode, without blocking merges, and measure two things from the beginning: comment usefulness and false-positive rate. If the feedback is not helping, the problem is almost always in the rule, the scope, or the comment volume.&lt;/p&gt;

&lt;p&gt;The next step would be to use real incidents to improve the system. After a regression, a bad query in production, or a long debugging session, the useful question is not “who made the mistake?” The useful question is “could this have been caught in review?” If the answer is yes, then it is worth turning that learning into a team checklist or a tool rule.&lt;/p&gt;

&lt;p&gt;In the end, the most interesting gain from AI review in .NET is not reviewing more PRs per day. It is making human review spend less energy on noise and more energy on decisions that actually change the quality of the system.&lt;/p&gt;

&lt;h2&gt;Frequently asked questions&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;What is the best AI code review tool for .NET?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;It depends on your main goal. For PR summaries and line-level suggestions, GitHub Copilot or CodeRabbit are good choices. For deeper architectural analysis and applying custom team standards, Kodus was built for that purpose with repository-level context and natural-language rules.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Does Kodus work with .NET?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes. Kodus works with any language and was designed to understand the structure of complex projects, including .NET solutions with multiple projects. Its ability to track dependencies across a repository makes it especially effective for C# and the .NET ecosystem.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;What about the complexity of async/await in .NET?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;This is an area where AI tools help a lot. They can detect common &lt;code&gt;async&lt;/code&gt; pitfalls, such as sync-over-async blocking, forgetting to use &lt;code&gt;await&lt;/code&gt; on a &lt;code&gt;Task&lt;/code&gt;, or using &lt;code&gt;async void&lt;/code&gt; in inappropriate contexts. Because they can analyze the full call stack, they can find problems that a simple linter may miss.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Are there free code review tools for .NET?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Many AI tools, including Kodus, offer free plans for open source projects or small teams, which is a good way to evaluate them before committing to a paid plan.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Are there self-hosted options for .NET reviews?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes. Kodus is the most complete option on this list. The platform combines self-hosted deployment, BYOK by default, open source code, and freedom to choose the model and provider. In practice, this gives more control over where the code runs, how keys are managed, and which external services enter the review workflow. For organizations with strong privacy, security, or governance requirements, this combination puts Kodus in a better position than tools that treat self-hosting as an exception or limit model choice.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>codereview</category>
      <category>devex</category>
    </item>
    <item>
      <title>Best Devin Alternatives in 2026</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Mon, 25 May 2026 17:18:00 +0000</pubDate>
      <link>https://dev.to/kodus/best-devin-alternatives-in-2026-85l</link>
      <guid>https://dev.to/kodus/best-devin-alternatives-in-2026-85l</guid>
      <description>&lt;p&gt;Devin put an important idea on the table: delegating development tasks to a more autonomous AI agent. From there, “Devin alternatives” became a broader search. Teams are not always looking for a Devin clone. Many times, they are trying to understand which type of AI tool makes the most sense for their own engineering workflow.&lt;/p&gt;

&lt;p&gt;In practice, not every team wants to add a separate agent outside the current flow to handle changes end to end. In many cases, the problem is more specific: slow reviews, PRs that are too large, lack of context, repetitive tasks in the editor, or difficulty keeping standards consistent across repositories.&lt;/p&gt;

&lt;p&gt;That is why the search for Devin alternatives usually falls into three groups.&lt;/p&gt;

&lt;p&gt;Some teams want tools that fit into the workflow they already have. Something that works in VS Code, in the terminal, in GitHub, in GitLab, or directly in the pull request, without requiring a major process change.&lt;/p&gt;

&lt;p&gt;Others want more control over what the AI does. They want to use AI to speed up parts of the work, but still review the steps, guide the changes, and decide what gets into the code.&lt;/p&gt;

&lt;p&gt;And some teams are not looking for a generic agent. They are trying to solve a very specific bottleneck. For one team, that might be code review. For another, refactoring. For another, test generation or repetitive tasks in the editor. In those cases, a more focused tool usually works better than a broad solution trying to cover everything.&lt;/p&gt;

&lt;h2&gt;8 top Devin alternatives&lt;/h2&gt;

&lt;p&gt;This list covers different types of tools, from AI-native IDEs to terminal-focused agents and code review specialists. We ranked the options based on how they fit into different development workflows.&lt;/p&gt;

&lt;h3&gt;1. Kodus&lt;/h3&gt;

&lt;p&gt;Kodus is an open source &lt;a href="https://kodus.io/en/ai-code-review-tools/" id="https://kodus.io/en/ai-code-review-tools/" rel="noopener noreferrer"&gt;AI code review tool,&lt;/a&gt; not a code generation agent. It focuses on improving code quality and consistency before merge. It integrates directly into your Git workflow, reviews pull requests automatically, and delivers feedback based on general best practices and custom rules your team defines in natural language. It is the best alternative to Devin Review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specialized in code review.&lt;/strong&gt; Kodus was built to review code, prioritize relevant issues, and reduce noise. It analyzes security risks, performance problems, error handling issues, maintainability concerns, and team-specific standards.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;More context than tools that only review the diff.&lt;/strong&gt; The review still stays anchored in the PR, but Kodus also uses full repository context, code search, and, when enabled, cross-file analysis and pull request-level checks. This usually leads to more useful comments than tools that only look at the isolated patch.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Customizable rules.&lt;/strong&gt; Teams can create Kody Rules for their own engineering policies, version those rules inside the repository, and control behavior at the global, repository, and directory level. This is especially useful in monorepos or teams with different standards across services.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Model-agnostic with real BYOK support.&lt;/strong&gt; You can use your own keys from any LLM provider, giving you control over costs and model choice.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Self-hosting.&lt;/strong&gt; Teams with strict data privacy requirements can host Kodus in their own infrastructure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not for code generation.&lt;/strong&gt; If you are looking for an agent to write features from scratch, Kodus is not the right tool. It is built to review and improve code, not create it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Community plan is free with BYOK.&lt;br&gt;The Teams plan costs &lt;strong&gt;$10 per active developer per month&lt;/strong&gt; + tokens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want to &lt;a href="https://kodus.io/en/guide-to-code-review/" id="https://kodus.io/en/guide-to-code-review/" rel="noopener noreferrer"&gt;automate the code review process&lt;/a&gt;, apply consistent standards, and improve code quality without slowing down development.&lt;/p&gt;

&lt;p&gt;Explore the open source repo: &lt;a href="https://github.com/kodustech/kodus-ai" rel="noopener noreferrer"&gt;https://github.com/kodustech/kodus-ai&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;2. Cursor&lt;/h3&gt;

&lt;p&gt;Cursor is an AI IDE before anything else. It provides autocomplete, chat, multi-file editing, background agents, and Bugbot for review.&lt;/p&gt;

&lt;p&gt;The comparison with Devin makes sense because both help produce code changes and automate part of the work. The workflow, however, is very different. Cursor starts in the editor. Devin starts from a more autonomous proposal. That is why Cursor tends to make more sense when the developer still wants to drive most of the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very good workflow for developers who want to use agents and assisted editing directly in the IDE. Background Agents and&lt;a href="https://kodus.io/kodus-vs-cursor-bugbot/" id="https://kodus.io/kodus-vs-cursor-bugbot/" rel="noopener noreferrer"&gt; Bugbot &lt;/a&gt;expand its use beyond autocomplete.&lt;/li&gt;



&lt;li&gt;Rules and project context can be versioned in the repository.&lt;/li&gt;



&lt;li&gt;Good option for teams that want to iterate quickly inside the editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Although it is a VS Code fork, it is its own editor. That can be a blocker for teams with strict policies around approved development environments.&lt;/li&gt;



&lt;li&gt;It is great for helping a developer who is actively coding, but it will not take a high-level prompt and finish an entire project by itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pro at $20/month&lt;br&gt;Pro+ at $60/month&lt;br&gt;Ultra at $200/month&lt;br&gt;Teams at $40/user/month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want IDE-centered AI, with agents and some automation, without completely changing how they write code.&lt;/p&gt;

&lt;h3&gt;3. Aider&lt;/h3&gt;

&lt;p&gt;Aider is an AI pair programming tool based in the terminal. It edits code directly in your local Git repository.&lt;/p&gt;

&lt;p&gt;Its proposal is very different from Devin’s. Aider is closer to an AI pair programmer, controlled by the developer, than to an autonomous agent. It uses a repository map to better understand context, supports architecture and implementation modes, integrates well with Git, and works with many models, both cloud-based and local.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open source&lt;/li&gt;



&lt;li&gt;Works with many providers and local models&lt;/li&gt;



&lt;li&gt;Excellent Git integration, including auto-commits and undo&lt;/li&gt;



&lt;li&gt;Lightweight and easy to fit into the terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not designed for long-running autonomy in the background&lt;/li&gt;



&lt;li&gt;The workflow is more focused on one session per repo&lt;/li&gt;



&lt;li&gt;PR review is outside its main scope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free; model costs are separate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Engineers who want terminal-based pair programming with a really good Git integration.&lt;/p&gt;

&lt;h3&gt;4. GitHub Copilot Coding Agent&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/github-copilot-alternatives/" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt; Coding Agent is GitHub’s most direct answer to the issue-to-PR workflow. If your team already works inside GitHub, wants to automate tasks, and does not want to bring another platform into the process, it is a very natural alternative to Devin.&lt;/p&gt;

&lt;p&gt;The main difference is scope. Copilot Coding Agent is more tied to the GitHub ecosystem. Devin tries to work as a broader and more autonomous layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works directly with issues and PRs in GitHub.&lt;/li&gt;



&lt;li&gt;Included in existing paid Copilot plans.&lt;/li&gt;



&lt;li&gt;Adoption tends to be simple for teams that already use GitHub as the base of their workflow.&lt;/li&gt;



&lt;li&gt;Benefits from the rest of the GitHub ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its functionality is almost entirely tied to GitHub. Teams using Bitbucket, GitLab, or other platforms are left out.&lt;/li&gt;



&lt;li&gt;Works better for incremental work than for teams that want a more independent agent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing: &lt;/strong&gt;Included starting with Copilot Pro, at $10/month. Pro+ costs $39/month. Business and Enterprise are available for organizations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that mainly work in GitHub and want to automate tasks without leaving the platform.&lt;/p&gt;

&lt;h3&gt;5. Continue.dev&lt;/h3&gt;

&lt;p&gt;Continue.dev has become a broad open source platform for AI development. It covers IDE extensions, CLI workflows, PR checks, cloud agents, MCP integrations, and paths for self-hosted models.&lt;/p&gt;

&lt;p&gt;That breadth is exactly what attracts some teams. You can treat Continue.dev as a customizable alternative to Devin when the goal is to build an AI workflow around your own checks, prompts, rules, and infrastructure, instead of adopting a more closed and opinionated agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open source and suitable for self-hosted setups or private models.&lt;/li&gt;



&lt;li&gt;Good customization with model roles, rules, prompts, and MCP servers.&lt;/li&gt;



&lt;li&gt;Makes sense for platform teams that want to build internal AI workflows instead of buying a closed product.&lt;/li&gt;



&lt;li&gt;Works both in the IDE and in the terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More configurable than ready to use.&lt;/li&gt;



&lt;li&gt;The product surface is broad, so new users need time to understand how the pieces connect.&lt;/li&gt;



&lt;li&gt;If you want a ready-made autonomous coding agent, with strong and opinionated defaults, other tools are simpler to start with.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Starter costs $3 per million input and output tokens, on a pay-as-you-go model. Team costs $20 per seat/month and includes $10 in credits per seat. Company has custom pricing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want open source flexibility, custom AI checks, self-hosting options, and more control over the stack than Devin usually offers.&lt;/p&gt;

&lt;h3&gt;6. Claude Code&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://kodus.io/kodus-vs-claude/" id="30446" rel="noopener noreferrer"&gt;Claude Code &lt;/a&gt;is Anthropic’s tool for working with code using Claude models. In practice, it stands out when you need to understand a real codebase, investigate bugs, refactor larger parts of the system, or discuss architecture decisions in the terminal.&lt;/p&gt;

&lt;p&gt;Claude Code works more like a terminal-based work tool than a full IDE. It helps edit files, run commands, navigate the codebase, and use parts of the Claude ecosystem, such as skills, memory, and connectors, inside a workflow that is closer to day-to-day development.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terminal-native and easy to fit into the engineering workflow.&lt;/li&gt;



&lt;li&gt;Works with Anthropic, Bedrock, and Vertex.&lt;/li&gt;



&lt;li&gt;Project settings can be versioned in the repository.&lt;/li&gt;



&lt;li&gt;Good option for teams that want an agent with constant human supervision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The cost for teams depends more on token consumption than on a simple per-user price.&lt;/li&gt;



&lt;li&gt;It does not have the same backlog and collaboration layer that Devin tries to offer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Claude Pro costs &lt;strong&gt;$20 per month&lt;/strong&gt; with monthly billing. Max starts at &lt;strong&gt;$100 per month&lt;/strong&gt;. Standard Team seats cost &lt;strong&gt;$25 per seat per month&lt;/strong&gt; with monthly billing, and Enterprise starts at &lt;strong&gt;$20 per seat plus usage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Developers who want a high-quality coding agent for deep reasoning, code understanding, and good terminal workflows.&lt;/p&gt;

&lt;h3&gt;7. OpenAI Codex&lt;/h3&gt;

&lt;p&gt;OpenAI Codex is a coding agent that reads, edits, and runs code in cloud environments. It can also be used locally through the CLI and extensions.&lt;/p&gt;

&lt;p&gt;The main difference compared with more editor-centered tools is delegation. You can assign multiple background tasks to Codex, let each one run in its own sandbox, trigger it through GitHub, and control internet access by environment. Among Devin alternatives, it is one of the closest when the focus is longer, parallel programming work running in the cloud.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Good cloud task model, with sandboxed environments and parallel execution.&lt;/li&gt;



&lt;li&gt;Works on the web, in the IDE, CLI, GitHub, and also through mobile entry points.&lt;/li&gt;



&lt;li&gt;Very explicit security controls, including rules and internet access allowlists by environment.&lt;/li&gt;



&lt;li&gt;MCP, SDK, and GitHub integration create room for internal automations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The price currently depends on credit consumption based on tokens, so uncontrolled use can get expensive quickly.&lt;/li&gt;



&lt;li&gt;The best results still depend on well-configured environments, which adds operational work.&lt;/li&gt;



&lt;li&gt;It is not as natural in the GitHub review flow as Copilot, nor as specialized in review as Kodus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Codex is included in ChatGPT Plus, Pro, Business, Edu, and Enterprise plans. After that, usage is charged through credits. OpenAI updated Codex to token-based pricing and estimates average usage at around $100 to $200 per developer per month.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want to delegate tasks in the cloud, in a workflow similar to Devin, but with more control over the sandbox and more integration options with the OpenAI ecosystem.&lt;/p&gt;

&lt;h3&gt;8. Cline&lt;/h3&gt;

&lt;p&gt;Cline is an open source coding agent that runs in the editor and the terminal. It can read and edit files, execute commands, use the browser, and work with different providers.&lt;/p&gt;

&lt;p&gt;The comparison with Devin makes sense for teams that want more autonomy in development, but still need transparency, BYOK, and explicit approval before certain actions. Cline makes the workflow more visible to the developer, which usually appeals to more technical teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open source.&lt;/li&gt;



&lt;li&gt;BYOK with several providers.&lt;/li&gt;



&lt;li&gt;Runs locally in your IDE, so it uses your exact development environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires more setup decisions than a managed platform.&lt;/li&gt;



&lt;li&gt;Teams that want a ready-made cloud workflow may prefer Devin or Windsurf.&lt;/li&gt;



&lt;li&gt;More complete governance features are more tied to the enterprise offering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pricing:&lt;/strong&gt; Free open source extension. Model costs or Cline credits are separate. Enterprise is available on request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want an open coding agent and are willing to assemble more parts of their own stack.&lt;/p&gt;

&lt;h2&gt;Full comparison table&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Main category&lt;/th&gt;
&lt;th&gt;Custom rules and policies&lt;/th&gt;
&lt;th&gt;Starting price&lt;/th&gt;
&lt;th&gt;Best fit&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Kodus&lt;/td&gt;
&lt;td&gt;AI code review&lt;/td&gt;
&lt;td&gt;Yes. Kody Rules, global/repo/directory config, and versioned rules in the repository.&lt;/td&gt;
&lt;td&gt;Community free; Teams at $10 per active developer/month + tokens&lt;/td&gt;
&lt;td&gt;Teams that want repository-aware code review and stronger governance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Devin&lt;/td&gt;
&lt;td&gt;Autonomous software agent&lt;/td&gt;
&lt;td&gt;Yes. Session instructions and task context.&lt;/td&gt;
&lt;td&gt;Free; Pro at $20/month; Teams from $80/month minimum&lt;/td&gt;
&lt;td&gt;Teams that want to delegate implementation, debugging, and long-running tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cursor&lt;/td&gt;
&lt;td&gt;AI-first code editor&lt;/td&gt;
&lt;td&gt;Yes. Rules, skills, hooks, and team context.&lt;/td&gt;
&lt;td&gt;Hobby free; Pro at $20/month; Teams at $40/user/month&lt;/td&gt;
&lt;td&gt;Developers who want AI embedded in the editor all day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Aider&lt;/td&gt;
&lt;td&gt;Terminal pair programming&lt;/td&gt;
&lt;td&gt;Partial. Configuration and git-based workflow.&lt;/td&gt;
&lt;td&gt;Free; inference costs only&lt;/td&gt;
&lt;td&gt;Developers who want local repo editing with a git-centric workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot Coding Agent&lt;/td&gt;
&lt;td&gt;GitHub-native agent and assistant&lt;/td&gt;
&lt;td&gt;Yes. Repository instructions and GitHub policy controls.&lt;/td&gt;
&lt;td&gt;Free; Pro at $10/month; Business at $19/user/month&lt;/td&gt;
&lt;td&gt;Teams already centered on GitHub Issues, PRs, and Actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Continue.dev&lt;/td&gt;
&lt;td&gt;Open source agent and checks platform&lt;/td&gt;
&lt;td&gt;Yes. Rules, tools, checks, and custom configuration.&lt;/td&gt;
&lt;td&gt;Starter at $3 per million tokens; Team at $20/seat/month&lt;/td&gt;
&lt;td&gt;Teams that want a more customizable and controlled AI development stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;Terminal-first coding agent&lt;/td&gt;
&lt;td&gt;Partial. Projects, memory, skills, and context.&lt;/td&gt;
&lt;td&gt;Claude Pro at $20/month; Max at $100/month&lt;/td&gt;
&lt;td&gt;Developers who want strong reasoning for refactoring, debugging, and implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI Codex&lt;/td&gt;
&lt;td&gt;Coding agent with cloud execution&lt;/td&gt;
&lt;td&gt;Yes. Environment controls, permissions, and automations.&lt;/td&gt;
&lt;td&gt;Included in paid ChatGPT plans + usage credits&lt;/td&gt;
&lt;td&gt;Teams that want parallel task delegation with sandbox and internet controls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cline&lt;/td&gt;
&lt;td&gt;Open source coding agent for editor and terminal&lt;/td&gt;
&lt;td&gt;Yes. Rules, MCP, hooks, skills, and permission controls.&lt;/td&gt;
&lt;td&gt;Free; inference costs only&lt;/td&gt;
&lt;td&gt;Power users who want fine-grained control over model, tools, and execution&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;Frequently asked questions&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;What is the best Devin alternative in 2026?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;It depends on what you want to replace. If the goal is to replace Devin as an autonomous implementation agent, tools like Claude Code, OpenAI Codex, and GitHub Copilot Coding Agent usually make more sense. If the main point is improving code review with AI, the best alternative is Kodus.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Is Kodus a good Devin alternative?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes, especially for teams that do not need an agent to implement entire features on its own, but want to raise code quality before merge. Kodus is the best option when the real problem is review: inconsistency between reviewers, shallow feedback, lack of repository context, and difficulty applying team standards in a predictable way.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Is Kodus better than Devin Review?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;For AI code review, in many scenarios, yes. Devin Review makes sense for teams that are already inside the Devin ecosystem and want to extend that experience to PRs. Kodus, on the other hand, is more specialized in code review and code review governance. It stands out by offering repository context, custom rules in natural language, versioned configuration, BYOK, a model-agnostic approach, and more control over the review workflow. In teams that treat review as a critical engineering process, that usually matters more than having a more generalist tool.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Can I migrate from Devin to Kodus?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Not in a 1:1 sense, because the two tools solve different parts of the workflow. The most common path is to keep a coding agent for implementation and add Kodus at the review layer. For many teams, that works better than trying to force a single product to do both things well.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Are there self-hosted Devin alternatives?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;For coding agents, Cline and Aider are good options. Continue also makes sense for teams that want to build a more custom workflow. For PR review, Kodus is the best option.&lt;/p&gt;

</description>
      <category>resources</category>
      <category>productivity</category>
      <category>devex</category>
    </item>
    <item>
      <title>Node.js Code Review: Best Practices, Checklist, and AI Tools (2026)</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Mon, 25 May 2026 14:11:53 +0000</pubDate>
      <link>https://dev.to/kodus/nodejs-code-review-best-practices-checklist-and-ai-tools-2026-2e4a</link>
      <guid>https://dev.to/kodus/nodejs-code-review-best-practices-checklist-and-ai-tools-2026-2e4a</guid>
      <description>&lt;p&gt;Code review is one of the best ways to improve code quality in a growing Node.js codebase. It helps teams catch bugs earlier, keep patterns consistent, and avoid changes that make services harder to maintain over time. In a Node.js code review, that matters even more because many problems are easy to miss in a quick pull request. Async flows, runtime validation, middleware order, external calls, and query behavior can all look fine at first and still create expensive issues in production.&lt;/p&gt;

&lt;p&gt;That is why a good review process for Node.js should do more than check style and names. It should help the team look at runtime behavior, system boundaries, operational risk, and long-term maintainability. In this guide, I will go through a practical checklist for reviewing Node.js code, common problems that &lt;a href="https://kodus.io/en/ai-code-review-tools/" id="26587" rel="noopener noreferrer"&gt;AI tools&lt;/a&gt; tend to catch well, and how I would set up a review workflow for a team building modern Node.js services.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Challenges in Node.js code review&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;Node.js code often looks simpler than it really is. A short route handler, for example, can hide weak input validation, missing authorization checks, expensive queries, or an external call with no timeout. In the diff, the change looks small. In production, though, the behavior depends on what happens at runtime, under concurrency, and across service boundaries.&lt;/p&gt;

&lt;p&gt;That is why reviewing Node.js is not just about looking at the code inside a file. It is about understanding how that code behaves when it receives real traffic, processes untrusted input, talks to the database, publishes to a queue, or depends on a package that just changed versions. A good reviewer needs to follow the path the code takes through the application, not just judge whether the implementation looks clean.&lt;/p&gt;

&lt;h2&gt;The areas I would always review first&lt;/h2&gt;

&lt;p&gt;In Node.js, many important problems do not show up as an obvious error in the pull request. The change can look small, pass the tests, and still create production risk. So before spending time on naming, formatting, or small refactors, I would look at these areas first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;runtime boundaries: &lt;/strong&gt;Node.js services receive data from many places: query params, request bodies, headers, webhook payloads, and queue messages. If those inputs are not validated carefully, the issue can show up as an authorization bug, a validation failure, or leakage across tenants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;async behavior:&lt;/strong&gt; many reliability problems come from promises without clear handling, retries with side effects, and async flows that work in the happy path but fail badly under load or partial failure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;performance risk:&lt;/strong&gt; blocking the event loop, using Promise.all without limits, or doing expensive I/O inside a critical flow can easily pass review. Each line looks simple, but the whole change can become heavy in production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;data access: &lt;/strong&gt;a short handler can still trigger a query that is too heavy, too broad, or inconsistent under load. This is one of the most common ways a small change becomes a problem after deploy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;operational impact: &lt;/strong&gt;changes to packages, timeouts, logs, configuration, and observability also need to be part of the review. In Node.js, these details often define whether an incident will be easy to understand or hard to investigate.&lt;/p&gt;

&lt;p&gt;I prioritize these areas because this is where small changes tend to create the most expensive problems. Cosmetic adjustments can wait. Runtime errors and operational failures almost never can.&lt;/p&gt;

&lt;h2&gt;A practical Node.js code review checklist&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;Input validation and runtime boundaries&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;request input:&lt;/strong&gt; are &lt;code&gt;req.body&lt;/code&gt;, &lt;code&gt;req.query&lt;/code&gt;, &lt;code&gt;req.params&lt;/code&gt;, headers, cookies, and webhook payloads validated before use?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;runtime assumptions:&lt;/strong&gt; does the code rely on TypeScript or casts where the runtime still accepts different formats?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;external data:&lt;/strong&gt; are responses from third-party services treated as untrusted until they are parsed and validated?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;configuration input:&lt;/strong&gt; are environment variables parsed and checked instead of being assumed correct?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Authorization and tenant isolation&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;auth checks:&lt;/strong&gt; does the route, command, or job apply authentication and authorization at the right level?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;tenant boundaries:&lt;/strong&gt; does the code use IDs from the request in a way that could weaken isolation between tenants or accounts?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;ownership rules:&lt;/strong&gt; are user and resource ownership rules explicit before sensitive actions happen?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Async flow&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;promise handling:&lt;/strong&gt; is every promise awaited, returned, or intentionally left in the background with explicit error handling?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;side effects:&lt;/strong&gt; if a process retries or runs twice, does the code remain safe?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;job behavior:&lt;/strong&gt; do workers, schedulers, and queue consumers make their assumptions about retry and delivery clear?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Error handling&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;expected versus unexpected failures:&lt;/strong&gt; are validation errors, domain errors, and system failures handled differently?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;error visibility:&lt;/strong&gt; does the code preserve enough context to debug what failed?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;safe responses:&lt;/strong&gt; do error responses avoid leaking stack traces, secrets, or internal structure?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Timeouts, cancellation, and external calls&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;timeouts:&lt;/strong&gt; do external HTTP calls, storage, cache, and brokers define explicit timeouts?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;abort behavior:&lt;/strong&gt; does the code pass abort or cancellation signals where the stack supports them?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;third-party reliability:&lt;/strong&gt; if the dependency becomes slow or returns bad data, does the application still behave predictably?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Performance and event loop&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;blocking work:&lt;/strong&gt; does the PR add synchronous filesystem access, heavy CPU transformations, large JSON parsing, compression, or encryption on a hot path?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;memory usage:&lt;/strong&gt; does the code load more data into memory than it needs?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;cost on the request path:&lt;/strong&gt; could this change increase latency or reduce throughput under real load?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Database access and query behavior&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;query shape:&lt;/strong&gt; does the ORM or query builder generate the query the author expects?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;pagination and filters:&lt;/strong&gt; does the code avoid accidental broad reads or missing limits?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;projection:&lt;/strong&gt; does the API return only the fields it needs?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;write behavior:&lt;/strong&gt; are transactions or conflict-handling patterns clear where multiple writes need to remain consistent?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Concurrency and consistency&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;parallel work:&lt;/strong&gt; does &lt;code&gt;Promise.all&lt;/code&gt; or batch fan-out create more concurrency than the system can safely handle?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;duplicate execution:&lt;/strong&gt; does the code behave safely if the same event or job is processed more than once?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;races:&lt;/strong&gt; are there obvious race conditions in writes, state transitions, or shared resources?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Middleware, HTTP pipeline, and execution order&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;middleware order:&lt;/strong&gt; if the PR changes Express, NestJS, or Fastify middleware, do auth, validation, logging, rate limiting, and error handling still happen in the right order?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;single responsibility:&lt;/strong&gt; is the middleware focused, or is it doing too much work for one layer?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;HTTP behavior:&lt;/strong&gt; do routes return the right status codes and predictable payloads for success and failure cases?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Dependencies and supply chain&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;package changes:&lt;/strong&gt; does a new dependency or version upgrade deserve manual review for security history, maintenance, or install scripts?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;lockfile review:&lt;/strong&gt; are lockfile changes and transitive dependencies being treated as part of the review surface?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;need:&lt;/strong&gt; is the new dependency worth the long-term cost of maintaining it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Configuration and environment variables&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;startup validation:&lt;/strong&gt; does the application fail fast when configuration is missing or malformed?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;safe defaults:&lt;/strong&gt; are defaults explicit and appropriate for the environment?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;secret handling:&lt;/strong&gt; do secrets stay out of code, logs, example files, and versioned configuration?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;logs:&lt;/strong&gt; if this fails in production, will the logs explain what happened without exposing sensitive data?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;metrics and traces:&lt;/strong&gt; does the change preserve enough visibility into latency, retries, external calls, and job behavior?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;correlation:&lt;/strong&gt; can the team connect a user-visible failure to the internal path that caused it?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Tests&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;coverage by risk level:&lt;/strong&gt; are tests added where the risk actually is, such as route boundaries, auth rules, queue behavior, or failure modes?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;unhappy paths:&lt;/strong&gt; are malformed input, timeout paths, retries, and edge cases covered?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;real formats:&lt;/strong&gt; do the tests reflect runtime behavior instead of only ideal typed inputs?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;&lt;strong&gt;Readability and maintainability&lt;/strong&gt;&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;clarity:&lt;/strong&gt; are names, module boundaries, and control flow easy to understand?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;coupling:&lt;/strong&gt; does the change create hidden dependencies between route code, service code, data access, and infrastructure?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;future review cost:&lt;/strong&gt; will the next reviewer understand this code quickly, or will they need to reverse-engineer the intent?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;&lt;strong&gt;Common Node.js problems an AI tool can help find&lt;/strong&gt;&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;Using untrusted input too early&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app.get('/projects', async (req, res) =&amp;gt; {
  const organizationId = req.query.organizationId as string;
  const projects = await projectService.listForOrganization(organizationId);
  res.json(projects);
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;app.get('/projects', async (req, res) =&amp;gt; {
  const rawOrganizationId = req.query.organizationId;

  if (typeof rawOrganizationId !== 'string') {
    return res.status(400).json({ error: 'organizationId must be a string' });
  }

  const projects = await projectService.listForOrganization(rawOrganizationId);
  res.json(projects);
});&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;strong&gt;Missing timeouts in external calls&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export async function fetchProfile(userId) {
  const response = await fetch(`https://profiles.example.com/${userId}`);
  return response.json();
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export async function fetchProfile(userId) {
  const response = await fetch(
    `https://profiles.example.com/${userId}`,
    { signal: AbortSignal.timeout(3000) }
  );

  if (!response.ok) {
    throw new Error(`profiles returned ${response.status}`);
  }

  return response.json();
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;strong&gt;Broad concurrency without limits&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;await Promise.all(orderIds.map((id) =&amp;gt; syncOrder(id)));&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;for (let i = 0; i &amp;lt; orderIds.length; i += 20) {
  const batch = orderIds.slice(i, i + 20);
  await Promise.all(batch.map((id) =&amp;gt; syncOrder(id)));
}&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&lt;strong&gt;Blocking the event loop on the request path&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import { readFileSync } from 'node:fs';

app.post('/preview-email', (req, res) =&amp;gt; {
  const template = readFileSync('./templates/email.html', 'utf8');
  res.send(render(template, req.body));
});&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;After, AI suggestion:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;import { promises as fs } from 'node:fs';

const template = await fs.readFile('./templates/email.html', 'utf8');

app.post('/preview-email', (req, res) =&amp;gt; {
  res.send(render(template, req.body));
});&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;What I would look for in an AI code review tool for Node.js&lt;/h2&gt;

&lt;p&gt;I would care less about whether the tool says it supports JavaScript or TypeScript and more about how much it helps with the real review problems in Node.js.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;repository-specific rules:&lt;/strong&gt; can the team encode standards for routes, workers, packages, and architectural boundaries?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;cross-file context:&lt;/strong&gt; can the tool reason beyond the changed line and understand the surrounding flow?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;dependency awareness:&lt;/strong&gt; does the review flow treat package and lockfile changes as real code review material?&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;signal over noise:&lt;/strong&gt; does the tool reduce repetitive failures or just create more comments to ignore?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Good code review tools for Node.js teams in 2026&lt;/h2&gt;

&lt;p&gt;A good code review tool for Node.js is not just the one that comments on the pull request. It needs to help the team find problems that easily slip through small diffs: runtime validation, tenant isolation, async flow, concurrency, bad queries, and operational impact.&lt;/p&gt;

&lt;p&gt;The options below have different approaches. It is worth looking less at the feature list and more at the type of review each one actually improves.&lt;/p&gt;

&lt;h3&gt;Kodus&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.13.32-1024x545.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.13.32-1024x545.png" alt="Kodus AI Code Review" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Node.js teams, &lt;a href="https://kodus.io" id="https://kodus.io" rel="noopener noreferrer"&gt;Kodus&lt;/a&gt; makes more sense when review needs to reflect the real context of the repository, not just generic best practices. This matters in codebases with APIs, workers, queues, external integrations, and internal rules that do not show up in linters.&lt;/p&gt;

&lt;p&gt;The practical difference comes down to three points. &lt;/p&gt;

&lt;p&gt;The first point is repository context. In Node.js, the bug is rarely only in the changed line. It usually appears in the path between route, middleware, service, query, queue, and external integration. That is why reviewing only the diff is almost never enough. What makes Kodus different is evaluating the change inside that larger flow, considering the repository structure and the rules the team has defined for each part of the system.&lt;/p&gt;

&lt;p&gt;Second, custom rules in natural language with Repository Rules and Kody Rules, useful for turning route patterns, middleware, jobs, boundaries, and data access into review criteria. &lt;/p&gt;

&lt;p&gt;Third, control: &lt;a href="https://github.com/kodustech/kodus-ai" id="https://github.com/kodustech/kodus-ai" rel="noopener noreferrer"&gt;Kodus is open source,&lt;/a&gt; supports &lt;a href="https://docs.kodus.io/how_to_use/en/byok" id="https://docs.kodus.io/how_to_use/en/byok" rel="noopener noreferrer"&gt;BYOK&lt;/a&gt;, is model-agnostic, and allows teams to use MCP plugins to bring external context, such as specs and tickets, into the review.&lt;/p&gt;

&lt;p&gt;In practice, this helps a lot in Node.js because many serious problems depend on context. A generic reviewer can find local bugs. Kodus makes more sense when the team wants to create rules like: “no public route should use req.query or req.body in authorization decisions before validating the runtime shape” or “changes to queue consumers need to be reviewed with a focus on idempotency and retry safety”.&lt;/p&gt;

&lt;p&gt;This kind of rule is not cosmetic. It targets expensive, recurring bug classes in Node.js APIs.&lt;/p&gt;

&lt;h3&gt;CodeAnt AI&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.16.08-1024x344.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.16.08-1024x344.png" alt="" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;CodeAnt leans more toward security and code health than pure contextual review. The platform combines pull request review, IDE, CLI, and a unified view of code, dependencies, infrastructure, and secrets.&lt;/p&gt;

&lt;p&gt;For Node.js teams, this makes sense when review needs to look more at risk, severity, and security posture than internal architecture conventions. The strong point is combining line-by-line comments with codebase context and a clearer layer of findings and prioritization. It also supports custom rules by repository and file glob, which helps apply specific policies to routes, services, or handlers.&lt;/p&gt;

&lt;p&gt;In practice, I see CodeAnt working better for Node.js teams that want to use review as part of a broader security and quality pipeline. It seems more useful when the question is “which changes increased risk?” than when the question is “how do we apply the internal rules of our monorepo and service architecture?”.&lt;/p&gt;

&lt;p&gt;For a Node.js API with a lot of public surface area, sensitive integrations, or compliance requirements, this approach can help. For a team that wants review more tied to boundaries and internal patterns, the result will depend a lot on the quality of the configured rules.&lt;/p&gt;

&lt;h3&gt;Graphite&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-06-at-14.00.28-1024x391.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-06-at-14.00.28-1024x391.png" alt="graphite" width="799" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/graphite-alternatives/" id="https://kodus.io/en/graphite-alternatives/" rel="noopener noreferrer"&gt;Graphite&lt;/a&gt; has a slightly different approach. It is stronger as a PR workflow platform, especially for teams that live in GitHub and want to add automated review without changing much of their current process.&lt;/p&gt;

&lt;p&gt;Graphite Agent focuses on fast setup, comments directly in the PR, concrete fix suggestions, custom rules, and acceptance analytics by rule. For Node.js, this helps when the main problem is review speed and feedback quality in pull requests, not deeper repository governance.&lt;/p&gt;

&lt;p&gt;I would place Graphite as a good option for Node.js teams that already have strong PR discipline, want high-signal feedback on bugs, edge cases, security, and performance, and prefer to iterate quickly with custom prompts and exclusions.&lt;/p&gt;

&lt;p&gt;The limit, compared with Kodus, is that the approach seems more centered on the GitHub PR flow and less on turning the repository into the source of truth for deeper operational and architectural rules. For day-to-day review, it may be enough. For Node.js teams that want to encode expected behavior by folder, boundary, service type, or internal domain policy, Kodus tends to be more interesting.&lt;/p&gt;

&lt;h3&gt;CodeRabbit&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.14.36-1024x306.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F05%2FScreenshot-2026-05-04-at-13.14.36-1024x306.png" alt="Coderabbit" width="800" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/coderabbit-alternative/" id="https://kodus.io/en/coderabbit-alternative/" rel="noopener noreferrer"&gt;CodeRabbit&lt;/a&gt; sits in a good middle ground between broad coverage and convenience. It runs in PRs, IDE, and CLI, supports GitHub, GitLab, Bitbucket, and Azure DevOps, and detects guideline files like AGENTS.md, CLAUDE.md, and .cursorrules.&lt;/p&gt;

&lt;p&gt;For Node.js teams, this helps reduce the gap between “the rules the team wrote in markdown” and “what the automated reviewer actually enforces”. The tool also seems well thought out for catching problems before the PR, which is useful in Node.js stacks with a lot of service, route, and integration code, where a simple mistake can spread quickly.&lt;/p&gt;

&lt;p&gt;In practice, I see CodeRabbit as a good option for teams that want review across multiple surfaces and value the ability to use patterns that are already documented. It makes sense in Node.js when the goal is to increase review coverage without changing everything at once.&lt;/p&gt;

&lt;p&gt;I would still put Kodus ahead when the team wants more control over the workflow, more model freedom, an open source posture, and the ability to bring external context through MCP plugins. CodeRabbit helps a lot with review distributed across PR, IDE, and CLI. Kodus tends to fit better when review needs to reflect how that repository and that team actually work.&lt;/p&gt;

&lt;h2&gt;Comparison of code review tools for Node.js&lt;/h2&gt;

&lt;h2&gt;How I would introduce this process in a real team&lt;/h2&gt;

&lt;p&gt;I would start with a small checklist and a small set of rules. No blocking merges in the first month. No trying to automate every review habit at once. The goal at the beginning is to catch the problems the team already knows are expensive, then measure whether the feedback is actually useful.&lt;/p&gt;

&lt;p&gt;For a typical Node.js service, I would probably start with three rule areas: runtime validation at public boundaries, timeout requirements for external calls, and tests for new endpoints or queue consumers. That already covers a large part of the expensive errors teams see in production.&lt;/p&gt;

&lt;p&gt;After that, I would use real incidents to improve the checklist. If the team spends a day debugging a broken retry flow, a bad query, or a tenant isolation bug, that should become review knowledge. Good review systems get stronger because the team keeps feeding those systems with real failures, not because the checklist started big.&lt;/p&gt;

&lt;h2&gt;Frequently asked questions&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;How do you create a code review checklist for Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;A good Node.js code review checklist should be short and focused on the points that most often create production problems. Instead of trying to cover everything, it is worth starting with higher-risk areas, such as runtime validation, authorization, async flow, external calls, queries, dependency changes, and tests. The best checklist is not the longest one. It is the one that helps reviewers avoid missing points that really matter in almost every PR. As the team learns from real bugs and incidents, that checklist can evolve with the codebase.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;What should you review first in a Node.js code review?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Start with the points that most often break in production: runtime validation, authorization, async flow, external calls, queries, and dependency changes. In Node.js, a small PR can hide a route that trusts input too early, triggers unlimited concurrency, runs a heavy query, or calls an external service with no timeout.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;What is the best code review tool for Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;It depends on what the team needs. For quick adoption in the current PR flow, several tools can help. But if the team wants review with repository context, custom rules in natural language, external context through plugins, model choice, and more control over the workflow, Kodus is one of the most complete options for Node.js. This matters in codebases with routes, workers, queues, shared packages, and internal rules that do not show up just by looking at the diff.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Which AI code review tool is best for Node.js teams that need custom rules?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Kodus stands out here. Node.js teams often need rules that go beyond style, such as requiring runtime validation in public endpoints, checking tenant isolation, reviewing queue consumers with a focus on idempotency, or applying patterns by folder and service type. Kodus supports natural-language rules at the repository level, external context through plugins, and a model-agnostic flow, which gives the team more control.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Can AI code review catch async and promise problems in Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes. AI reviewers are often useful for missing &lt;code&gt;await&lt;/code&gt;, weak timeout handling, broad concurrency patterns, and other async errors that can slip through a quick manual review.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Does TypeScript reduce the need for code review in Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;TypeScript helps, but it does not replace code review. It catches many errors early and improves code structure, but it does not validate input at runtime, does not guarantee correct authorization, does not prevent event loop blocking, and does not make external integrations safe. In Node.js, many bugs appear exactly between the static type and the real behavior of the application.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Should package.json and lockfile changes be part of Node.js code review?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes. Dependency changes also need to be reviewed. A package upgrade can change installation, introduce security risk, change transitive dependencies, or create performance and maintenance cost. Reviewing only the application code and ignoring package.json or the lockfile lets too much risk through.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Should lockfile changes be part of code review in Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Yes. In Node.js, dependency and lockfile changes can affect security posture, installation behavior, and operational risk. They should be treated as part of the real review surface.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;How should a team start improving code review in Node.js?&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Start small. Use a short checklist, focus on the highest-risk areas, and add automation only where it clearly improves signal. A smaller review process the team actually follows is better than a perfect process nobody uses.&lt;/p&gt;

</description>
      <category>node</category>
      <category>codereview</category>
      <category>devex</category>
    </item>
    <item>
      <title>Open-source, model-agnostic alternative to Claude Code Review</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Tue, 10 Mar 2026 14:33:56 +0000</pubDate>
      <link>https://dev.to/ed_dfreitas/open-source-model-agnostic-alternative-to-claude-code-review-4021</link>
      <guid>https://dev.to/ed_dfreitas/open-source-model-agnostic-alternative-to-claude-code-review-4021</guid>
      <description>&lt;p&gt;Claude just launched code review and the announced price is $15–$25 per pull request. 🤯&lt;/p&gt;

&lt;p&gt;I got curious and decided to run a simple calculation.&lt;/p&gt;

&lt;p&gt;There are teams processing ~1,000 PRs per week.&lt;/p&gt;

&lt;p&gt;Nothing unusual for larger companies.&lt;/p&gt;

&lt;p&gt;If each review costs $25, that’s something close to $100k per month just for code review. 🫠&lt;/p&gt;

&lt;p&gt;Just to review PRs.&lt;/p&gt;

&lt;p&gt;Code review is a continuous activity. The more a team grows and the more code gets produced, the higher the volume of PRs.&lt;/p&gt;

&lt;p&gt;If the cost scales with the number of PRs, the financial impact can get pretty large pretty quickly.&lt;/p&gt;

&lt;p&gt;You can use Kodus, which is open source, run any model you want, and pay less than 1/10 of that.&lt;/p&gt;

&lt;p&gt;If you want to try it, you can get started right away.&lt;/p&gt;

&lt;p&gt;No credit card, no PR limits, no user limits, and no need to configure an API key.&lt;/p&gt;

&lt;p&gt;🔗 &lt;a href="https://kodus.io" rel="noopener noreferrer"&gt;https://kodus.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/kodustech/kodus-ai" rel="noopener noreferrer"&gt;https://github.com/kodustech/kodus-ai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
    <item>
      <title>I gathered more than 10,000 skills for AI agents in one place</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Wed, 28 Jan 2026 13:30:43 +0000</pubDate>
      <link>https://dev.to/ed_dfreitas/i-gathered-more-than-10000-skills-for-ai-agents-in-one-place-661</link>
      <guid>https://dev.to/ed_dfreitas/i-gathered-more-than-10000-skills-for-ai-agents-in-one-place-661</guid>
      <description>&lt;p&gt;Over the past few months, I’ve been spending a lot of time studying how AI agents are actually being built in practice.&lt;/p&gt;

&lt;p&gt;One thing became very clear: there’s a huge number of skills scattered all over the place, but everything is fragmented, hard to search, and even harder to reuse.&lt;/p&gt;

&lt;p&gt;So I decided to run an experiment:&lt;/p&gt;

&lt;p&gt;👉 a site with more than 10,000 agent skills, organized, searchable, and with direct links to each implementation.&lt;/p&gt;

&lt;p&gt;You can check it out here: &lt;a href="https://ai-skills.io/" rel="noopener noreferrer"&gt;https://ai-skills.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m still refining a few things and adding more skills, so I’d really love your feedback :)&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>resources</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Dealing with legacy code in modern applications</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Fri, 16 Jan 2026 12:01:00 +0000</pubDate>
      <link>https://dev.to/kodus/dealing-with-legacy-code-in-modern-applications-4052</link>
      <guid>https://dev.to/kodus/dealing-with-legacy-code-in-modern-applications-4052</guid>
      <description>&lt;p&gt;A new feature request lands, and you realize it has to touch the old permissions module. The project planning meeting suddenly gets very quiet because everyone knows any change in that part of the &lt;strong&gt;legacy code&lt;/strong&gt; means weeks of careful testing, unpredictable behavior, and a high-stakes deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fa-wise-senior-dev-once-said-dont-touch-the-legacy-code-base-v0-6tzcybbk052a1-1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fa-wise-senior-dev-once-said-dont-touch-the-legacy-code-base-v0-6tzcybbk052a1-1.webp" alt="" width="500" height="589"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the friction point where building new things slows to a crawl, constrained by decisions made years ago by people who are no longer on the team.&lt;/p&gt;

&lt;h2&gt;Beyond the "Rewrite or Refactor" Dichotomy&lt;/h2&gt;

&lt;p&gt;In these moments, someone will almost always suggest a full rewrite. It’s an appealing idea, a clean slate where all past mistakes are erased. The reality is that a &lt;a href="https://kodus.io/en/refactor-or-rewrite/" rel="noopener noreferrer"&gt;full rewrite&lt;/a&gt; is rarely a practical solution. It freezes the delivery of new business value for months or even years, introduces a massive amount of risk, and discards years of battle-tested logic that, for all its faults, currently runs the business. The code might be hard to read, but it contains valuable, implicit knowledge about edge cases you haven't even thought of yet.&lt;/p&gt;

&lt;p&gt;The alternative, incremental refactoring, works much better when treated as a continuous process instead of a standalone project. The goal is to evolve the system, not to achieve a perfect, idealized state. The most valuable code is often the oldest, and learning to work with it is a core engineering skill.&lt;/p&gt;

&lt;h3&gt;When legacy code becomes a real bottleneck&lt;/h3&gt;

&lt;p&gt;The term &lt;a href="https://kodus.io/en/managing-technical-debt-rapid-growth/" rel="noopener noreferrer"&gt;"technical debt"&lt;/a&gt; can be a bit abstract, but a bottleneck is painfully concrete. It’s the module that slows down every new feature. It's the source of recurring performance incidents or the component with a known security vulnerability that’s too entangled to patch easily. You know you've found a bottleneck when multiple teams have to coordinate for even minor changes, or when the operational overhead of keeping a service running outweighs the value it delivers.&lt;/p&gt;

&lt;p&gt;These are the areas that actively impede progress. Identifying them is the first step, because you can't fix everything at once, and trying to do so just leads to paralysis.&lt;/p&gt;

&lt;h2&gt;An Approach for Evolving Systems&lt;/h2&gt;

&lt;p&gt;The most effective approach is to stop thinking about "fixing everything" and instead focus on "strategically evolving" the system. Your job is to create pathways for new development while safely containing the old. Architectural patterns like the Strangler Fig are built on this idea: you gradually intercept traffic to an old system, route it to new services, and eventually, the old system is "strangled" out of existence without a high-risk cutover.&lt;/p&gt;

&lt;p&gt;This requires &lt;a href="https://kodus.io/en/technical-debt-prioritizing-features/" rel="noopener noreferrer"&gt;prioritizing changes&lt;/a&gt; based on a combination of business impact and technical risk. A part of the codebase might be messy, but if it’s stable and rarely changes, it's probably not where you should spend your time. Focus on the parts of the system that are both critical and under constant pressure to change.&lt;/p&gt;

&lt;h3&gt;Techniques for Managing the Boundaries&lt;/h3&gt;

&lt;p&gt;To evolve a system safely, you need to manage the boundaries between the old and new parts of your codebase. Here are a few practical techniques that work well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identify Seams and Interfaces:&lt;/strong&gt; First, you have to find the natural joints in the system. These are the points where you can intercept calls between components without rewriting either one. A seam could be an API call, a method invocation, or a message being passed to a queue. Once you find them, you can start to redirect behavior.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Isolate Functionality:&lt;/strong&gt; When you have a particularly problematic area, the goal is to contain it. You can write an adapter or an anti-corruption layer that sits between the old code and the rest of the application. This new layer translates requests and responses, hiding the complexity of the legacy component and providing a clean, modern interface for new code to interact with.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Write Characterization Tests:&lt;/strong&gt; You can't safely change code if you don't know what it does. Before you touch anything, write a suite of tests that document the current behavior, including its bugs. These "&lt;a href="https://kodus.io/en/how-to-write-software-test-cases/" rel="noopener noreferrer"&gt;characterization tests&lt;/a&gt;" don't judge the code; they just capture its existing state. When you make a change, you can run these tests to ensure you haven't broken an implicit assumption somewhere else in the system.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Implement Observability:&lt;/strong&gt; You need to see what the old components are doing in production. Adding detailed logging, metrics, and distributed tracing gives you the insight needed to understand runtime behavior. Without this, you're flying blind every time you deploy a change that touches the older code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;The Incremental Evolution Framework: Decide, Delimit, Develop&lt;/h2&gt;

&lt;h3&gt;1. Decide: Where is the real pain?&lt;/h3&gt;

&lt;p&gt;Your resources are finite, so prioritization is everything. The place to start is at the intersection of business value and frequency of change. Which part of the system is most often a blocker for important projects? Evaluate the impact of modernizing a component versus the effort required. Often, the highest-leverage targets are areas with high coupling or poor testability, because improving them unlocks velocity for multiple teams.&lt;/p&gt;

&lt;h3&gt;2. Delimit: How can we contain the change?&lt;/h3&gt;

&lt;p&gt;Once you've decided where to focus, the next step is to draw a boundary around the problem area. This is where architectural decisions come in. You might create a new microservice to house the new logic, using an API gateway or a message queue to bridge the gap between the old and new systems. The key is to create a clear interface that abstracts away the legacy implementation. The rest of the application shouldn't need to know whether it's talking to a 10-year-old monolith or a brand-new service.&lt;/p&gt;

&lt;h3&gt;3. Develop: Execute with small, well-tested iterations&lt;/h3&gt;

&lt;p&gt;With a clear boundary in place, you can start developing. New features that interact with the legacy code should be built using test-driven development to ensure the new logic and the integrations are correct. Small, incremental changes deployed via an automated pipeline give you the confidence to move quickly. Each pull request should be a small, verifiable step forward. Code reviews for this kind of work should be especially focused on the clarity and durability of the new interfaces you're creating.&lt;/p&gt;

&lt;h2&gt;Cultivating a Sustainable Relationship with Your Codebase&lt;/h2&gt;

&lt;p&gt;Working with legacy systems isn't a one-off project with a defined end. It's a continuous process of improvement. The most effective &lt;a href="https://kodus.io/en/scaling-engineering-culture-systems/" rel="noopener noreferrer"&gt;teams build a culture&lt;/a&gt; that values this incremental work, not just reactive fixes when something breaks. This means investing in developer tools and practices that support safe, small changes and make refactoring a low-ceremony activity.&lt;/p&gt;

&lt;p&gt;Ultimately, "modern" is a moving target. The shiny new service you build today will be somebody else's legacy code in five years. The real skill is learning to manage complexity as an ongoing practice, ensuring the codebase you have is one that allows you to keep building, testing, and delivering value.&lt;/p&gt;

</description>
      <category>legacy</category>
    </item>
    <item>
      <title>How to structure technical planning for engineering</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Fri, 16 Jan 2026 10:57:00 +0000</pubDate>
      <link>https://dev.to/kodus/how-to-structure-technical-planning-for-engineering-1h1n</link>
      <guid>https://dev.to/kodus/how-to-structure-technical-planning-for-engineering-1h1n</guid>
      <description>&lt;p&gt;In a fast-growing company, the default state of engineering is reactive. The product roadmap is packed, deadlines are tight, and the team is constantly switching context to put out the fire of the moment. This environment makes any kind of intentional &lt;strong&gt;technical planning&lt;/strong&gt; feel like a luxury you can’t afford, so most teams don’t even try. You end up stuck shipping features, fixing bugs, and hoping core systems don’t fall apart, while &lt;a href="https://kodus.io/en/managing-technical-debt-rapid-growth/" rel="noopener noreferrer"&gt;technical debt&lt;/a&gt; quietly piles up in the background.&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2F0_3rGgPkCs0m3m-ZzJ-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2F0_3rGgPkCs0m3m-ZzJ-1.jpg" alt="" width="800" height="870"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;This “just build” approach looks productive in the short term, but it comes with a real and cumulative cost. Before long, you notice engineers on different teams solving the same scaling problem in different ways. A simple feature request now requires changes across five services, each with its own quirks. The speed you were so proud of six months ago starts to drop, and no one can point to a single clear reason why. This is the slow accumulation of uncoordinated decisions.&lt;/p&gt;

&lt;h2&gt;Technical planning for unstable environments&lt;/h2&gt;

&lt;p&gt;Breaking out of this reactive cycle requires a shift in how we think about planning. Most frameworks are too rigid for a company where priorities can change in a week. A detailed two-year technical roadmap is useless if it becomes obsolete a month after it’s written.&lt;/p&gt;

&lt;p&gt;The goal is adaptability, not prediction. It’s about creating shared understanding around technical direction so that, when engineers make local decisions, they align with a broader direction. That forward-looking view is what allows a team to handle change without breaking everything. It turns planning from a bureaucratic obstacle into an accelerator, because you stop wasting time on duplicated work and architectural dead ends. Understanding the real cost of uncontrolled growth is the first step; it shows up as longer onboarding times, higher bug rates in critical modules, and a general sense of friction when trying to build anything new.&lt;/p&gt;

&lt;h2&gt;A practical and adaptable model for technical planning&lt;/h2&gt;

&lt;p&gt;A good technical plan doesn’t live in a dense document no one reads. It’s a living guide that connects engineering work directly to what the business is trying to achieve. It needs to be flexible enough to change quickly, but structured enough to provide real direction.&lt;/p&gt;

&lt;h3&gt;Define your North Star ⭐️&lt;/h3&gt;

&lt;p&gt;Every meaningful technical initiative should be traceable back to a business goal. This isn’t about pleasing stakeholders; it’s about making sure you’re solving the right problems. When the company decides to move upmarket and serve enterprise customers, that translates into very specific technical requirements, like more robust permissions, audit logs, and integrations with common identity providers.&lt;/p&gt;

&lt;p&gt;Framing the work this way pulls the conversation out of the abstract and into concrete outcomes. Discussions that used to sound like “we need to refactor the authentication service” become directly tied to clear business goals, like closing enterprise customers in Q3, which requires supporting SAML and role-based access control. The reason behind the work becomes clear, and the engineering team understands why it matters, not just what needs to be done.&lt;/p&gt;

&lt;h3&gt;Building the “What”: Scope and Outcomes&lt;/h3&gt;

&lt;p&gt;With a clear “why,” prioritization becomes much simpler. You can evaluate technical work side by side with product features based on impact to company goals. A large refactor might not deliver immediate, visible value to users, but if it unlocks the ability to iterate 50% faster in a core part of the product over the next year, the value is obvious.&lt;/p&gt;

&lt;p&gt;This is also where you make conscious trade-offs. You might decide to accept some technical debt in a non-critical area to free up resources and fix a serious scalability bottleneck that’s threatening user growth. The key point is to make these decisions explicitly, instead of letting them happen by accident. When defining scope, the goal is to design for what you know is coming, not every possible future. Build with extensibility where you anticipate change, but avoid overengineering based purely on speculation.&lt;/p&gt;

&lt;h3&gt;The “How”: Planning and Execution&lt;/h3&gt;

&lt;p&gt;Execution needs to happen within the workflow the team already has. When parallel processes or extra ceremonies appear, they tend to be ignored as soon as pressure ramps up.&lt;/p&gt;

&lt;p&gt;Here are a few practices that work well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Architectural Decision Records (ADRs).&lt;/strong&gt; A simple markdown file in the right repository is enough. This is where decisions are recorded, along with the alternatives considered and the reasoning behind the final choice. That context ends up being valuable both for new team members and for your future self.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Involve senior engineers early in the design phase.&lt;/strong&gt; &lt;a href="https://kodus.io/en/how-small-pull-requests-improve-team-flow/" rel="noopener noreferrer"&gt;Don’t wait for a 5,000-line pull request&lt;/a&gt; to show up. Have conversations about the “how” before implementation starts. That might be a short design doc, a whiteboard discussion, or even a dedicated chat channel. This helps spread knowledge and catch architectural issues while they’re still cheap to fix.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Create regular review and adaptation cycles.&lt;/strong&gt; A technical plan isn’t static. Review it quarterly. What changed in the business? What did we learn from the last quarter’s work? Adjust priorities based on new information. This helps keep the plan relevant and useful.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Turning Technical Planning into an Advantage&lt;/h2&gt;

&lt;p&gt;Introducing this process doesn’t require a company-wide initiative. You can start small, with a single team or a critical system. Pick an area of the codebase that’s a known source of pain and build a clear plan to improve it, directly connecting the effort to a product or business outcome.&lt;/p&gt;

&lt;p&gt;At the end of the day, it’s about &lt;a href="https://kodus.io/en/scaling-engineering-culture-systems/" rel="noopener noreferrer"&gt;fostering an engineering culture&lt;/a&gt; where everyone feels responsible for the health of the system. When engineers understand the “why” behind the work and see a clear path to &lt;a href="https://kodus.io/en/evolving-code-standards-scaling-teams/" rel="noopener noreferrer"&gt;improving the codebase&lt;/a&gt;, they’re more engaged. You can measure the impact directly through improved development velocity, system stability, and, most importantly, the ability to respond to new business opportunities without having to rebuild everything from scratch.&lt;/p&gt;

</description>
      <category>management</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How Small Pull Requests Improve Team Flow</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Thu, 15 Jan 2026 14:05:08 +0000</pubDate>
      <link>https://dev.to/kodus/how-small-pull-requests-improve-team-flow-3gml</link>
      <guid>https://dev.to/kodus/how-small-pull-requests-improve-team-flow-3gml</guid>
      <description>&lt;p&gt;A 2,000-line Pull Request lands in your &lt;a href="https://kodus.io/en/scaling-code-review-teams" rel="noopener noreferrer"&gt;review queue&lt;/a&gt; on a Thursday afternoon, touching a dozen files spread across three different parts of the application. Everyone knows what happens next. You either give it an LGTM while hoping for the best, or you block two hours of your day, completely breaking your own flow, just to understand the changes.&lt;/p&gt;

&lt;p&gt;This is not an exception, it is usually routine for the team. Large PRs slow the team down, increase the risk of errors slipping through, and make the &lt;a href="https://kodus.io/en/how-to-improve-software-delivery-speed/" rel="noopener noreferrer"&gt;delivery cycle less predictable&lt;/a&gt;. The problem is not just the code inside the PR, it is the time it ties up people, decisions, and deploys throughout the entire process.&lt;/p&gt;

&lt;h2&gt;The weight of large changes&lt;/h2&gt;

&lt;p&gt;Large pull requests create bottlenecks that spill outward. The most immediate impact falls on the reviewer, who &lt;a href="https://kodus.io/en/context-switching-is-hurting-your-engineering-team/" rel="noopener noreferrer"&gt;now faces massive context switching&lt;/a&gt;. A change of this size requires not only reading the code, but reconstructing the entire mental model of the person who wrote it. This cognitive load makes it tempting to postpone the review, leaving the PR sitting idle for days while the author’s own context starts to fade. When the review finally happens, the feedback is usually less detailed, because the reviewer is just trying to understand the architecture at a high level instead of identifying logic flaws.&lt;/p&gt;

&lt;p&gt;This delay creates cascading effects. While the large PR waits for review, the &lt;code&gt;main&lt;/code&gt; branch keeps moving forward, making merge conflicts almost inevitable. The longer a branch stays open, the more it diverges and the harder final integration becomes. Dependent work gets blocked, and if a fundamental design issue is found during this late review, the rework cost is huge. A problem discovered days after the code was written is much more expensive to fix than one caught in minutes. The entire process slows down, and the team’s predictability suffers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2025%2F01%2Fhpaef0nwm8d11-928x1024.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2025%2F01%2Fhpaef0nwm8d11-928x1024.webp" alt="" width="800" height="882"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Why small PRs make a difference in the team’s process&lt;/h2&gt;

&lt;p&gt;Moving to smaller, more frequent pull requests tackles these bottlenecks directly. When a review is limited to something around a hundred lines, it can be done in minutes, often between other tasks, without a major context switch. The cognitive load is low, which encourages reviewers to engage quickly and provide &lt;a href="https://kodus.io/en/pull-request-feedback-high-performing-teams/" rel="noopener noreferrer"&gt;more focused and constructive feedback&lt;/a&gt;. The author gets this feedback while the code is still fresh in their mind, allowing for fast iterations. This creates a short cycle of coding, review, and integration that keeps work flowing continuously.&lt;/p&gt;

&lt;p&gt;The benefits compound over time. Small, incremental changes are easier to validate and, if needed, to roll back. The blast radius of any potential issue stays contained within a small, understandable unit of work. Instead of a monolithic, high-risk merge once a week, you end up with a steady flow of low-risk changes reaching production every day. This continuous progress is great for team morale and makes it easier to course-correct if a feature is heading in the wrong direction. The team moves from a batch-processing model to a real-time flow.&lt;/p&gt;

&lt;h2&gt;Main reasons to do small PRs&lt;/h2&gt;

&lt;h3&gt;1. &lt;strong&gt;Faster and more accurate reviews&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When the scope of a Pull Request is small, the reviewer can focus on the details that really matter. This not only speeds up the review but also increases the quality of the feedback. Issues are detected earlier and with greater clarity.&lt;/p&gt;

&lt;h3&gt;2. &lt;strong&gt;Faster feedback&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Smaller PRs make life easier for everyone. Reviewers can respond more quickly, and those waiting for feedback can move forward with less idle time. This speed is essential to keeping productivity high.&lt;/p&gt;

&lt;h3&gt;3. &lt;strong&gt;Reduced conflicts&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Each small PR is processed quickly, which reduces the chances of conflicts with other code changes. That means less rework and more focus on what really matters: creating value for the product.&lt;/p&gt;

&lt;h3&gt;4. &lt;strong&gt;Clearer intent&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When you limit the scope of a PR, it becomes much easier for everyone to understand what is being solved. This not only improves communication within the team, but also makes the project history more organized and traceable.&lt;/p&gt;

&lt;h3&gt;5. &lt;strong&gt;Higher deploy frequency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With small Pull Requests, it becomes possible to do smaller, more frequent deploys. That means features and fixes reach users faster, while the risk of something breaking in production goes down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read also:&lt;/strong&gt;&lt;a href="https://kodus.io/melhorando-qualidade-pull-requests/" rel="noopener noreferrer"&gt; How to improve PR quality&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;Building a culture of small Pull Requests&lt;/h2&gt;

&lt;h3&gt;&lt;strong&gt;Breaking work into smaller parts&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;It is not enough to tell people “make smaller PRs”. You need to offer techniques for slicing work into independent, mergeable pieces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement feature toggles for incomplete functionality. This is the most powerful tool for decoupling deploy from release. It allows incremental merging of the code for a larger feature, even when it is not yet ready for users. Each part can be reviewed and tested in isolation behind a flag.&lt;/li&gt;



&lt;li&gt;Prioritize refactoring as a distinct, isolated change. Avoid mixing &lt;a href="https://kodus.io/en/reduce-technical-debt" rel="noopener noreferrer"&gt;refactoring&lt;/a&gt; with feature delivery in the same PR. When a change only touches structure, it is much easier to review. When it mixes code reorganization with new behavior, the review becomes confusing and risky. Clean up first, merge it, and only then build the feature on top of a clearer base.&lt;/li&gt;



&lt;li&gt;Slice user stories vertically into minimal viable increments. Instead of building an entire feature horizontally (backend, then frontend, then API), find the smallest possible vertical slice that delivers a bit of value to the user. Maybe the first PR only adds the API endpoint with a hardcoded response. The next adds the database schema. The following one connects the two. Each step is a small, verifiable improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Team agreements and practices for Pull Requests&lt;/h3&gt;

&lt;p&gt;Consistency comes from shared expectations. The team needs to have explicit conversations about what a “good” PR looks like.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set guidelines for acceptable size and complexity. Some teams use lines of code as a rough proxy (for example, under 250 lines), while others look at the number of files touched or the conceptual weight of the change. The exact number matters less than having a shared understanding.&lt;/li&gt;



&lt;li&gt;Define clear expectations for review turnaround times. Agree on a target response time for reviews, such as a few business hours. This prevents PRs from being forgotten in the queue and signals that reviewing is a priority responsibility for everyone on the team.&lt;/li&gt;



&lt;li&gt;Use tools to identify and flag exceptionally large Pull Requests. Many CI/CD platforms and Git tools can be configured to automatically mark PRs that exceed a certain size threshold. This works as a gentle, automatic reminder of team agreements, without making the conversation confrontational.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Measuring the impact on delivery flow&lt;/h2&gt;

&lt;p&gt;To know whether the change is working, you need to measure. &lt;a href="https://kodus.io/en/engineering-metrics-data-driven-improvement/" rel="noopener noreferrer"&gt;Adding flow metrics&lt;/a&gt; can provide clear evidence of improvement and help justify the investment in this practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Track Lead Time for Changes.&lt;/strong&gt; This metric measures the time between the first commit on a branch and the code running in production. Smaller PRs tend to reduce this number directly by shortening review and integration stages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Monitor Code Review Cycle Time.&lt;/strong&gt; How long does a PR sit waiting for review or iteration? This metric helps surface process bottlenecks and should drop as PRs get smaller and more focused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch for a reduction in merge conflict frequency and defect rates.&lt;/strong&gt; With shorter branches and smaller changes, conflicts tend to decrease. The faster feedback cycle also helps catch bugs earlier, reducing the rate of defects that get reintroduced or make it to production.&lt;/p&gt;

&lt;h2&gt;At the end of the day&lt;/h2&gt;

&lt;p&gt;Creating smaller PRs is about building a more efficient and sustainable workflow. It is not something that happens overnight, but over time these practices become part of the team’s culture and make all the difference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2025%2F01%2Fahfu67.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2025%2F01%2Fahfu67.jpg" alt="" width="577" height="433"&gt;&lt;/a&gt;&lt;/p&gt;



</description>
      <category>codequality</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Code Standards and Best Practices for Growing Teams</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Thu, 15 Jan 2026 10:55:00 +0000</pubDate>
      <link>https://dev.to/kodus/code-standards-and-best-practices-for-growing-teams-l4g</link>
      <guid>https://dev.to/kodus/code-standards-and-best-practices-for-growing-teams-l4g</guid>
      <description>&lt;p&gt;When an engineering team is small, informal agreements tend to work just fine. There’s a shared understanding of how things should be built, because any disagreement can be quickly resolved in a Slack thread or a conversation. But as the team grows from five to fifty developers, these unwritten rules start to cause problems. Suddenly, you find yourself in pull request comments debating brace placement, naming conventions, and which async pattern to use, for the third time in the same week. That’s when the need for explicit &lt;strong&gt;code standards&lt;/strong&gt; becomes painfully obvious.&lt;/p&gt;

&lt;p&gt;The friction isn’t limited to PRs. It also shows up in the cost of context switching, when each microservice has its own rules for errors and configuration, for example. A developer from the checkout team trying to fix a bug in the inventory service first has to spend an hour just understanding the local conventions, before even starting to debug. This fragmentation slows down collaboration and makes the entire system harder to understand. If teams can’t even agree on something basic, like a branching strategy or commit message format, you lose the ability to automate release notes or reliably track changes across services.&lt;/p&gt;

&lt;h2&gt;Code standards as a foundation for shared context&lt;/h2&gt;

&lt;p&gt;The most common reaction to this chaos is to impose a top-down set of rules. An architecture group might write a very comprehensive document dictating everything from file structure to design patterns. This approach almost always creates more problems. It feels bureaucratic, and developers, who are paid to solve problems, will naturally work around any rule that gets in the way without delivering clear value. The goal isn’t to impose dogma, but to build a shared understanding that reduces cognitive load.&lt;/p&gt;

&lt;p&gt;Code standards exist to get trivial decisions out of the way, allowing the team to focus its energy on the real business problem. When they work well, they provide default answers to common questions and clear the path for what actually matters. This is the balance between &lt;a href="https://kodus.io/en/speed-code-quality-startups/" rel="noopener noreferrer"&gt;moving fast now and building a system that remains sustainable for years&lt;/a&gt;. The decision to skip writing tests might speed up the release of a feature by a day, but the long-term cost of that missing context and safety net will be paid with interest during the next production incident or refactor.&lt;/p&gt;

&lt;h3&gt;The real purpose is to reduce cognitive load&lt;/h3&gt;

&lt;p&gt;Think about the decisions an engineer makes every day. Many of them are repetitive: how should I format this file? What should I name this component? How should I structure API error responses? Good standards provide a single answer, automated or well documented, to these questions. For example, an agreed-upon JSON structure for logs, like &lt;code&gt;{"level": "error", "timestamp": "...", "service": "auth-api", "message": "..."}&lt;/code&gt;, means everyone can query and filter logs across the platform using the same tools and techniques, without having to learn the logging quirks of each service.&lt;/p&gt;

&lt;h2&gt;How to keep code standards adaptable over time&lt;/h2&gt;

&lt;p&gt;Good code standards are the ones that can evolve over time. They need to be grounded in principles, not rigid rules, and make sense to the people writing code every day. The focus is on making collaboration easier and maintaining &lt;a href="https://kodus.io/en/code-quality-standards-and-best-practices/" rel="noopener noreferrer"&gt;quality&lt;/a&gt;, without getting in the way of flow.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fcoding_standard-1-1024x576.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fcoding_standard-1-1024x576.jpg" alt="code standards" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Defining core principles, not rigid rules&lt;/h3&gt;

&lt;p&gt;Instead of a hundred-page document, start with a small set of principles that are easy to remember and apply. Some good examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus on clarity and intent.&lt;/strong&gt; Code should be written to be understood by everyone first. A variable name like &lt;code&gt;customerData&lt;/code&gt; is too vague, but &lt;code&gt;activePayingCustomers&lt;/code&gt; clearly communicates intent. This isn’t something a linter can always catch, which makes it a great topic for discussion during code review.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Promote consistency where it matters most.&lt;/strong&gt; Be opinionated about what truly affects collaboration across teams, such as API design, security standards, and the use of core libraries. The style of a private function inside a single module matters much less.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Automate some processes to sustain standards over time &lt;a href="https://kodus.io/en/ai-code-review-tools/" rel="noopener noreferrer"&gt; like code review &lt;/a&gt;.&lt;/strong&gt; People’s time is too valuable to be spent debating formatting or standards everyone should already be following. Automating this makes life easier for everyone, especially when new people are joining the team.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;The “balance zone”&lt;/h3&gt;

&lt;p&gt;There’s always a point of balance. Every new standard adds a bit of friction, so it’s worth asking whether it really improves day-to-day clarity and consistency.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Too little:&lt;/strong&gt; Leads to a chaotic codebase, where every file feels like it was written by a different team. This is where &lt;a href="https://kodus.io/en/managing-technical-debt-rapid-growth/" rel="noopener noreferrer"&gt;technical debt&lt;/a&gt; piles up through duplicated logic and inconsistent patterns.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Too much:&lt;/strong&gt; Creates an overly rigid environment that stifles the team and innovation. If engineers have to fight the tools or fill out a form just to try a new library, they’ll stop experimenting. Standards become a source of frustration for the people building.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Just right:&lt;/strong&gt;Defines a default path for most cases, while still leaving room for exceptions when they make sense. Consistency where it matters helps collaboration, and flexibility everywhere else gives the team space to innovate.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Some strategies you can try&lt;/h3&gt;

&lt;p&gt;Putting standards into practice requires more than just writing them down. You need to integrate them into the daily workflow and create a mechanism for them to evolve.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Define a default path for common tasks.&lt;/strong&gt; Build tools that make doing the right thing the easiest path. A CLI command like &lt;code&gt;platform-cli create-service&lt;/code&gt;, which scaffolds a new project with the correct CI/CD pipelines, logging libraries, and lint configs already set up, is far more effective than a wiki page.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Make standards a team responsibility.&lt;/strong&gt; Create a space to discuss and update standards, such as an engineering guild or a dedicated Slack channel. Changes to standards should be proposed and discussed via pull requests in a shared repository, just like any other code change. This increases team buy-in and helps keep standards up to date.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Implement a feedback loop for refinement.&lt;/strong&gt; Standards aren’t immutable. The team should regularly ask itself, “Is this rule still helping us, or is it getting in the way?”. If a specific lint rule is constantly being ignored, it might be a sign that the problem is with the rule, not the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Integrating best practices into the workflow&lt;/h3&gt;

&lt;p&gt;In the end, the best standards become part of the team’s daily routine. They’re simply part of how things are done, without adding another checklist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kodus.io/en/scaling-code-review-teams/" rel="noopener noreferrer"&gt;Code reviews&lt;/a&gt; become learning opportunities, where a senior engineer can point to documentation that explains the rationale behind a particular standard. Documenting the &lt;em&gt;why&lt;/em&gt; behind a decision in an ADR gives future engineers the context they need to make better decisions. This creates a virtuous cycle in which standards help simplify onboarding for new team members, who in turn learn the conventions and help maintain them, making the entire engineering organization more cohesive and effective as it grows.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>productivity</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>The challenge of managing multiple projects as a Tech Lead</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Wed, 14 Jan 2026 13:52:36 +0000</pubDate>
      <link>https://dev.to/kodus/the-challenge-of-managing-multiple-projects-as-a-tech-lead-2i5p</link>
      <guid>https://dev.to/kodus/the-challenge-of-managing-multiple-projects-as-a-tech-lead-2i5p</guid>
      <description>&lt;p&gt;Your scope as a Tech Lead almost never stays confined to a single, clean workstream. As a product grows, you end up responsible for a new feature initiative, a critical infrastructure migration, and a lingering performance issue, all at the same time. This isn't a promotion; it's an expansion of responsibility that quietly creeps in until you find yourself spread across three different stand-ups, answering questions about domains you haven't had time to think deeply about in weeks.&lt;/p&gt;

&lt;p&gt;The immediate result is a huge spike in cognitive load. You’re holding multiple complex system diagrams in your head, trying to recall the specifics of a data model for one project while a stakeholder from another is pinging you about their timeline. The pressure to keep all the plates spinning forces a reactive mode of operation, where multitasking feels like the only option, even though we all know the &lt;a href="https://kodus.io/en/context-switching-is-hurting-your-engineering-team/" rel="noopener noreferrer"&gt;heavy penalty of constant context switching. &lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;The Systemic Challenges of Capacity and Focus&lt;/h2&gt;

&lt;p&gt;When everything feels slow despite everyone being busy, it’s tempting to look for individual productivity hacks or better time management techniques. But the root cause is usually systemic. The problem isn't how you manage your calendar; it's that the system is overloaded, and the assumptions about team capacity are fundamentally broken.&lt;/p&gt;

&lt;h3&gt;Resource Allocation&lt;/h3&gt;

&lt;p&gt;Most planning starts with an optimistic view of team bandwidth. We map out projects as if they will be worked on in isolation, with developers dedicating 100% of their focus. In reality, that focus is fragmented. A developer assigned to Project A still gets pulled into on-call rotations, bug fixes from their previous work on Project B, and code reviews for Project C. The actual available bandwidth is much lower than what the roadmap assumes, and this mismatch creates a cycle of missed deadlines and rushed work. Output doesn't just degrade linearly under these conditions; it falls off a cliff once the team hits a certain threshold of cognitive overload and fragmentation.&lt;/p&gt;

&lt;h3&gt;The Productivity Drain of Constant Context Switching&lt;/h3&gt;

&lt;p&gt;Every time an engineer has to switch from thinking about a Kubernetes operator configuration to a complex SQL query for a different project, there's a significant mental cost. The context from the first task gets flushed, and it takes time to load the new one. When a team is responsible for multiple unrelated projects, these switches happen all day long. Interruptions from different Slack channels, competing stakeholder requests, and unexpected bugs from various domains create a constant churn that destroys any chance for deep work. As a leader, one of your most important jobs becomes creating an environment that actively protects focused time, which is nearly impossible when the team's mandate is too broad.&lt;/p&gt;

&lt;h3&gt;Dealing with competing priorities&lt;/h3&gt;

&lt;p&gt;Without a clear framework for prioritization, the "annoying" stakeholder often wins. This leads to a reactive cycle where the team bounces between strategic initiatives, urgent customer requests, and critical maintenance. The most difficult part is advocating for the invisible work, like &lt;a href="https://kodus.io/en/managing-technical-debt-rapid-growth/" rel="noopener noreferrer"&gt;paying down technical debt&lt;/a&gt; or refactoring a brittle module. These tasks have no external stakeholder championing them, but neglecting them guarantees that all future projects will be slower and more painful. Your role shifts from technical guidance to making a business case for technical health, &lt;a href="https://kodus.io/en/technical-debt-prioritizing-features/" rel="noopener noreferrer"&gt;connecting a refactor today with the ability to deliver a key feature next quarter&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;The Compounding Effects on Quality and Team Health&lt;/h2&gt;

&lt;p&gt;A perpetually overloaded system doesn't just move slower; it starts to break down in predictable ways. The small compromises made to keep things moving accumulate, affecting the codebase, the architecture, and the team itself.&lt;/p&gt;

&lt;h3&gt;Cross-Project Dependencies and Unforeseen Bottlenecks&lt;/h3&gt;

&lt;p&gt;When you're managing separate projects, it’s easy to miss the subtle ways they connect. A delay in one team's API development can completely block another team's frontend work. These dependencies are often unmapped, living only in people's heads until something goes wrong. A single person who is the sole expert on a legacy service becomes a bottleneck for three different initiatives. The only way to manage this is to stop viewing projects as independent &lt;a href="https://kodus.io/en/silo-busting-knowledge-flow-engineering-teams/" rel="noopener noreferrer"&gt;silos&lt;/a&gt; and start mapping them as an interconnected system, proactively identifying and tracking the dependencies between them.&lt;/p&gt;

&lt;h3&gt;The weight of accumulating technical debt&lt;/h3&gt;

&lt;p&gt;In a multi-project environment, "cutting corners" becomes a rational survival strategy. When faced with a tight deadline for one project and an urgent request from another, it’s almost always easier to write the quick hack than to do the "right" thing. Each of these small decisions adds up, and the accumulated technical debt acts as a drag on all future development. Simple changes start requiring complex workarounds, and the team's velocity slows down. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fimage1-1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkodus.io%2Fwp-content%2Fuploads%2F2026%2F01%2Fimage1-1.gif" alt="" width="900" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;Preserving Team Morale and Preventing Burnout&lt;/h3&gt;

&lt;p&gt;The human cost of chronic overload is severe. Engineers become demoralized when they can't take pride in their work because they're always rushing. Unclear priorities and constantly shifting goals create a sense of chaos, leading to frustration and burnout. Adding more pressure never accelerates delivery in these situations; it only accelerates attrition. As a leader, your most critical responsibility is to model &lt;a href="https://kodus.io/en/scaling-engineering-culture-systems/" rel="noopener noreferrer"&gt;sustainable work practices&lt;/a&gt; and be the person who protects the team from unrealistic expectations. This often means saying no, which is one of the hardest but most necessary parts of the job.&lt;/p&gt;

&lt;h2&gt;Some frameworks Tech Leads can use to manage multiple projects&lt;/h2&gt;

&lt;p&gt;Getting out of this reactive trap requires moving from simply managing projects to actively shaping the environment. This involves establishing a few frameworks that bring clarity, distribute responsibility, and create more sustainable workflows in both the short and long term.&lt;/p&gt;

&lt;h3&gt;Shifting from Project Management to Portfolio Optimization&lt;/h3&gt;

&lt;p&gt;Instead of treating projects as a checklist to be completed, view them as a portfolio of investments. This means thinking about how they relate to each other.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cross-project prioritization:&lt;/strong&gt; Is it possible to organize projects so that the learnings or capabilities built in the first one directly benefit the second? For example, building a new authentication library for one project that can then be used by two others.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Resource Constraints:&lt;/strong&gt; Identify cross-project constraints early. If you only have one database expert and three projects need database work, that needs to be factored into the timeline for all three. Don't pretend you can do them in parallel.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Holistic View:&lt;/strong&gt; Use tools like a multi-project Kanban board to visualize all work in one place. This makes the competing demands visible to everyone, including stakeholders, and forces a more realistic conversation about what's possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Who decides what (and why)&lt;/h3&gt;

&lt;p&gt;A Tech Lead who is the bottleneck for every decision is a system failure. The goal is to push decision-making down to the people with the most context. Define who owns what. For example, a sub-team might own the architectural decisions for their set of microservices, while a chapter lead owns the standards for frontend development. This moves the team from endless debate to clear accountability. Empowering team members with defined boundaries of ownership not only speeds things up but also develops their skills and sense of responsibility.&lt;/p&gt;

&lt;h3&gt;Distributing decisions and responsibility&lt;/h3&gt;

&lt;p&gt;Delegation isn't just about offloading tasks; it's a core strategy for managing workload and growing your team. When you delegate a piece of a project, you're also delegating the responsibility and authority that comes with it. This means providing clear expectations and the necessary support, but then trusting your team to execute without micromanagement. Doing this effectively frees you up to focus on the higher-level concerns that only you can handle, like cross-team alignment, architectural strategy, and stakeholder negotiations.&lt;/p&gt;

&lt;h3&gt;Building a culture of communication&lt;/h3&gt;

&lt;p&gt;When multiple workstreams are in flight, communication needs to be solid to avoid turning into chaos. That’s why you need to design clear protocols to manage the flow of information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent rhythms:&lt;/strong&gt; Create regular, lightweight mechanisms, like a shared weekly update document or a short demo. This keeps everyone aligned without adding a meeting overload.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Shared Sources of Truth:&lt;/strong&gt; Use dashboards or shared project boards that pull information directly from your ticketing system. This provides real-time visibility and prevents stakeholders from having to ask you for status updates constantly.&lt;/li&gt;



&lt;li&gt;
&lt;strong&gt;Minimize Interruptions:&lt;/strong&gt; Establish clear channels for communication. For example, use a specific Slack channel for urgent operational issues and direct all feature requests and planning questions to your ticketing system. This helps protect the team's focus.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These frameworks are a good starting point because they force conversations that usually stay implicit: what’s at stake, what depends on what, who decides what, and what actually fits into the same quarter. That takes weight off your shoulders and reduces the need to be involved in everything.&lt;/p&gt;

</description>
      <category>career</category>
      <category>leadership</category>
      <category>management</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Refactor or Rewrite? Dealing With Code That’s Grown Too Large</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Sat, 10 Jan 2026 09:11:00 +0000</pubDate>
      <link>https://dev.to/kodus/refactor-or-rewrite-dealing-with-code-thats-grown-too-large-2cm</link>
      <guid>https://dev.to/kodus/refactor-or-rewrite-dealing-with-code-thats-grown-too-large-2cm</guid>
      <description>&lt;p&gt;The decision to &lt;strong&gt;refactor or rewrite&lt;/strong&gt; a large codebase usually starts with a feeling of friction. Small changes that should take a day suddenly take a week. Every new feature seems to break an old one, and the team’s bug backlog grows faster than it shrinks.&lt;/p&gt;

&lt;p&gt;This happens because systems don’t just age, they accumulate history. Every feature request, urgent fix, and change in direction adds another layer of code. Over time, what was once a clean architecture turns into a web of dependencies and workarounds. The pressure to ship new features means there’s rarely time to go back and clean things up, so &lt;a href="https://kodus.io/en/managing-technical-debt-rapid-growth/" rel="noopener noreferrer"&gt;technical debt&lt;/a&gt; piles up. When you reach this point, the system starts actively resisting change, and every pull request becomes a painful negotiation with the past.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;Signs the system is at its limit&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;It’s easy to complain about a codebase, but there are clear signs that a system is close to breaking. The most obvious one is a steady drop in development speed. You can measure this with &lt;a href="https://kodus.io/en/optimizing-pr-cycle-time/" rel="noopener noreferrer"&gt;cycle time&lt;/a&gt; or, more simply, by comparing how long it takes to ship a basic feature today versus a year ago.&lt;/p&gt;

&lt;p&gt;Another clear sign is an increase in regressions in specific parts of the system. When fixing one bug almost always creates another, it usually points to an architecture that’s too tightly coupled, where small changes have side effects that are hard to predict.&lt;/p&gt;

&lt;p&gt;There are also human costs. When engineers spend more time fighting the system’s limitations than building with it, motivation drops fast. Onboarding new people becomes hard because the cognitive load required to understand the system is huge. And when your most experienced engineers start asking to work on anything else, or you struggle to hire because no one wants to touch the “legacy” stack, that’s usually a sign the system has reached a critical point.&lt;/p&gt;

&lt;h2&gt;Accidental complexity vs. essential complexity&lt;/h2&gt;

&lt;p&gt;Before making a good decision, you need to understand what kind of complexity you’re actually dealing with. Software complexity usually falls into two groups: essential and accidental.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essential complexity&lt;/strong&gt; is inherent to the business problem you’re solving. If you’re building a payment processing system, you have to deal with regulations, fraud detection, and multiple payment gateways. No matter how clean the code is, that complexity doesn’t go away. The best you can do is keep it under control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accidental complexity&lt;/strong&gt;, on the other hand, comes from the choices we’ve made along the way. It’s the result of outdated libraries, &lt;a href="https://kodus.io/en/code-smells/" rel="noopener noreferrer"&gt;poorly designed abstractions, inconsistent patterns, or quick fixes&lt;/a&gt; that were never revisited. This is the complexity that makes code hard to read, test, and change, even when the business logic itself is simple.&lt;/p&gt;

&lt;h3&gt;Why this distinction is everything&lt;/h3&gt;

&lt;p&gt;This distinction is the most important factor in the refactor versus rewrite debate.&lt;/p&gt;

&lt;p&gt;Refactoring is an excellent tool for attacking accidental complexity. It helps improve abstractions, simplify parts of the system that no longer make sense, and make the codebase more consistent, which makes day-to-day work easier. If your problem is mostly accidental complexity, a series of targeted refactorings is almost always the right answer.&lt;/p&gt;

&lt;p&gt;A full rewrite, however, is often proposed as a solution to all complexity. The problem is that a rewrite doesn’t remove essential complexity.&lt;/p&gt;

&lt;p&gt;If the team doesn’t deeply understand the business domain and its inherent challenges, they’ll simply recreate the same essential complexity in a new language or framework, only now without years of bug fixes and edge-case handling baked in.&lt;/p&gt;

&lt;p&gt;That’s why so many rewrites fail. They confuse essential complexity with accidental problems and end up producing a new system with the same issues as before, plus several new ones.&lt;/p&gt;

&lt;h2&gt;What are the costs of refactoring or rewriting?&lt;/h2&gt;

&lt;p&gt;Both refactoring and rewriting come with costs that go far beyond engineering hours, and they’re often underestimated.&lt;/p&gt;

&lt;h3&gt;The price of refactoring&lt;/h3&gt;

&lt;p&gt;The most significant cost of refactoring is opportunity cost. Every hour your team spends on internal improvements is an hour not spent on customer-facing features. This can be a hard sell to product and business leaders who don’t see immediate value. On top of that, a large refactoring effort sometimes fails to deliver the promised benefits if it doesn’t address the real architectural problems.&lt;/p&gt;

&lt;p&gt;You can spend months cleaning up modules only to realize that the real issue is how the database is structured or how services communicate.&lt;/p&gt;

&lt;h3&gt;The problem with a full rewrite&lt;/h3&gt;

&lt;p&gt;A full rewrite is one of the riskiest projects a software team can take on. Timelines are almost always wildly optimistic. While the new system is being built, the old one still needs to be maintained, which means running two systems in parallel and splitting the team’s focus. All the unwritten rules and implicit knowledge about why the old system works the way it does get lost, leading to a new wave of bugs and regressions.&lt;/p&gt;

&lt;p&gt;This often leads to what’s known as the “second system effect.” Free from the constraints of the old system, architects try to build a perfect, overengineered solution that solves every problem they can think of. Scope grows out of control, the project drags on for years, and by the time it’s finally ready, the business needs have changed again.&lt;/p&gt;

&lt;h2&gt;When should you refactor or rewrite?&lt;/h2&gt;

&lt;p&gt;Instead of relying on gut instinct, you need a structured way to evaluate your options. The decision should be based on a clear analysis of the trade-offs.&lt;/p&gt;

&lt;h3&gt;Criteria to evaluate your options&lt;/h3&gt;

&lt;p&gt;Here are a few key areas to assess with the team:&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;Technical viability&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Being realistic, can the current system be maintained for the next two or three years? Or are there architectural decisions, like a &lt;a href="https://kodus.io/en/monolith-to-microservices-guide/" rel="noopener noreferrer"&gt;monolith&lt;/a&gt; that blocks teams, that refactoring won’t fix?&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;Risk to business continuity&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;What can go wrong with each option? Refactoring too aggressively can create production instability. Rewriting everything introduces a different kind of risk, with many unknowns and a long, delicate migration.&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;Team capacity and knowledge&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Does the team have the skills to execute a rewrite in a new technology? Just as important: is there enough knowledge about the quirks of the old system to avoid repeating past mistakes?&lt;/p&gt;

&lt;h4&gt;&lt;strong&gt;Total cost of ownership&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Look beyond the initial project cost. Consider long-term maintenance costs, the cost of running systems in parallel during a rewrite, and the impact on hiring and retention.&lt;/p&gt;

&lt;h3&gt;A simple heuristic&lt;/h3&gt;

&lt;p&gt;If you need a simpler way to look at the decision, compare the estimated cost of incrementally refactoring the existing system to a state that meets future requirements with the total cost of starting from scratch.&lt;/p&gt;

&lt;p&gt;Be honest and comprehensive in your estimates, including parallel maintenance, migration, and the operational overhead of a new system.&lt;/p&gt;

&lt;p&gt;If the cost of a rewrite is even close to the cost of refactoring, the incremental path is almost always the safer and better choice, because it allows you to deliver value more continuously and manage risk along the way.&lt;/p&gt;

&lt;h2&gt;How to execute&lt;/h2&gt;

&lt;p&gt;Once the decision is made, everything depends on execution. Both paths can work, as long as there’s discipline, clear ownership, and a direct connection to business goals.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;Incremental refactoring with Strangler Fig&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;If the decision is to stick with the existing system, improvement needs to be continuous, not a large, one-off project. Make room in every sprint to &lt;a href="https://kodus.io/en/technical-debt-prioritizing-features/" rel="noopener noreferrer"&gt;reduce technical debt&lt;/a&gt; and improve what’s already in production.&lt;/p&gt;

&lt;p&gt;When larger architectural changes come into play, the &lt;em&gt;Strangler Fig&lt;/em&gt; pattern often works well. The idea is simple: pick a specific piece of functionality, implement it as a separate service, and start routing traffic to this new component through a proxy or routing layer. Gradually, parts of the old monolith stop being used and can be removed.&lt;/p&gt;

&lt;p&gt;Over time, the legacy system gets replaced in a controlled way, without a big-bang migration. This lets you modernize gradually, keep delivering value, and significantly reduce the risk of breaking something critical along the way.&lt;/p&gt;

&lt;h3&gt;Phased rewrites with a minimum viable scope&lt;/h3&gt;

&lt;p&gt;If a rewrite is truly unavoidable, the key is to aggressively limit scope. Define a &lt;strong&gt;Minimum Viable Rewrite (MVR)&lt;/strong&gt; that focuses on a small, well-understood vertical slice of the system.&lt;/p&gt;

&lt;p&gt;The goal is to get part of the new system into production as quickly as possible, even if it runs alongside the old one. Use feature flags and canary releases to roll the new system out gradually to users, giving yourself time to find and fix issues before a full cutover. This phased approach turns a huge, high-risk project into a series of smaller, manageable steps.&lt;/p&gt;

&lt;h3&gt;Governance and long-term alignment&lt;/h3&gt;

&lt;p&gt;No modernization effort will succeed without clear governance. This might mean setting up an Architecture Review Board to guide technical decisions or implementing automated tools to monitor code quality and technical debt.&lt;/p&gt;

&lt;p&gt;More importantly, any refactoring or rewrite initiative needs to be tied to clear product and business goals. If you can’t connect the technical work to real improvements, like faster delivery, greater stability, or a better user experience, support tends to fade over time.&lt;/p&gt;

</description>
      <category>refactoring</category>
      <category>code</category>
    </item>
    <item>
      <title>Engineering metrics: using data (DORA and others) to improve the team</title>
      <dc:creator>Edvaldo Freitas</dc:creator>
      <pubDate>Thu, 08 Jan 2026 11:10:00 +0000</pubDate>
      <link>https://dev.to/kodus/engineering-metrics-using-data-dora-and-others-to-improve-the-team-4ad4</link>
      <guid>https://dev.to/kodus/engineering-metrics-using-data-dora-and-others-to-improve-the-team-4ad4</guid>
      <description>&lt;p&gt;The conversation around &lt;strong&gt;engineering metrics&lt;/strong&gt; often gets stuck on the wrong things. We end up tracking activities like lines of code or number of commits per week, which say almost nothing about the health of our system or the effectiveness of the team. In practice, these metrics are easy to game and create incentives for the wrong behaviors, like splitting a single logical change into ten tiny commits.&lt;/p&gt;

&lt;p&gt;This gets even more complicated with AI-based coding assistants. The &lt;a href="https://cloud.google.com/resources/content/2025-dora-ai-assisted-software-development-report" rel="noopener noreferrer"&gt;2025 DORA report&lt;/a&gt; highlights how &lt;a href="https://kodus.io/en/whats-the-real-impact-of-ai-in-software-development/" rel="noopener noreferrer"&gt;AI acts as a problem amplifier&lt;/a&gt;. Teams using AI are shipping code faster, but they’re also seeing stability get worse. What happens is that AI makes it easy to generate a lot of code quickly, but if your &lt;a href="https://kodus.io/en/guide-to-code-review/" rel="noopener noreferrer"&gt;review processes&lt;/a&gt;, testing culture, and deployment pipelines are weak, you’re just pushing broken code to production faster than before.&lt;/p&gt;

&lt;p&gt;The core problem is still the same: we need a way to measure the health of the system as a whole, not just the speed of individual developers.&lt;/p&gt;

&lt;h2&gt;DORA: A framework to understand system health&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://kodus.io/en/essential-devops-metrics/" rel="noopener noreferrer"&gt;DORA metrics&lt;/a&gt; (Deployment Frequency, Lead Time for Changes, Change Failure Rate, and Mean Time to Recovery) offer a way to do that. They focus on system-level outcomes rather than individual output. Looking at these four metrics together gives you a clearer picture of speed and stability, which often complement each other. Improving one without considering the others usually leads to problems.&lt;/p&gt;

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

&lt;p&gt;This &lt;a href="https://kodus.io/en/how-to-measure-deployment-frequency/" rel="noopener noreferrer"&gt;metric measures how often you can successfully deploy to production&lt;/a&gt;. A higher frequency generally points to a healthier, more automated CI/CD pipeline and a workflow based on small, manageable changes. When deployment frequency is low, it’s usually a sign of large and risky batches, manual deployment steps, or fear of breaking things. For a tech lead, tracking this can help justify investments in better CI or more robust testing.&lt;/p&gt;

&lt;h3&gt;Lead Time for Changes&lt;/h3&gt;

&lt;p&gt;This is the &lt;a href="https://kodus.io/en/lead-time-6-tips-to-optimize-your-projects-efficiency/" rel="noopener noreferrer"&gt;time it takes for a commit to reach production&lt;/a&gt;. It’s one of the most useful diagnostic metrics for a team. A long lead time can point to several different issues: PRs that are too large, a slow code review process, flaky tests in the CI pipeline, or manual QA gates. By breaking lead time into stages (time to first review, time in review, time to merge, time to deploy), you can pinpoint exactly where work is getting stuck. If PRs sit idle for days waiting for review, that’s a team process conversation, not an individual developer speed issue.&lt;/p&gt;

&lt;h3&gt;Change Failure Rate&lt;/h3&gt;

&lt;p&gt;This metric tracks how often a production deployment causes a failure, such as an outage or a rollback. It’s a direct measure of quality and stability. A high failure rate suggests that your testing and review processes aren’t catching issues before they reach users. This often correlates with large batches, since bigger changes are harder to understand and test thoroughly.&lt;/p&gt;

&lt;h3&gt;Mean Time to Recovery (MTTR)&lt;/h3&gt;

&lt;p&gt;When a failure happens, how long does it take to restore service? &lt;a href="https://kodus.io/en/what-is-mean-time-to-recover/" rel="noopener noreferrer"&gt;That’s MTTR&lt;/a&gt;. A low MTTR is a sign of a resilient system and a solid incident response process. It shows that you can detect problems quickly, diagnose them effectively, and roll back or fix issues without causing new ones.&lt;/p&gt;

&lt;h2&gt;AI and engineering metrics&lt;/h2&gt;

&lt;p&gt;AI tools for code don’t change the basic principles of how software is delivered. What they do is amplify what’s already there. AI works as a multiplier of the systems and practices a team already has. If you have strong technical fundamentals, a habit of working in small batches, and a healthy review process, AI tends to accelerate all of that and reduce friction.&lt;/p&gt;

&lt;p&gt;The real risk shows up when those practices don’t exist. If your team already tends to create huge pull requests, AI will help generate even bigger PRs, just faster. If there’s already a lot of &lt;a href="https://kodus.io/en/reduce-technical-debt/" rel="noopener noreferrer"&gt;technical debt&lt;/a&gt;, AI-generated code without context can easily make it worse.&lt;/p&gt;

&lt;p&gt;That’s why good practices become even more important with AI, especially working in small batches, which becomes even more critical. A small, well-understood change is always safer to ship to production, whether it’s written by a person or with the help of AI.&lt;/p&gt;

&lt;h2&gt;&lt;strong&gt;What needs to be in place before using AI, according to DORA&lt;/strong&gt;&lt;/h2&gt;

&lt;p&gt;To get value from AI without amplifying existing problems, teams need a solid foundation. DORA’s research summarizes this into seven essential capabilities for adopting AI the right way:&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;1. Clear guidance on AI usage&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Everyone on the team needs to know the rules of the game: which tools can be used, what kind of data can be shared, and how to handle AI-generated code in day-to-day work.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;2. Healthy data ecosystems&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;The quality of the help AI provides depends directly on the quality of the data behind it. Garbage in, garbage out.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;3. Internal data accessible to AI&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;To be truly useful, AI needs context. That includes internal libraries, APIs, company standards, and relevant documentation.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;4. Working in small batches&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Working with small changes reduces risk and keeps the feedback loop short. This becomes even more important when code can be generated very quickly.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;5. Focus on the end user&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;AI is a means, not an end. It should help solve real user problems, not just increase the amount of code produced.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;6. Well-maintained internal platforms&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;A good internal platform removes repetitive work and provides clear paths to test and deploy. That makes it much safer to integrate AI-generated code.&lt;/p&gt;

&lt;h3&gt;&lt;strong&gt;7. Strong technical fundamentals&lt;/strong&gt;&lt;/h3&gt;

&lt;p&gt;Loosely coupled architecture, comprehensive test automation, and solid engineering standards are not optional.&lt;/p&gt;

&lt;h2&gt;Other metrics that can help&lt;/h2&gt;

&lt;p&gt;DORA metrics go a long way toward understanding the health of the delivery pipeline, but on their own they don’t explain everything. Other frameworks complement this view by connecting delivery performance to developer experience and overall value flow.&lt;/p&gt;

&lt;h3&gt;SPACE&lt;/h3&gt;

&lt;p&gt;The SPACE framework broadens the view of what actually makes developers productive and satisfied. It argues that you can’t measure output alone. To understand real productivity, you need to look at multiple signals at the same time:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;
&lt;strong&gt;Satisfaction and well-being:&lt;/strong&gt; How fulfilled and healthy are your engineers? Burnout is a major productivity killer.&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Performance:&lt;/strong&gt; How do individuals and teams perceive their own performance?&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Activity:&lt;/strong&gt; Output metrics like commits or PRs. They’re useful, but dangerous when analyzed in isolation.&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Communication and collaboration:&lt;/strong&gt; How well do people and teams work together? Think about how easy it is to find information and the quality of reviews.&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Efficiency and flow:&lt;/strong&gt; How effectively can developers work without interruptions or friction? This ties directly to DORA’s Lead Time for Changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal of SPACE is to create a balanced set of metrics so you don’t accidentally optimize one area at the expense of another, like increasing activity at the cost of burnout.&lt;/p&gt;

&lt;h3&gt;Value Stream Management (VSM)&lt;/h3&gt;

&lt;p&gt;Value Stream Management is a way to visualize, measure, and improve the entire process, from idea conception to customer delivery.&lt;/p&gt;

&lt;p&gt;While DORA gives you key outcomes (like lead time), VSM helps map all the intermediate steps to understand &lt;em&gt;why&lt;/em&gt; your lead time is what it is. It focuses on flow metrics such as:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;
&lt;strong&gt;Flow Velocity:&lt;/strong&gt; How many work items are completed per unit of time?&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Flow Time:&lt;/strong&gt; How long does an item take from start to finish? (Similar to Lead Time)&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Flow Load:&lt;/strong&gt; How many items are currently in progress? (A proxy for WIP)&lt;/li&gt;
    &lt;li&gt;
&lt;strong&gt;Flow Efficiency:&lt;/strong&gt; What percentage of the total flow time is spent on active work versus waiting? This is often the most revealing metric. It’s common to discover that a ticket spends 90% of its time just waiting for a review, a build, or a handoff.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;VSM adds context to DORA metrics. Your Change Failure Rate might be high, and a value stream map might show that this happens because there’s no dedicated time for QA, forcing developers to rush tests at the last minute.&lt;/p&gt;

&lt;h2&gt;Using metrics to improve the team&lt;/h2&gt;

&lt;p&gt;Collecting metrics doesn’t help much if you don’t act on them. The idea is to use the data to spark good conversations and improve the team, not to create yet another dashboard that no one opens. The DORA improvement loop helps close that gap.&lt;/p&gt;

&lt;h3&gt;The DORA improvement loop&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Establish a baseline:&lt;/strong&gt; First, simply measure your four core metrics to understand where you are today. You can’t improve what you don’t measure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Have a conversation:&lt;/strong&gt; Metrics tell you &lt;strong&gt;what&lt;/strong&gt; is happening, but not &lt;strong&gt;why&lt;/strong&gt;. The next step is to talk with the team. A value stream mapping exercise can be extremely useful to visualize the entire process, from idea to production, and identify where the real friction is.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit to improving the biggest constraint:&lt;/strong&gt; Don’t try to fix everything at once. Identify the biggest bottleneck slowing the team down or causing failures and focus on that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Turn the commitment into a plan:&lt;/strong&gt; Create a concrete plan with leading indicators. For example, if the bottleneck is code review time, an indicator might be “average PR size” or “time from PR open to first comment.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do the work:&lt;/strong&gt; This involves systemic changes, not quick fixes. It might mean &lt;a href="https://kodus.io/en/best-developer-productivity-tools/" rel="noopener noreferrer"&gt;investing in better tools&lt;/a&gt;, changing a team process, or paying down a specific chunk of technical debt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check progress and iterate:&lt;/strong&gt; After a few weeks or a sprint, review your DORA metrics and indicators to see if the changes had the expected effect. Then choose the next biggest constraint and repeat the cycle.&lt;/p&gt;

&lt;p&gt;It’s also useful to remember that DORA isn’t the only framework. The SPACE framework is a great complement, as it brings in developer satisfaction, well-being, and collaboration.&lt;/p&gt;

&lt;h2&gt;The most common mistakes when using engineering metrics&lt;/h2&gt;

&lt;p&gt;When you start using these metrics, it’s easy to fall into a few common traps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using metrics to evaluate individual performance:&lt;/strong&gt; This is the fastest way to destroy trust and encourage metric gaming. DORA metrics measure team and system performance, period. They should &lt;strong&gt;never&lt;/strong&gt; be used in individual performance reviews.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The “gaming” metrics trap:&lt;/strong&gt; If you incentivize a specific metric, people will find a way to optimize it, often at the expense of what actually matters. For example, focusing only on Deployment Frequency can lead a team to ship tiny, meaningless changes just to inflate the number.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Metrics overload:&lt;/strong&gt; Don’t try to measure everything. Start with the four core DORA metrics. Once you have a handle on them, you can add others, but keep the focus on a small set of indicators directly tied to your improvement goals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not acting on the data:&lt;/strong&gt; The worst outcome is spending time and effort collecting data and then doing nothing with it. Metrics should always be a catalyst for conversation and action. If they aren’t, it’s worth asking why you’re collecting them in the first place.&lt;/p&gt;

&lt;h2&gt;Some recommendations&lt;/h2&gt;

&lt;p&gt;If the goal is to use data more deliberately to improve the team, here’s a path you can follow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Establish baseline DORA metrics:&lt;/strong&gt; Use a tool or script to get an initial reading of the four core metrics. This gives you a starting point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Focus improvement efforts on the team’s biggest constraint:&lt;/strong&gt; Work with the team to identify the most painful bottleneck right now and make a clear agreement to focus on improving that first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Treat AI adoption as a systemic change:&lt;/strong&gt; It’s not just about handing out Copilot licenses and hoping for the best. Set clear guidelines and reinforce good habits so AI doesn’t simply accelerate existing problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Complement DORA with other frameworks:&lt;/strong&gt; Consider using elements of SPACE to get a more complete view that includes developer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Embrace continuous improvement as a cultural practice:&lt;/strong&gt; The goal isn’t to achieve a “perfect” score on metrics. It’s to build a culture where the team is constantly working to improve its workflow and the health of its systems.&lt;/p&gt;

</description>
      <category>engineeringmetrics</category>
      <category>dorametrics</category>
    </item>
  </channel>
</rss>
