<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://www.yellowduck.be/pretty-atom-feed-v3.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <link href="https://www.yellowduck.be" rel="alternate"/>
  <link href="https://www.yellowduck.be/posts/feed" rel="self"/>
  <author>
    <name>Pieter Claerhout</name>
    <email>pieter@yellowduck.be</email>
  </author>
  <id>https://www.yellowduck.be/posts/feed</id>
  <title>🐥 YellowDuck.be</title>
  <updated>2026-09-12T17:00:00Z</updated>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/undoing-a-pushed-merge-commit-without-losing-work" rel="alternate"/>
    <content type="html">&lt;p&gt;Sometimes you push a merge commit you didn&apos;t mean to, and notice it only after the fact. Here&apos;s how we handled it cleanly when that happened on a feature branch.&lt;/p&gt;
&lt;p&gt;My branch history looked like this:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;abc1234  Fix for the feature we were working on  ← latest commit, must keep
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;def5678  Merge branch &amp;#39;feature/my-branch&amp;#39; of ...  ← mistake
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;ghi9012  Previous commit
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;jkl3456  Older commit
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The merge commit &lt;code&gt;def5678&lt;/code&gt; was already pushed to GitHub. The latest fix (&lt;code&gt;abc1234&lt;/code&gt;) sat on top of it, so a plain &lt;code&gt;git reset --hard HEAD~1&lt;/code&gt; would have taken the fix with it.&lt;/p&gt;
&lt;p&gt;I needed to drop exactly one commit from the middle of the history while keeping everything above it. &lt;code&gt;git rebase --onto&lt;/code&gt; is the right tool for this:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;rebase&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;--onto&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;ghi9012&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;def5678&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;HEAD&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells Git: take all commits after &lt;code&gt;def5678&lt;/code&gt; up to &lt;code&gt;HEAD&lt;/code&gt;, and replay them directly onto &lt;code&gt;ghi9012&lt;/code&gt; — the commit before the bad merge. The merge commit is skipped entirely.&lt;/p&gt;
&lt;p&gt;The rebase left us in a detached HEAD state, so we updated the branch pointer and switched back:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;branch&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;feature/my-branch&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;HEAD&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;checkout&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;feature/my-branch&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The history was now clean:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;xyz7890  Fix for the feature we were working on
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;ghi9012  Previous commit
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;jkl3456  Older commit
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then a force-push to update the remote:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;--force&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why not &lt;code&gt;git revert&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git revert -m 1 &lt;hash&gt;&lt;/code&gt; is the safer choice when multiple people have already pulled the branch, because it adds a new commit rather than rewriting history. In our case the branch was a personal feature branch with no other active collaborators, so rewriting was fine and kept the history cleaner.&lt;/p&gt;
&lt;p&gt;When in doubt on a shared branch, revert. On a solo feature branch, rebase is cleaner.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/terminal&quot;&gt;#terminal&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/git&quot;&gt;#git&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-12T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/undoing-a-pushed-merge-commit-without-losing-work</id>
    <title>🐥 Undoing a pushed merge commit without losing work</title>
    <updated>2026-09-12T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/why-we-dont-use-ai-rene-herse-cycles" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;A nice post from Rene Herse Cycles on why AI is not the answer to everything.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.renehersecycles.com/why-we-dont-use-ai/&quot;&gt;Continue reading on &lt;strong&gt;www.renehersecycles.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-12T15:00:00Z</published>
    <id>https://www.yellowduck.be/posts/why-we-dont-use-ai-rene-herse-cycles</id>
    <title>🔗 Why We Don’t Use AI @ Rene Herse Cycles</title>
    <updated>2026-09-12T15:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/linux-nameservers-and-dns-resolution" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;DNS resolution on Linux can lead to frustrating errors like “Temporary failure in resolving” when issues arise. This guide, written by Hayden James, explains how DNS resolution works on Linux systems, covering configuration for desktops, servers, and VPS setups. The article details the management of DNS settings via &lt;code&gt;/etc/nsswitch.conf&lt;/code&gt; and &lt;code&gt;/etc/resolv.conf&lt;/code&gt;, as well as the role of &lt;code&gt;systemd-resolved&lt;/code&gt; in modern distributions. Key tools such as &lt;code&gt;dig&lt;/code&gt;, &lt;code&gt;resolvectl&lt;/code&gt;, and &lt;code&gt;getent&lt;/code&gt; are discussed for diagnosing and troubleshooting DNS problems. Readers will learn how to configure DNS servers, flush caches, and resolve common DNS issues. Understanding these concepts is crucial for maintaining reliable network connectivity on Linux systems.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://linuxblog.io/linux-nameservers-dns-resolution/&quot;&gt;Continue reading on &lt;strong&gt;linuxblog.io&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/terminal&quot;&gt;#terminal&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/linux&quot;&gt;#linux&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sysadmin&quot;&gt;#sysadmin&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-12T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/linux-nameservers-and-dns-resolution</id>
    <title>🔗 Linux nameservers and DNS resolution</title>
    <updated>2026-09-12T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/laravel-doctor-diagnose-your-app-with-one-artisan-command" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Laravel Doctor was announced at Laracon US 2026 in Boston, introducing an &lt;code&gt;artisan doctor&lt;/code&gt; command that performs health checks on Laravel applications. This command ensures essential configurations are correct, such as verifying the presence of the &lt;code&gt;.env&lt;/code&gt; file, checking the &lt;code&gt;APP_KEY&lt;/code&gt;, confirming PHP version compatibility, and making sure required extensions are installed. If issues are found, Doctor can automatically fix them where possible or clearly state what needs attention.&lt;/p&gt;
