<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ace-2504</title>
    <description>The latest articles on DEV Community by Ace-2504 (@ace2504).</description>
    <link>https://dev.to/ace2504</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3565080%2F7da89d83-ca34-469a-ae5b-435de1ae7d3f.png</url>
      <title>DEV Community: Ace-2504</title>
      <link>https://dev.to/ace2504</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ace2504"/>
    <language>en</language>
    <item>
      <title>The Bugs That Hide Behind "It Works": Debugging a Multithreaded C++ Proxy Server</title>
      <dc:creator>Ace-2504</dc:creator>
      <pubDate>Mon, 08 Jun 2026 08:37:27 +0000</pubDate>
      <link>https://dev.to/ace2504/the-bugs-that-hide-behind-it-works-debugging-a-multithreaded-c-proxy-server-1373</link>
      <guid>https://dev.to/ace2504/the-bugs-that-hide-behind-it-works-debugging-a-multithreaded-c-proxy-server-1373</guid>
      <description>&lt;p&gt;As a student, one of the biggest lessons I've picked up is that a program which compiles and runs is not the same as a program that is correct. It really hit home while I was building a multithreaded C++ network proxy server — a project that authenticates users with SHA-256, enforces role-based website filtering, and caches HTTP responses using a custom LRU cache.&lt;/p&gt;

&lt;p&gt;The happy path worked on pretty early. The real learning started when I went looking for the bugs that &lt;em&gt;don't&lt;/em&gt; announce themselves — the ones that only show up under concurrency, fragmented packets, or heavy load. Here are four of the most interesting and challenging issues I ran into and how I fixed them.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Thread Pool That Never Detached
&lt;/h2&gt;

&lt;p&gt;The proxy spawns 20 persistent worker threads at startup. The idea was simple: create the workers, then detach them from the main thread so they run independently.&lt;/p&gt;

&lt;p&gt;The bug was an ordering mistake. My detachment loop ran &lt;em&gt;before&lt;/em&gt; the threads were created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;detach&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// workers is still EMPTY here&lt;/span&gt;
&lt;span class="n"&gt;workers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emplace_back&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;            &lt;span class="c1"&gt;// threads created afterward&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the vector was empty when the loop ran, the iteration did nothing — the threads were never actually detached. It's the kind of bug that compiles cleanly, passes a quick test, and then causes resource and lifecycle problems once the server runs for a while.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; I changed the order of the code. First, I created all the worker threads. Then, I detached them. What I learned: when working with threads, the order of setup steps matters. It is part of making the program correct, not just a small coding detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. A Data Race Hiding Inside the Logger
&lt;/h2&gt;

&lt;p&gt;My logging system looked thread-safe. Every write to &lt;code&gt;proxy.log&lt;/code&gt; was guarded by a &lt;code&gt;std::lock_guard&amp;lt;std::mutex&amp;gt;&lt;/code&gt;, so 20 threads writing at once could never scramble the file.&lt;/p&gt;

&lt;p&gt;But the timestamps came from &lt;code&gt;ctime(&amp;amp;now)&lt;/code&gt;. Under POSIX, &lt;code&gt;ctime&lt;/code&gt; returns a pointer to a &lt;strong&gt;globally shared static buffer&lt;/strong&gt;. My mutex protected the file stream — it did NOT protect that hidden global buffer. So two threads formatting timestamps at the same time could corrupt each other's strings, even though the file writes themselves were perfectly safe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; switched to the thread-safe version, &lt;code&gt;ctime_r()&lt;/code&gt;, which writes into a buffer. The lesson was a subtle one: locking the &lt;em&gt;obvious&lt;/em&gt; shared resource isn't enough. You also have to think about the shared state hiding inside the standard library functions you're calling.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The TCP Read That Assumed Too Much
&lt;/h2&gt;

&lt;p&gt;My request handler made a single call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client_socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This assumes that one &lt;code&gt;recv()&lt;/code&gt; gives you one complete HTTP request. TCP makes no such promise. TCP is a &lt;strong&gt;byte stream&lt;/strong&gt;, not a message protocol — a request can arrive split across several packets. If a header got cut in half, my &lt;code&gt;request.find("Host:")&lt;/code&gt; parsing would just fail, and a valid request would get dropped for no obvious reason.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; replaced the single read with a loop that keeps calling &lt;code&gt;recv()&lt;/code&gt; until the &lt;code&gt;\r\n\r\n&lt;/code&gt; header terminator has fully arrived. For my proxy, this handled the request headers; a fuller HTTP implementation would also need to handle bodies using &lt;code&gt;Content-Length&lt;/code&gt; or chunked transfer encoding. This turned out to be one of the most common (and most underestimated) mistakes in network programming: treating a stream like a neat sequence of separate messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Defending Against Hanging Connections
&lt;/h2&gt;

