<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Home on Buro notes</title><link>https://notes.burelli.xyz/</link><description>Recent content in Home on Buro notes</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Thu, 22 Oct 2026 01:11:58 +0200</lastBuildDate><atom:link href="https://notes.burelli.xyz/index.xml" rel="self" type="application/rss+xml"/><item><title>The proper use of useEffect</title><link>https://notes.burelli.xyz/posts/engineering/reactjs/use-effect/</link><pubDate>Wed, 21 Oct 2026 16:01:56 +0200</pubDate><guid>https://notes.burelli.xyz/posts/engineering/reactjs/use-effect/</guid><description>&lt;h1 id="the-proper-use-of-useeffect"&gt;The proper use of useEffect&lt;/h1&gt;&#10;&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is for &lt;strong&gt;side effects&lt;/strong&gt;: stepping outside React to sync a component with an external system (network, timers, subscriptions, browser APIs). The typical case is async work: a promise whose result arrives after the render.&lt;/p&gt;&#10;&lt;p&gt;Ref: &lt;a href="https://react.dev/learn/synchronizing-with-effects" target="_blank" rel="noopener noreferrer"&gt;Synchronizing with Effects&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2 id="the-standard-shape"&gt;The standard shape&lt;/h2&gt;&#10;&lt;p&gt;It&amp;rsquo;s literally the first page of the &lt;a href="https://react.dev/reference/react/useEffect#reference" target="_blank" rel="noopener noreferrer"&gt;official &lt;code&gt;useEffect&lt;/code&gt; documentation&lt;/a&gt;.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-jsx" data-lang="jsx"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;useEffect&lt;/span&gt;(() =&amp;gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 1. setup: start the side effect&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;AbortController&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;`/api/users/&lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;userId&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;, { &lt;span style="color:#a6e22e"&gt;signal&lt;/span&gt;&lt;span style="color:#f92672"&gt;:&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;signal&lt;/span&gt; })&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;) =&amp;gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#f92672"&gt;!&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;throw&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Error(&lt;span style="color:#e6db74"&gt;`HTTP &lt;/span&gt;&lt;span style="color:#e6db74"&gt;${&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;status&lt;/span&gt;&lt;span style="color:#e6db74"&gt;}&lt;/span&gt;&lt;span style="color:#e6db74"&gt;`&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;res&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; })&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;then&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;setUser&lt;/span&gt;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#66d9ef"&gt;catch&lt;/span&gt;((&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;) =&amp;gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;name&lt;/span&gt; &lt;span style="color:#f92672"&gt;!==&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;AbortError&amp;#39;&lt;/span&gt;) &lt;span style="color:#a6e22e"&gt;setError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;err&lt;/span&gt;);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; });&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// 2. cleanup: stop or neutralize it&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; () =&amp;gt; &lt;span style="color:#a6e22e"&gt;controller&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;abort&lt;/span&gt;();&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}, [&lt;span style="color:#a6e22e"&gt;userId&lt;/span&gt;]); &lt;span style="color:#75715e"&gt;// 3. dependencies: re-run when they change&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; rejects only on network errors: an HTTP error (4xx, 5xx) still resolves, so check &lt;code&gt;res.ok&lt;/code&gt; and throw. All the examples below do it.&lt;/p&gt;</description></item><item><title>Docker containers management</title><link>https://notes.burelli.xyz/posts/engineering/docker-containers/</link><pubDate>Wed, 21 Oct 2026 00:29:59 +0200</pubDate><guid>https://notes.burelli.xyz/posts/engineering/docker-containers/</guid><description>&lt;h1 id="docker-containers-management"&gt;Docker containers management&lt;/h1&gt;&#10;&lt;h2 id="why"&gt;Why&lt;/h2&gt;&#10;&lt;p&gt;Label everything, so you can:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;filter&lt;/strong&gt; metrics (Prometheus) and logs (Loki) by service, env, version&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;track the full chain&lt;/strong&gt;: log/metric → container → image → git commit → code&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="labels"&gt;Labels&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Use Docker labels for all the metadata.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Build labels&lt;/strong&gt;: use the &lt;a href="https://github.com/opencontainers/image-spec/blob/main/annotations.md" target="_blank" rel="noopener noreferrer"&gt;OCI standard keys&lt;/a&gt;, already understood by registries, scanners, Renovate, GitHub, &amp;hellip;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Run labels&lt;/strong&gt;: define your own &lt;strong&gt;prefix&lt;/strong&gt; to avoid collisions with other tools&amp;rsquo; labels (e.g. &lt;code&gt;acme_&lt;/code&gt;).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Label&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Set at&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Example&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;org.opencontainers.image.source&lt;/code&gt; (git repo)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;build&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;https://github.com/acme/orders&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;org.opencontainers.image.revision&lt;/code&gt; (git commit)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;build&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;3f9c2a1&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;org.opencontainers.image.version&lt;/code&gt; (image tag)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;build&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;1.4.0&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;org.opencontainers.image.created&lt;/code&gt; (build date)&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;build&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;2026-10-21T10:00:00Z&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;acme_release_date&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;run&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;2026-10-22T08:30:00Z&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;acme_env&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;run&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;production&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;acme_service&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;run&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;orders&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;acme_host&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;run&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;node-1&lt;/code&gt;&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Image labels are inherited by the containers, so every container carries both build and run labels.&lt;/p&gt;</description></item><item><title>SQL optimization</title><link>https://notes.burelli.xyz/posts/engineering/sql-optimization/</link><pubDate>Wed, 21 Oct 2026 00:03:01 +0200</pubDate><guid>https://notes.burelli.xyz/posts/engineering/sql-optimization/</guid><description>&lt;h1 id="sql-optimization"&gt;SQL optimization&lt;/h1&gt;&#10;&lt;p&gt;Two goals:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;reduce roundtrips&lt;/strong&gt; between the caller (e.g. the BE) and the DB&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;optimize the queries&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="measure-first"&gt;Measure first&lt;/h2&gt;&#10;&lt;p&gt;Don&amp;rsquo;t guess, find what is actually slow: slow query log, &lt;code&gt;pg_stat_statements&lt;/code&gt;, &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; (runs the query and shows real timings, unlike plain &lt;code&gt;EXPLAIN&lt;/code&gt;).&lt;/p&gt;&#10;&lt;h2 id="reading"&gt;Reading&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Ensure indexes&lt;/strong&gt; on the columns used in &lt;code&gt;WHERE&lt;/code&gt;, &lt;code&gt;JOIN&lt;/code&gt; and &lt;code&gt;ORDER BY&lt;/code&gt;.&#10;&lt;ul&gt;&#10;&lt;li&gt;Indexes are not free: they slow down writes and take space. Index what your queries use, not everything.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Composite indexes&lt;/strong&gt;: column order matters, put equality filters before range filters.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Covering indexes&lt;/strong&gt;: include the selected columns so the DB doesn&amp;rsquo;t need to read the table.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Check how you wrote the query&lt;/strong&gt;: select only the columns you need, avoid functions on indexed columns.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Avoid N+1&lt;/strong&gt; (classic with ORMs): fetch related rows for the whole batch at once with eager loading or &lt;code&gt;WHERE id IN (...)&lt;/code&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;CREATE&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;INDEX&lt;/span&gt; idx_orders_customer_created &lt;span style="color:#66d9ef"&gt;ON&lt;/span&gt; orders (customer_id, created_at) INCLUDE (total);&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;EXPLAIN&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;ANALYZE&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;SELECT&lt;/span&gt; id, total &lt;span style="color:#66d9ef"&gt;FROM&lt;/span&gt; orders&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;WHERE&lt;/span&gt; customer_id &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;42&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;AND&lt;/span&gt; created_at &lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;2026-01-01&amp;#39;&lt;/span&gt;;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="reading-many-rows"&gt;Reading many rows&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Use pagination&lt;/strong&gt;: never load the whole table at once.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Load in batches&lt;/strong&gt; (e.g. 500 rows per call), process them, then write the results in batch (see below).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;Prefer keyset pagination over &lt;code&gt;OFFSET&lt;/code&gt;, it stays fast on big tables:&lt;/p&gt;</description></item><item><title>Me</title><link>https://notes.burelli.xyz/posts/me/</link><pubDate>Sat, 21 Sep 2024 13:13:56 +0200</pubDate><guid>https://notes.burelli.xyz/posts/me/</guid><description>&lt;h1 id="me"&gt;Me&lt;/h1&gt;&#10;&lt;p&gt;Who am I?&lt;/p&gt;</description></item><item><title>what is this</title><link>https://notes.burelli.xyz/posts/what-is-this/</link><pubDate>Sat, 21 Sep 2024 13:13:56 +0200</pubDate><guid>https://notes.burelli.xyz/posts/what-is-this/</guid><description>&lt;h1 id="what-is-this"&gt;What is this&lt;/h1&gt;&#10;&lt;p&gt;This is not a blog. This is a collection of notes that I update when I want by adding, removing or changing stuff.&lt;br&gt;&#10;My ideas change, I change, I have new experences, so these notes will change accordly without warning and without the need for consistency.&lt;/p&gt;&#10;&lt;p&gt;These are my notes, they don&amp;rsquo;t claim to be right or wrong, just my notes.&lt;/p&gt;&#10;&lt;p&gt;Hope these notes could help someone.&lt;/p&gt;</description></item><item><title>who I am</title><link>https://notes.burelli.xyz/posts/who-i-am/</link><pubDate>Sat, 21 Sep 2024 13:13:56 +0200</pubDate><guid>https://notes.burelli.xyz/posts/who-i-am/</guid><description>&lt;h1 id="who-i-am"&gt;Who I am&lt;/h1&gt;&#10;&lt;p&gt;I&amp;rsquo;m Buro.&lt;/p&gt;</description></item></channel></rss>