&lt;p&gt;Each diagnostic is grouped into classes handling specific checks—covering environment, Composer dependencies, configuration, database connectivity, and more. The command can be extended by packages that want to add custom diagnostics, making it a versatile tool for maintaining application health. With the ability to provide machine-readable reports, Laravel Doctor is designed not only for developers but also for CI environments and AI coding agents, ensuring robust application maintenance across various setups.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://laravel-news.com/laravel-doctor-first-party-diagnostics-for-your-application&quot;&gt;Continue reading on &lt;strong&gt;laravel-news.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-12T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/laravel-doctor-diagnose-your-app-with-one-artisan-command</id>
    <title>🔗 Laravel Doctor: Diagnose your app with one artisan command</title>
    <updated>2026-09-12T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/clickhouse-adapter-elixir" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Building an Ecto adapter for ClickHouse involved overcoming the limits of Postgres when handling aggregate data. The article describes how integrating ClickHouse&apos;s columnar storage improves query performance while preserving Ecto&apos;s familiar syntax and functions. The author shares insights on the development process, including utilizing a dependency-aware issue tracker called &lt;code&gt;beads&lt;/code&gt; and employing a language model for incremental task breakdowns. An important aspect of the project was establishing a native TCP driver to facilitate efficient communication. Key challenges included debugging a complex handshake protocol and implementing a custom compression method. Ultimately, the project produced a functional &lt;code&gt;clickhouse_adapter_ecto&lt;/code&gt;, enabling support for ClickHouse features while adapting them to Ecto&apos;s structure, proving the value of careful planning and incremental testing in software development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://mfeckie.dev/blog/clickhouse-adapter-elixir&quot;&gt;Continue reading on &lt;strong&gt;mfeckie.dev&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-11T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/clickhouse-adapter-elixir</id>
    <title>🔗 ClickHouse adapter Elixir</title>
    <updated>2026-09-11T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/anti-antipatterns-in-elixir-library-guidelines" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The Elixir Library Guidelines preach strict rules, but what if they&apos;re overlooking practical software engineering needs? This article dives into the nine declared &quot;anti-patterns&quot; from these guidelines, arguing why they aren&apos;t just permissible but essential in many scenarios. From the erroneous avoidance of application configuration to the drawbacks of strictly using tuples for control flow, the discussion reveals real-world use cases where breaking these prescribed rules can lead to better software design. The guidelines may be a helpful starting point, but understanding when and why to deviate from them empowers developers to make informed decisions tailored to their project&apos;s unique challenges. This piece invites readers to reconsider the rigidity of these guidelines, emphasizing the importance of context-driven development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://rocket-science.ru/hacking/2026/08/09/anti-antipatterns-in-elixir-libraries&quot;&gt;Continue reading on &lt;strong&gt;rocket-science.ru&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/pattern&quot;&gt;#pattern&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-11T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/anti-antipatterns-in-elixir-library-guidelines</id>
    <title>🔗 Anti-antipatterns in Elixir library guidelines</title>
    <updated>2026-09-11T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/phoenix-version-adoption-security" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The Phoenix ecosystem sees rapid patch adoption but slow migration between minor versions. Data shows that patch releases within the same minor version gain traction within two weeks, while the transition to a new minor version often takes seven to eight months to surpass a 50% adoption rate. This pattern highlights a connection between the minor series in use and the responsiveness to security releases.&lt;/p&gt;
&lt;p&gt;Currently, four minor versions of Phoenix receive official support. Adoption data indicates that teams using older versions experience delays in applying patches due to inertia. This not only elevates the risk of unpatched vulnerabilities but complicates upgrades as dependencies grow. When crucial security patches roll out, older versions lag in responsiveness, posing a significant security risk, especially when vulnerabilities require no authentication, rendering unpatched systems vulnerable to attacks. Staying current with Phoenix and LiveView releases is essential to maintaining application security and operational efficiency.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.praialabs.com/phoenix-version-adoption&quot;&gt;Continue reading on &lt;strong&gt;www.praialabs.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/phoenix&quot;&gt;#phoenix&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-11T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/phoenix-version-adoption-security</id>
    <title>🔗 Phoenix version adoption &amp; security</title>
    <updated>2026-09-11T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/genstage-demand-visualized" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Can visualizing demand in GenStage optimize your Elixir applications? Andrea Leopardi demonstrates how to craft informative visualizations that clarify backpressure in stream processing. By employing tools like &lt;code&gt;:observer&lt;/code&gt; and custom metrics, the article emphasizes the importance of understanding how demand fluctuates in real-time. Leopardi shares practical examples that help developers grasp how to balance producer and consumer relationships in GenStage for more resilient applications. He advocates for clear metrics and visual aids that can significantly enhance how systems operate, especially as complexity increases with more extensive data streams. Overall, it&apos;s a focused look at leveraging Elixir&apos;s capabilities to improve application performance through visual insights.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://out.reddit.com/t3_1vhxagp?app_name=ios&amp;token=AQAA0092avhip6BbqTwiqSMrplW2w8k1NqYRbiGqDdGqlMP12sli&amp;url=https%3A%2F%2Fandrealeopardi.com%2Fposts%2Fgenstage-demand-visualized%2F&quot;&gt;Continue reading on &lt;strong&gt;out.reddit.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/elixir&quot;&gt;#elixir&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-10T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/genstage-demand-visualized</id>
    <title>🔗 GenStage demand visualized</title>
    <updated>2026-09-10T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/github-actions-is-having-one-of-the-worst-days-in-its-history" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;GitHub Actions experienced a major outage on August 6, 2026, that lasted over seven hours, making it the second-longest outage in the service&apos;s history. The incident significantly impacted the ability to execute workflows, with GitHub processing only about 15% of webhook triggers at its peak. Many jobs failed to execute, and although there was an improvement later on, the overall performance remained poor. The outage contrasted sharply with GitHub&apos;s rapid growth in service demand, as reflected in past metrics that showed an increase from 500 million minutes a week in 2023 to over 2.1 billion minutes this spring. While GitHub has not yet disclosed the exact cause of this latest outage, it highlights the challenges that come with scaling services to meet increasing user demand.&lt;/p&gt;