&lt;p&gt;Worker threads are a limited resource — I only have 20. A single unresponsive remote server that never closes its connection could tie up a worker forever, and 20 of those stalls would quietly take the whole proxy offline.&lt;/p&gt;

&lt;p&gt;My defense was setting a receive timeout with &lt;code&gt;setsockopt()&lt;/code&gt; using &lt;code&gt;SO_RCVTIMEO&lt;/code&gt;, set to one second. If a remote server goes quiet mid-response, the thread frees itself instead of hanging forever. Combined with proper HTTP status codes sent back to the client — &lt;code&gt;502 Bad Gateway&lt;/code&gt; when DNS resolution fails, &lt;code&gt;504 Gateway Timeout&lt;/code&gt; when the upstream stalls — the proxy fails gracefully instead of dying silently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Debugging Concurrent Code Taught Me
&lt;/h2&gt;

&lt;p&gt;The common thread across all four bugs is the same: &lt;strong&gt;concurrency and networking break the assumptions that work perfectly in single-threaded, single-packet test runs.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup &lt;em&gt;order&lt;/em&gt; is part of correctness, not a detail.&lt;/li&gt;
&lt;li&gt;A mutex protects what it wraps — and nothing else, including hidden global state.&lt;/li&gt;
&lt;li&gt;The network gives you a byte stream, never a tidy message.&lt;/li&gt;
&lt;li&gt;Limited resources need timeouts, or one bad peer takes everything down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these bugs threw an error or crashed the compiler. They lived in the gap between "it runs" and "it is correct" — and for me, closing that gap has been the most rewarding part of learning systems programming.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you've built low-level networked systems in C++, I'd love to hear which subtle concurrency bug cost you the most time to track down.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>systems</category>
      <category>networking</category>
      <category>learning</category>
    </item>
    <item>
      <title>Turning Behaviour into Climate Accountability</title>
      <dc:creator>Ace-2504</dc:creator>
      <pubDate>Tue, 24 Feb 2026 18:57:22 +0000</pubDate>
      <link>https://dev.to/ace2504/turning-behaviour-into-climate-accountability-3pph</link>
      <guid>https://dev.to/ace2504/turning-behaviour-into-climate-accountability-3pph</guid>
      <description>&lt;p&gt;One winter morning in Delhi, the AQI crossed 460 — officially hazardous. Schools shut. Hospitals filled. Transport slowed. Offices continued. Every day, millions of environmental decisions are made. Whether to drive or take public transport. Whether to allow remote work. Whether to burn waste or compost. These choices influence emissions — yet we rarely measure the pollution that did not happen because of them.&lt;/p&gt;

&lt;p&gt;That is the missing piece.&lt;/p&gt;

&lt;p&gt;Most environmental systems measure what exists: current emissions, fuel consumption, air quality levels. They do not formally measure avoided emissions. Counterfactual attribution addresses this gap by comparing two clearly defined scenarios:&lt;/p&gt;

&lt;p&gt;Business-as-usual baseline — what would have happened&lt;br&gt;
Verified alternative — what actually occurred&lt;/p&gt;

&lt;p&gt;Impact = Baseline − Verified Alternative.&lt;/p&gt;

&lt;p&gt;A Practical Example: Urban Commuting&lt;br&gt;
Consider a professional living 14 km from work. A 28 km daily round trip in a petrol car (≈ 120 g CO₂/km) results in about 3.36 kg CO₂ per day. Across 240 working days, that equals approximately 806 kg CO₂ annually. That is the baseline.&lt;/p&gt;

&lt;p&gt;Now introduce two behavioural shifts:&lt;/p&gt;

&lt;p&gt;Work from home two days per week → avoids ~322 kg per year&lt;br&gt;
Shift to electric metro on remaining days (≈ 15 g CO₂/km) → saves ~423 kg&lt;/p&gt;

&lt;p&gt;Total avoided emissions ≈ 745 kg CO₂ Remaining footprint ≈ 61 kg&lt;/p&gt;