&lt;p&gt;The final tally for this incident marked 7 hours and 26 minutes of total downtime, just shy of the record for the longest major outage set in May 2021. While there may be no immediate lessons learned, the community was left collectively waiting for updates as the situation unfolded.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://kernel.pryanic.com/posts/github-actions-is-having-one-of-the-worst-days-in-its-history&quot;&gt;Continue reading on &lt;strong&gt;kernel.pryanic.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/github&quot;&gt;#github&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/announcement&quot;&gt;#announcement&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-10T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/github-actions-is-having-one-of-the-worst-days-in-its-history</id>
    <title>🔗 GitHub Actions is having one of the worst days in its history</title>
    <updated>2026-09-10T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-distinct-in-your-count" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;The query &lt;code&gt;SELECT count(DISTINCT user_id) FROM events;&lt;/code&gt; might seem efficient, but it can lead to performance pitfalls. The keyword &lt;code&gt;DISTINCT&lt;/code&gt; disables parallel query execution in PostgreSQL, forcing the database to process all data serially. This occurs because the aggregate &lt;code&gt;COUNT(DISTINCT ...)&lt;/code&gt; requires a unique count, which cannot use parallel processing effectively due to the need for a specific order. Without parallel execution, queries on large tables become inefficient, often resulting in costly disk usage and longer processing times. The article offers a solution: rewriting the query to use a &lt;code&gt;GROUP BY&lt;/code&gt; clause instead. This approach allows for parallel processing, significantly improving query execution time with larger datasets while still achieving the desired unique count result.  This insight is crucial for developers optimizing analytics queries for better performance.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://boringsql.com/posts/distinct-in-your-count/&quot;&gt;Continue reading on &lt;strong&gt;boringsql.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/postgresql&quot;&gt;#postgresql&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sql&quot;&gt;#sql&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-10T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-distinct-in-your-count</id>
    <title>🔗 The DISTINCT in your COUNT</title>
    <updated>2026-09-10T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/what-are-code-reviews-even-for" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;AI didn’t break code review; it highlighted existing issues. Brian Houck discusses how the surge of AI in code production has outpaced human review. At Meta, lines of code per diff increased by 106%, with diffs up 51% due to AI, while the timeliness of reviews has declined. Developers idealize spending only 7% of their time reviewing code, indicating we must rethink the purpose of code review itself. It&apos;s traditionally about more than just defect detection; it&apos;s a space for knowledge transfer and architectural understanding. Rethinking habits around code reviews before AI can be effective is crucial. Using AI wisely can enhance the process, but organizations risk eroded collective understanding by automating too much. Effective code review is about preserving knowledge and fostering collaboration, not just speeding up the process.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://newsletter.getdx.com/p/what-are-code-reviews-even-for&quot;&gt;Continue reading on &lt;strong&gt;newsletter.getdx.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-09T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/what-are-code-reviews-even-for</id>
    <title>🔗 What are code reviews even for?</title>
    <updated>2026-09-09T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/your-count-distinct-is-too-slow-approximations-and-sampling-in-postgresql" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Can you afford to wait for precise distinct counts in Postgres? Elizabeth Garrett Christensen reveals that exact counts can be prohibitively slow, especially with large datasets. She outlines various strategies for approximating unique counts using features like the built-in &lt;code&gt;TABLESAMPLE&lt;/code&gt; for random sampling, the HyperLogLog (HLL) for efficient distinct counting, and introduces Apache DataSketches for more complex scenarios. The article offers practical examples, including how to set up a sample &lt;code&gt;page_views&lt;/code&gt; table with 10 million rows, and examines the benchmarks of different methods to highlight performance differences. You&apos;ll learn how accurate data analysis can still be quick and accessible without sacrificing too much precision.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.snowflake.com/en/blog/engineering/postgres-count-distinct-approximation/&quot;&gt;Continue reading on &lt;strong&gt;www.snowflake.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/postgresql&quot;&gt;#postgresql&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-09T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/your-count-distinct-is-too-slow-approximations-and-sampling-in-postgresql</id>
    <title>🔗 Your COUNT(DISTINCT) is too slow: Approximations and sampling in PostgreSQL</title>
    <updated>2026-09-09T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/hybrid-search-patterns-with-postgresql-and-pgvector" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Most production vector queries aren&apos;t just about finding similar documents; they often involve specific criteria. The article explains hybrid search patterns, combining similarity ranking with scalar filters in PostgreSQL by utilizing &lt;code&gt;pgvector&lt;/code&gt; and hybrid Nearest Neighbor searches. The author showcases how to effectively integrate &lt;code&gt;WHERE&lt;/code&gt; clauses into vector queries, which can often lead to trade-offs between recall and performance. Techniques such as iterative index scans are discussed to refine these searches. The article thoroughly analyzes various querying strategies, including oversampling and caching responses to improve query efficiency. It offers practical insights on building indexes and optimizing performance for complex applications that require both speed and accuracy, making it an essential read for database administrators and developers working with vector data in PostgreSQL.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.crunchydata.com/blog/hybrid-vector-search&quot;&gt;Continue reading on &lt;strong&gt;www.crunchydata.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/postgresql&quot;&gt;#postgresql&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-09T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/hybrid-search-patterns-with-postgresql-and-pgvector</id>
    <title>🔗 Hybrid search patterns with PostgreSQL and pgvector</title>
    <updated>2026-09-09T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/image-dominant-color-and-heic-support-in-laravel-13-24" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Laravel 13.24 brings major improvements to its image API, including dominant color detection and support for HEIC files. With the new &lt;code&gt;dominantColor()&lt;/code&gt; method, developers can now easily retrieve the average color of an image, making it ideal for UI enhancements while loading images. This version also introduces the &lt;code&gt;modelKeys()&lt;/code&gt; method to Eloquent queries, streamlining primary key retrieval, along with a new &lt;code&gt;array_keys&lt;/code&gt; validation rule that reports unexpected keys directly. Importantly, it adds support for AVIF and HEIC image formats as both input and output, enhancing compatibility for images straight from devices like iPhones. Other fixes include performance improvements for wildcard validations on large arrays, among various other enhancements to the Laravel framework. This update reflects Laravel&apos;s ongoing commitment to improving developer experience and application performance.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://laravel-news.com/laravel-13-24-0&quot;&gt;Continue reading on &lt;strong&gt;laravel-news.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/eloquent&quot;&gt;#eloquent&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-08T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/image-dominant-color-and-heic-support-in-laravel-13-24</id>
    <title>🔗 Image dominant color and HEIC support in Laravel 13.24</title>
    <updated>2026-09-08T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/limited-output-is-a-feature" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;As startups increasingly leverage LLM agents for software tasks, a critical question arises: are they losing sight of meaningful product development? Johanna Larsson argues that many are racing to optimize for &quot;AI-enablement&quot; rather than focusing on user value. She highlights successful companies like Linear, which thrived by prioritizing core user experiences over excessive features. Instead of getting caught up in continuous output and feature requests, Larsson encourages a return to thoughtful product creation. Businesses should spend more time contemplating what truly matters—cutting out unnecessary complexity to reveal the essence of their products. This slower, more intentional approach not only enhances user satisfaction but also fosters innovation, advocating for fewer features that deliver greater value.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://jola.dev/posts/limited-output-is-a-feature&quot;&gt;Continue reading on &lt;strong&gt;jola.dev&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-08T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/limited-output-is-a-feature</id>
    <title>🔗 Limited output is a feature.</title>
    <updated>2026-09-08T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/whats-new-in-php-8-6" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;PHP 8.6, set to release on November 19, 2026, introduces several important features including partial function application (PFA) and a new polling API. PFA lets developers create references to closures with some parameters pre-defined, streamlining code when combined with the pipe operator. The new polling API improves the handling of asynchronous processes, although it doesn&apos;t bring built-in async capabilities.&lt;/p&gt;
&lt;p&gt;Another significant change is the allowance of default values for readonly properties, following the introduction of property hooks in PHP 8.4, and the addition of new functions and classes for enhanced functionality such as &lt;code&gt;Duration&lt;/code&gt; and &lt;code&gt;clamp()&lt;/code&gt;. Moreover, the security for session defaults is tightened with stricter ini settings, improving overall security for applications. These updates reflect an aim for better usability and performance in PHP development.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://stitcher.io/blog/new-in-php-86&quot;&gt;Continue reading on &lt;strong&gt;stitcher.io&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/development&quot;&gt;#development&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/php&quot;&gt;#php&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-08T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/whats-new-in-php-8-6</id>
    <title>🔗 What&apos;s new in PHP 8.6</title>
    <updated>2026-09-08T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/laravel-boost-best-practices-a-major-tone-shift-august-2026" rel="alternate"/>
    <content type="html">&lt;p&gt;Two commits landed in the &lt;a href=&quot;https://github.com/laravel/boost&quot;&gt;Laravel Boost&lt;/a&gt; repository on August 26, 2026 that significantly update the AI guidance rules baked into the package. The changes touch all 19 best-practice rule files and add a new section on controller resource design. Here is what changed and why it matters.&lt;/p&gt;
&lt;h1&gt;The big picture: from prescriptive to contextual&lt;/h1&gt;
&lt;p&gt;The first commit (&lt;a href=&quot;https://github.com/laravel/boost/commit/d165b9ea6086294a8f1999ac3dcf4e61da267b23&quot;&gt;&lt;code&gt;d165b9ea&lt;/code&gt;&lt;/a&gt;) touches 1,427 lines across every rule file. The headline change is not a new feature — it is a &lt;strong&gt;deliberate softening of absolute language&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Rules that previously said &lt;strong&gt;&quot;Incorrect&quot; / &quot;Correct&quot;&lt;/strong&gt; now use labels like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&quot;Manual lookup:&quot;&lt;/em&gt; / &lt;em&gt;&quot;Use route model binding:&quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&quot;Hidden dependency:&quot;&lt;/em&gt; / &lt;em&gt;&quot;Injected dependency:&quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&quot;Unsafe:&quot;&lt;/em&gt; / &lt;em&gt;&quot;Preferred:&quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&quot;Queued and durable:&quot;&lt;/em&gt; / &lt;em&gt;&quot;Deferred in the current process:&quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The intent is clear: the guidance now presents &lt;strong&gt;trade-offs and context&lt;/strong&gt; instead of moral verdicts. This matters because AI coding agents (and developers) following these rules were previously being trained to treat &quot;Incorrect&quot; examples as always wrong, even in situations where the pattern was actually fine.&lt;/p&gt;
&lt;h1&gt;Key Changes by Area&lt;/h1&gt;
&lt;h2&gt;Queries — &lt;code&gt;advanced-queries.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The old guidance said &lt;code&gt;whereHas()&lt;/code&gt; was flat-out wrong because it &quot;re-executes per row.&quot; The new version is more honest:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;whereHas()&lt;/code&gt; typically produces an &lt;code&gt;EXISTS&lt;/code&gt; subquery, while &lt;code&gt;whereIn()&lt;/code&gt; can express the same filter with an &lt;code&gt;IN&lt;/code&gt; subquery. Either form may be faster depending on the database engine, indexes, cardinality, and query plan. &lt;strong&gt;Measure both forms with representative data.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The section title changed from &lt;em&gt;&quot;Prefer &lt;code&gt;whereIn&lt;/code&gt; + Subquery Over &lt;code&gt;whereHas&lt;/code&gt;&quot;&lt;/em&gt; to &lt;em&gt;&quot;Compare &lt;code&gt;whereHas()&lt;/code&gt; with an &lt;code&gt;IN&lt;/code&gt; Subquery&quot;&lt;/em&gt;. Similarly, the compound index rule now says &lt;em&gt;&quot;verify the query plan&quot;&lt;/em&gt; rather than asserting a single correct approach.&lt;/p&gt;
&lt;p&gt;A technical fix also snuck in: the dynamic relationship example now correctly passes the foreign key to &lt;code&gt;belongsTo()&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;l-comment&quot;&gt;// Before (broken — missing the FK argument):&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;l-keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;l-variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;belongsTo&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;&lt;span class=&quot;l-comment&quot;&gt;// After (correct):&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;&lt;span class=&quot;l-keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;l-variable-builtin&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;belongsTo&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;Login&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&amp;#39;last_login_id&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Architecture — &lt;code&gt;architecture.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Two notable shifts:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dependency injection&lt;/strong&gt;: The old rule said constructor injection was always correct and method injection was a code smell. The new rule aligns with how Laravel actually works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Prefer constructor injection for dependencies required throughout an object&apos;s lifetime. &lt;strong&gt;Method injection is appropriate for dependencies needed by one controller action, listener, job handler, or other container-invoked method.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;Default sort order&lt;/strong&gt;: Instead of &quot;always use &lt;code&gt;latest()&lt;/code&gt;&quot;, the guidance now recommends a stable two-column sort with a tie-breaker for reliable pagination:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;l-type&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;    &lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;orderByDesc&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;created_at&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;orderByDesc&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;id&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;    &lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;paginate&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Caching — &lt;code&gt;caching.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;Cache::remember()&lt;/code&gt; section now explicitly warns about the false-cache-miss bug:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The manual version below incorrectly treats valid falsy values, such as &lt;code&gt;false&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt;, as cache misses.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It also adds an honest caveat: &lt;code&gt;Cache::remember()&lt;/code&gt; does not prevent concurrent requests from computing the same missing value — you still need &lt;code&gt;Cache::lock()&lt;/code&gt; for that.&lt;/p&gt;
&lt;h2&gt;Routing — &lt;code&gt;routing.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The &quot;Keep Controllers Thin&quot; rule (with its arbitrary &quot;under 10 lines&quot; target) is gone. In its place:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Controllers should coordinate HTTP input, authorization, validation, an application operation, and the response. &lt;strong&gt;Extract substantial or reusable business logic, but do not introduce an action or service merely to satisfy an arbitrary line limit.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Migrations — &lt;code&gt;migrations.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The file shrank significantly (78 → 24 deletions vs. 24 additions). Several overly prescriptive examples were removed. The foreign-key section now includes a practical note:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not add a duplicate single-column index without checking the database driver&apos;s treatment of foreign-key indexes and the indexes already created by the migration.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Security — &lt;code&gt;security.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Two nuanced additions stand out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;$guarded = []&lt;/code&gt; is no longer labeled universally &quot;Incorrect.&quot; The new text acknowledges that mass-assignment protection controls &lt;em&gt;which attributes can be set&lt;/em&gt;, not values or authorization — and that deliberate conventions using &lt;code&gt;$guarded&lt;/code&gt; are valid.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The SQL injection example now uses the fluent string helper properly:&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;l-type&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;whereRaw&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;LOWER(name) = ?&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;l-variable&quot;&gt;$request&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;name&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;A new explicit note: &lt;em&gt;&quot;Public actions intentionally available to everyone do not need a redundant authorization check.&quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Queues — &lt;code&gt;queue-jobs.md&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The Amazon SQS footnote is new and important:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Amazon Simple Queue Service uses its &lt;strong&gt;visibility timeout&lt;/strong&gt; instead of Laravel&apos;s &lt;code&gt;retry_after&lt;/code&gt;; configure that timeout at the queue level.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;code&gt;ShouldBeUnique&lt;/code&gt; section now notes that all dispatching processes must share a cache store that supports locks — a silent gotcha that has burned teams before.&lt;/p&gt;
&lt;hr /&gt;
&lt;h1&gt;New section: organize controllers around resources&lt;/h1&gt;
&lt;p&gt;The second commit (&lt;a href=&quot;https://github.com/laravel/boost/commit/d165b9ea6086294a8f1999ac3dcf4e61da267b23&quot;&gt;&lt;code&gt;b19e98a8&lt;/code&gt;&lt;/a&gt;) adds a standalone section to &lt;code&gt;routing.md&lt;/code&gt; covering a pattern that often gets debated on Laravel teams.&lt;/p&gt;
&lt;p&gt;The guidance establishes a clear default: organize controllers around one resource using standard resource actions (&lt;code&gt;index&lt;/code&gt;, &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;store&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, &lt;code&gt;destroy&lt;/code&gt;). When a custom verb like &lt;code&gt;publish&lt;/code&gt;, &lt;code&gt;approve&lt;/code&gt;, or &lt;code&gt;archive&lt;/code&gt; appears, treat it as a &lt;strong&gt;design signal&lt;/strong&gt; — it might represent a separate resource.&lt;/p&gt;
&lt;p&gt;The canonical example models podcast publishing as a dedicated controller:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-php&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;2&quot;&gt;&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;3&quot;&gt;&lt;span class=&quot;l-comment&quot;&gt;// Route&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;4&quot;&gt;&lt;span class=&quot;l-type&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;/published-podcasts/{podcast}&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;PublishedPodcastController&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;5&quot;&gt;    &lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;published-podcasts.store&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;6&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;7&quot;&gt;&lt;span class=&quot;l-type&quot;&gt;Route&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-function-call&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;/published-podcasts/{podcast}&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-punctuation-bracket&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;PublishedPodcastController&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;l-constant&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&amp;#39;destroy&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;8&quot;&gt;    &lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-string&quot;&gt;&amp;#39;published-podcasts.destroy&amp;#39;&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;9&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;10&quot;&gt;&lt;span class=&quot;l-comment&quot;&gt;// Controller&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;11&quot;&gt;&lt;span class=&quot;l-keyword-type&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;l-type&quot;&gt;PublishedPodcastController&lt;/span&gt; &lt;span class=&quot;l-keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;l-type&quot;&gt;Controller&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;12&quot;&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;13&quot;&gt;    &lt;span class=&quot;l-keyword-modifier&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;l-keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;l-function-method&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;Podcast&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;$podcast&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-type&quot;&gt;RedirectResponse&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;14&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;15&quot;&gt;        &lt;span class=&quot;l-variable&quot;&gt;$podcast&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;16&quot;&gt;        &lt;span class=&quot;l-keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;back&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;17&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;18&quot;&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;19&quot;&gt;    &lt;span class=&quot;l-keyword-modifier&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;l-keyword-function&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;l-function-method&quot;&gt;destroy&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-type&quot;&gt;Podcast&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;$podcast&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-type&quot;&gt;RedirectResponse&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;20&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;21&quot;&gt;        &lt;span class=&quot;l-variable&quot;&gt;$podcast&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;-&gt;&lt;/span&gt;&lt;span class=&quot;l-function-method-call&quot;&gt;unpublish&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;22&quot;&gt;        &lt;span class=&quot;l-keyword-return&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;back&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;l-punctuation-delimiter&quot;&gt;;&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;23&quot;&gt;    &lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;24&quot;&gt;&lt;span class=&quot;l-punctuation-bracket&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The guidance ends with an important escape hatch:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Treat a custom verb as a &lt;strong&gt;design signal, not proof&lt;/strong&gt; that another controller is required. Use query parameters for simple filtering, and keep an explicit action route when modeling the operation as a resource would obscure the domain or conflict with established project conventions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Why this matters for AI-assisted development&lt;/h2&gt;
&lt;p&gt;Laravel Boost feeds these rules directly to AI coding agents as context when generating code. Overly prescriptive &quot;always/never&quot; rules cause agents to reject valid patterns and to add unnecessary abstractions (action classes for trivial logic, for example). The new tone should lead to more pragmatic, context-aware suggestions — and fewer unnecessary &quot;Incorrect&quot; rewrites of perfectly reasonable code.&lt;/p&gt;
&lt;p&gt;The shift also signals a broader direction: good AI guidance reads like a &lt;strong&gt;senior developer explaining trade-offs&lt;/strong&gt;, not a linter listing violations.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/ai&quot;&gt;#ai&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-07T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/laravel-boost-best-practices-a-major-tone-shift-august-2026</id>
    <title>🐥 Laravel boost best practices: A major tone shift (August 2026)</title>
    <updated>2026-09-07T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/native-apps-should-be-avoided-whenever-possible" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;What if your smartphone is tracking you more than you think? A detailed article warns against using native apps, revealing their penchant for collecting vast amounts of data, often without users&apos; knowledge. It highlights the case of the recently launched White House app, which claimed zero data collection but was found to be tracking location continuously. The author emphasizes that native apps often inherit permissions from embedded third-party software, posing significant privacy risks. In contrast, websites restrict this level of access, making them a safer choice for most services. With governments and companies frequently buying users&apos; location data, the article advocates for minimizing app usage, reminding readers that many everyday tasks can be handled through web browsers instead. This shift could help protect personal data from prying eyes in an age when surveillance and data commodification are rampant.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://nooneshappy.com/article/native-apps-should-be-avoided-whenever-possible/&quot;&gt;Continue reading on &lt;strong&gt;nooneshappy.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/android&quot;&gt;#android&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-07T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/native-apps-should-be-avoided-whenever-possible</id>
    <title>🔗 Native apps should be avoided whenever possible</title>
    <updated>2026-09-07T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/ibm-i-os-400-the-database-operating-system" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;What if there’s an operating system that challenges traditional views on how systems should be designed? Kamil Pytliński’s article dives into IBM i, an often-overlooked platform that marries its integrated relational database, &lt;code&gt;Db2 for i&lt;/code&gt;, directly with its OS. This unique configuration treats all data as objects, leading to enhanced security and unprecedented performance in online transaction processing since its inception in 1988. With features such as Single Level Storage and the TIMI layer ensuring backward compatibility, IBM i stands as a testament to innovative design, offering capabilities still unmatched today, though access remains limited to high-end IBM hardware. The article showcases how this elite system continues to perform where others struggle, challenging the perception of legacy systems.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://osadmins.com/en/ibm-i-os-400-the-database-operating-system/&quot;&gt;Continue reading on &lt;strong&gt;osadmins.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sysadmin&quot;&gt;#sysadmin&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-07T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/ibm-i-os-400-the-database-operating-system</id>
    <title>🔗 IBM i (OS/400) the database operating system</title>
    <updated>2026-09-07T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/the-schema-doctor-is-in" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;A migration adding a &lt;code&gt;user_id&lt;/code&gt; column can pass all reviews, but later lead to slow queries. This is a problem the new &lt;code&gt;truss:doctor&lt;/code&gt; feature of Truss 1.5 addresses. Designed to identify schema issues before deployment, it flags problems like tables missing primary keys, foreign keys without supporting indexes, and redundant indexes.&lt;/p&gt;
&lt;p&gt;Running &lt;code&gt;php artisan truss:doctor&lt;/code&gt; in your terminal checks for these issues deterministically, which is safe for CI pipelines. The results can also be viewed graphically in the dashboard, offering real-time feedback on database structure without querying actual data. This phase one release includes 13 distinct rules and plans for future enhancements are already in the pipeline, focusing on suppressions and additional checks. Truss has quickly gained traction in the Laravel community, making it a valuable tool for maintaining database integrity.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://albertoarena.it/posts/the-schema-doctor-is-in/&quot;&gt;Continue reading on &lt;strong&gt;albertoarena.it&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/tools&quot;&gt;#tools&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-06T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/the-schema-doctor-is-in</id>
    <title>🔗 The schema doctor is in</title>
    <updated>2026-09-06T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/15-linux-interview-questions-every-sysadmin-should-know" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Most Linux interview lists recycle the same ten questions from a decade ago, and many of the ‘official’ answers are outdated or no longer apply to modern Linux distributions. This updated guide highlights essential knowledge for positions such as Linux System Administrator, DevOps, and Site Reliability Engineer (SRE).&lt;/p&gt;
&lt;p&gt;It covers 15 practical questions designed to help candidates showcase their hands-on experience rather than just theoretical knowledge. Interviewers seek to understand real-world problem-solving skills, so the guide emphasizes the importance of explaining concepts clearly and demonstrating with the right Linux commands.&lt;/p&gt;
&lt;p&gt;Candidates can expect topics like managing processes, checking boot messages, and automating log rotation. With the Linux landscape continuously evolving, being prepared with the latest tools and techniques is crucial for any sysadmin preparing for interviews.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.tecmint.com/10-useful-interview-questions-and-answers-on-linux-commands/&quot;&gt;Continue reading on &lt;strong&gt;www.tecmint.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/linux&quot;&gt;#linux&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sysadmin&quot;&gt;#sysadmin&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-06T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/15-linux-interview-questions-every-sysadmin-should-know</id>
    <title>🔗 15 Linux interview questions every sysadmin should know</title>
    <updated>2026-09-06T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/with-purpose-how-to-win-the-transcontinental-race" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Robin Gemperle set an impressive standard by winning The Transcontinental Race No. 12 in just 10 days, 8 hours, and 55 minutes. Covering 4,694 kilometers from Trondheim, Norway, to Kalamata, Greece, he demonstrated an unparalleled strategy in race preparation. Every decision, from gear selection to routing, was made with the primary goal of victory in mind, showing that even the best need to balance racing hard and resting hard. With precise planning, including ingenious hydration solutions and clever route adjustments, Robin exemplified what it means to race with intent. His methodical approach to rest and efficient setup proved key to maintaining speed throughout the grueling challenge. The article showcases Robin&apos;s dedication and clever tactics, which might just inspire the next wave of ultra-racers aiming for success.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://www.apidura.com/journal/with-purpose-how-to-win-the-transcontinental-race/&quot;&gt;Continue reading on &lt;strong&gt;www.apidura.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sports&quot;&gt;#sports&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-06T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/with-purpose-how-to-win-the-transcontinental-race</id>
    <title>🔗 With purpose: How to win the transcontinental race</title>
    <updated>2026-09-06T08:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/one-line-to-measure-php-memory" rel="alternate"/>
    <content type="html">&lt;p&gt;You&apos;ve just run a long-running Artisan command and production is complaining about memory. Before reaching for Xdebug or a full profiler, there&apos;s a tool already on your machine that answers the question in one line:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-bash&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt;&lt;span class=&quot;l-function-call&quot;&gt;/usr/bin/time&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;-l&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;php&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;artisan&lt;/span&gt; &lt;span class=&quot;l-variable-parameter&quot;&gt;your:command&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;l-operator&quot;&gt;&gt;&amp;&lt;/span&gt;&lt;span class=&quot;l-number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;l-operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;l-function-call&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;l-string&quot;&gt;&quot;maximum resident&quot;&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s it. No code changes, no instrumentation, no deployment.&lt;/p&gt;
&lt;h2&gt;Breaking it down&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/usr/bin/time&lt;/code&gt;&lt;/strong&gt; — the system binary, not the shell built-in. The full path is important: your shell likely has a &lt;code&gt;time&lt;/code&gt; built-in that doesn&apos;t support the &lt;code&gt;-l&lt;/code&gt; flag.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-l&lt;/code&gt;&lt;/strong&gt; — tells it to emit detailed resource usage. On Linux, use &lt;code&gt;-v&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;2&gt;&amp;1&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;time&lt;/code&gt; writes its output to stderr, so you need to redirect it into stdout before you can pipe it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;| grep &quot;maximum resident&quot;&lt;/code&gt;&lt;/strong&gt; — filters down to the one line you care about.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The output looks like this:&lt;/p&gt;
&lt;pre class=&quot;lumis&quot;&gt;&lt;code class=&quot;language-plaintext&quot; translate=&quot;no&quot; tabindex=&quot;0&quot;&gt;&lt;div class=&quot;l-line&quot; data-line=&quot;1&quot;&gt; 147922944  maximum resident set size
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That number is in bytes. Divide by &lt;code&gt;1024 × 1024&lt;/code&gt; and you have the peak RSS in megabytes — in this case, &lt;strong&gt;141 MB&lt;/strong&gt;. That&apos;s the high-water mark of physical RAM the process held at any one moment, and the right number to compare against &lt;code&gt;memory_limit&lt;/code&gt; in &lt;code&gt;php.ini&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Why not &lt;code&gt;memory_get_peak_usage()&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;PHP&apos;s own &lt;code&gt;memory_get_peak_usage(true)&lt;/code&gt; is great when you control the code — add it at the end of &lt;code&gt;handle()&lt;/code&gt; and you see PHP&apos;s internal allocator peak. But it only sees what PHP&apos;s memory manager tracked. The OS-level approach catches everything: the runtime itself, loaded extensions, forked child processes. For commands that spawn subprocesses or load large extensions, the two numbers can diverge meaningfully.&lt;/p&gt;
&lt;p&gt;The OS measurement also requires no deployment — run it against production code on a staging server without touching a line.&lt;/p&gt;
&lt;h2&gt;macOS vs. Linux&lt;/h2&gt;
&lt;p&gt;Swap &lt;code&gt;-l&lt;/code&gt; for &lt;code&gt;-v&lt;/code&gt; on Linux. The field name also changes slightly — look for &lt;code&gt;&quot;Maximum resident set size (kbytes)&quot;&lt;/code&gt; — and note the unit shift from bytes to kilobytes.&lt;/p&gt;
&lt;h2&gt;Drop the grep for more&lt;/h2&gt;
&lt;p&gt;Skip the pipe entirely and &lt;code&gt;/usr/bin/time -l&lt;/code&gt; dumps the full resource table after your command finishes: page faults, context switches, I/O operations, wall time. Worth reading once to understand what your command is actually doing at the OS level.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/laravel&quot;&gt;#laravel&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/php&quot;&gt;#php&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/terminal&quot;&gt;#terminal&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sysadmin&quot;&gt;#sysadmin&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-05T17:00:00Z</published>
    <id>https://www.yellowduck.be/posts/one-line-to-measure-php-memory</id>
    <title>🐥 One line to measure PHP memory</title>
    <updated>2026-09-05T17:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/curl-says-its-fast-your-users-disagree" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;Does your application feel slow even when Curl shows it&apos;s fast? This article dives into the real user experience versus baseline performance metrics. It highlights how relying solely on tools like Curl can mislead developers about actual performance. The article draws attention to user feedback, which often uncovers issues that run deeper than simple response times. It emphasizes the importance of understanding user interactions and suggests that performance metrics should include real-world scenarios instead of just testing tools. Developers are encouraged to look beyond the numbers to measure how users truly experience their applications.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://madewithlove.com/blog/curl-says-its-fast-your-users-disagree/&quot;&gt;Continue reading on &lt;strong&gt;madewithlove.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/best-practice&quot;&gt;#best-practice&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/http&quot;&gt;#http&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-05T13:00:00Z</published>
    <id>https://www.yellowduck.be/posts/curl-says-its-fast-your-users-disagree</id>
    <title>🔗 Curl says it&apos;s fast. Your users disagree.</title>
    <updated>2026-09-05T13:00:00Z</updated>
  </entry>
  <entry>
    <author>
      <name>Pieter Claerhout</name>
      <email>pieter@yellowduck.be</email>
    </author>
    <link href="https://www.yellowduck.be/posts/sqlite-vs-duckdb-on-the-same-16-box-every-cliff-moved-100x" rel="alternate"/>
    <content type="html">&lt;blockquote&gt;
&lt;p&gt;DuckDB outperforms SQLite significantly on a low-cost server, achieving write speeds 4x to 15x faster. In a benchmark that lasted six days, DuckDB managed to serve dashboards at up to 100 times the row count, accommodating a billion metric points within 10.8 GB. Notably, DuckDB&apos;s architecture allowed for efficient data handling and query performance, smoothly surpassing SQLite&apos;s limits in real-world scenarios. For instance, metrics read cliffs increased from 1 million rows in SQLite to 100 million in DuckDB, all while maintaining or improving latency. Such results imply that for self-hosted applications managing large volumes of data, DuckDB may provide a compelling alternative to SQLite, especially in contexts that demand high throughput and scalability. The article also elaborates on the methodology of the tests conducted.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://tracewayapp.com/blog/sqlite-vs-duckdb&quot;&gt;Continue reading on &lt;strong&gt;tracewayapp.com&lt;/strong&gt;&lt;/a&gt;&lt;p&gt;&lt;a href=&quot;https://www.yellowduck.be/tags/reading-list&quot;&gt;#reading-list&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/database&quot;&gt;#database&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/devops&quot;&gt;#devops&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/testing&quot;&gt;#testing&lt;/a&gt; &lt;a href=&quot;https://www.yellowduck.be/tags/sqlite&quot;&gt;#sqlite&lt;/a&gt;&lt;/p&gt;</content>
    <published>2026-09-05T08:00:00Z</published>
    <id>https://www.yellowduck.be/posts/sqlite-vs-duckdb-on-the-same-16-box-every-cliff-moved-100x</id>
    <title>🔗 SQLite vs DuckDB on the same $16 box: every cliff moved 100X</title>
    <updated>2026-09-05T08:00:00Z</updated>
  </entry>
</feed>