&lt;p&gt;That is a reduction of over 90%, derived from a measurable behavioural delta — not offsets, not assumptions.&lt;/p&gt;

&lt;p&gt;If the remaining 61 kg is neutralised through verified sequestration (e.g., monitored urban trees at ~10 kg per tree annually), the commuting footprint approaches net zero.&lt;/p&gt;

&lt;p&gt;Baseline → Reduction → Net Impact. Each step is quantifiable.&lt;/p&gt;

&lt;p&gt;Preventing Double Counting&lt;br&gt;
A critical issue emerges: duplication.&lt;/p&gt;

&lt;p&gt;If an employee reports work-from-home reductions, and their employer's HR department also reports the same reduction in ESG disclosures, total claimed impact exceeds actual impact.&lt;/p&gt;

&lt;p&gt;To prevent this, the framework introduces a non-duplication constraint.&lt;/p&gt;

&lt;p&gt;Let:&lt;/p&gt;

&lt;p&gt;Δ_total = Verified avoided emissions&lt;br&gt;
C_i = Claim attributed to entity i&lt;/p&gt;

&lt;p&gt;The system enforces:&lt;/p&gt;

&lt;p&gt;Σ Cᵢ ≤ Δ_total&lt;/p&gt;

&lt;p&gt;No combination of claims may exceed the verified delta.&lt;/p&gt;

&lt;p&gt;Each reduction event is assigned:&lt;/p&gt;

&lt;p&gt;A unique registry ID&lt;br&gt;
A defined ownership tag&lt;br&gt;
A claim status flag&lt;/p&gt;

&lt;p&gt;Work-from-home emissions may be attributed to the enabling institution, while individual dashboards reflect behavioural contribution — without generating duplicate claimable credits unless formally allocated.&lt;/p&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;p&gt;Measurability&lt;br&gt;
Additionality&lt;br&gt;
Non-duplication&lt;br&gt;
Audit defensibility&lt;/p&gt;

&lt;p&gt;Without duplication control, avoided-emission accounting collapses under verification.&lt;/p&gt;

&lt;p&gt;Enterprise Implications&lt;br&gt;
Most sustainability reports rely on estimated participation and averaged emission factors. A verification-first counterfactual architecture instead:&lt;/p&gt;

&lt;p&gt;Establishes defined baselines&lt;br&gt;
Verifies behavioural change in a privacy-preserving manner&lt;br&gt;
Models avoided emissions at corridor level&lt;br&gt;
Applies attribution constraints&lt;br&gt;
Produces audit-ready metrics&lt;/p&gt;

&lt;p&gt;Under such a system, work-from-home is not merely HR flexibility. It becomes measurable climate infrastructure.&lt;/p&gt;

&lt;p&gt;The Broader Shift&lt;br&gt;
This logic applies anywhere a conservative baseline can be defined:&lt;/p&gt;

&lt;p&gt;Agricultural burn avoidance&lt;br&gt;
Household waste diversion&lt;br&gt;
Fuel switching in buildings&lt;br&gt;
Distributed renewable adoption&lt;br&gt;
Industrial efficiency upgrades&lt;/p&gt;

&lt;p&gt;For decades, climate systems focused on measuring what we emit.&lt;/p&gt;

&lt;p&gt;The next frontier is measuring what we prevent — without inflation, without duplication, and without ambiguity.&lt;/p&gt;

&lt;p&gt;Climate accountability will not be built on slogans.&lt;/p&gt;

&lt;p&gt;It will be built on baselines, constraints, and verifiable delta.&lt;/p&gt;

&lt;p&gt;Patent Filed, 2026. A technical paper detailing the verification-first MRV architecture, statistical bias bounds, and attribution constraints is under preparation.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>datascience</category>
      <category>science</category>
    </item>
    <item>
      <title>How McKinsey Frameworks Fixed My Scattered API</title>
      <dc:creator>Ace-2504</dc:creator>
      <pubDate>Sun, 04 Jan 2026 15:51:33 +0000</pubDate>
      <link>https://dev.to/ace2504/how-structured-thinking-fixed-my-api-design-a-case-study-i1n</link>
      <guid>https://dev.to/ace2504/how-structured-thinking-fixed-my-api-design-a-case-study-i1n</guid>
      <description>&lt;p&gt;While building the backend for &lt;strong&gt;Ace Rentals&lt;/strong&gt;, I realized that my authorization logic, although functionally correct, felt increasingly fragile. Ownership checks were scattered across multiple routes, duplicated in several places, and easy to forget when adding new endpoints. Over time, this made the system harder to reason about and increased the risk of subtle security gaps.&lt;/p&gt;

&lt;p&gt;Rather than continuing with incremental fixes, I stepped back and redesigned authorization as a system-level concern using centralized middleware. This article explains how I identified the issue, how I reasoned about the redesign, how it was implemented, and what improved as a result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Previous Authorization Approach
&lt;/h2&gt;

&lt;p&gt;Authorization checks were implemented directly inside individual route handlers. Each protected endpoint contained its own logic to verify whether the current user was allowed to perform the requested action.&lt;/p&gt;

&lt;p&gt;While this approach worked initially, it introduced several challenges as the application grew:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The same ownership logic was copied across multiple routes
&lt;/li&gt;
&lt;li&gt;Route handlers mixed business logic with authorization concerns
&lt;/li&gt;
&lt;li&gt;Adding new endpoints required manual checks, increasing the chance of mistakes
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system did not fail outright, but correctness increasingly depended on careful and repetitive implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Identifying the Design Issue
&lt;/h2&gt;

&lt;p&gt;The problem was not a missing check or a faulty condition—it was a structural issue. Authorization was treated as an implementation detail instead of a rule enforced consistently by the architecture.&lt;/p&gt;

&lt;p&gt;This meant security relied on developer memory rather than system guarantees. As the number of routes increased, so did the effort required to maintain consistency and confidence in the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Analysis and Decision-Making
&lt;/h2&gt;

&lt;p&gt;To avoid patching individual routes, I analyzed the problem at a design level.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I used &lt;strong&gt;MECE-style analysis&lt;/strong&gt; to verify whether authorization was applied consistently across all relevant routes. This exposed gaps and overlap in enforcement.
&lt;/li&gt;
&lt;li&gt;I compared alternative approaches and found that &lt;strong&gt;centralized middleware&lt;/strong&gt; offered the best balance between reuse, clarity, and maintainability.
&lt;/li&gt;
&lt;li&gt;I set clear constraints for the refactor—no change in behavior, minimal surface area, and focused scope—to avoid unnecessary complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structured approach helped ensure the redesign addressed the root cause rather than its symptoms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authorization Redesign and Implementation
&lt;/h2&gt;

&lt;p&gt;Authorization was elevated to a system-level concern and implemented through middleware:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ownership checks were consolidated into a single, reusable middleware function
&lt;/li&gt;
&lt;li&gt;API endpoints were reorganized around resources rather than actions, improving clarity
&lt;/li&gt;
&lt;li&gt;Authorization was enforced early in the request pipeline, before any business logic executed
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this setup, routes automatically inherit authorization rules. Developers no longer need to remember to reapply checks when adding or modifying endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observed Impact of the Redesign
&lt;/h2&gt;

&lt;p&gt;The redesign produced clear and measurable improvements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization logic now exists in one place instead of being duplicated
&lt;/li&gt;
&lt;li&gt;All protected routes enforce authorization consistently by default
&lt;/li&gt;
&lt;li&gt;Maintenance effort and regression risk were significantly reduced
&lt;/li&gt;
&lt;li&gt;Resource relationships are clearer through resource-based routing
&lt;/li&gt;
&lt;li&gt;Route handlers are simpler and focus only on business logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A qualitative review showed that core domain logic is stable. Remaining risk is isolated to shared authorization middleware, where it is explicit, visible, and easier to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Learning
&lt;/h2&gt;

&lt;p&gt;Repeated logic is often a signal of a deeper design issue. Treating security as a structural concern—rather than a manual step—leads to systems that are easier to maintain, extend, and trust over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Decisions and Learnings
&lt;/h2&gt;

&lt;p&gt;This article provides a high-level summary of the decisions and outcomes from redesigning authorization in Ace Rentals.&lt;/p&gt;

&lt;p&gt;For a deeper look into my &lt;strong&gt;learning experience&lt;/strong&gt;—including diagrams, structured reasoning, trade-offs, and implementation details—you can read the full write-up here:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://ace-2504.github.io/api-design-blog/" rel="noopener noreferrer"&gt;https://ace-2504.github.io/api-design-blog/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The full version documents the complete thought process and lessons learned while designing and refactoring the system.&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>systemdesign</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
