<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged chaosengineering</title>
<link>https://coderlegion.com/tag/chaosengineering</link>
<description>Powered by Question2Answer</description>
<item>
<title>Chaos Network Proxy</title>
<link>https://coderlegion.com/8696/chaos-network-proxy</link>
<description>&lt;p&gt;&lt;img src=&quot;https://coderlegion.com/?qa=blob&amp;amp;qa_blobid=7083163861350358817&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Story: Why I built Chaos Proxy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We've all been there. The feature works perfectly on &lt;code&gt;localhost&lt;/code&gt;. The E2E tests pass with flying colors. Then we deploy to production, and users on 3G networks start complaining that the app freezes, crashes, or—worst of all—&lt;strong&gt;charges them twice&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I realized that our CI pipelines were living in a fantasy world of &lt;strong&gt;0ms latency and 100% uptime&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I wanted to simulate &quot;Bad Network&quot; conditions automatically in GitHub Actions, specifically for &lt;strong&gt;mobile apps&lt;/strong&gt; and &lt;strong&gt;backend idempotency checks&lt;/strong&gt;. I tried mocking requests in Playwright, but that didn't cover native Android/iOS emulators. I tried local proxies, but they were hard to script.&lt;/p&gt;
&lt;p&gt;So I built &lt;strong&gt;Chaos Proxy&lt;/strong&gt; —a cloud-based, programmable Chaos Proxy designed for CI/CD.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How it works&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Debuggo isn't just a GUI tool. It’s an &lt;strong&gt;API-first platform&lt;/strong&gt;. You can treat your network infrastructure like code.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create&lt;/strong&gt;: Your CI script calls our API to spin up an isolated, ephemeral proxy container.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connect&lt;/strong&gt;: You route your E2E test traffic (Web, Android, iOS) through this proxy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Break&lt;/strong&gt;: You send API commands to inject latency, trigger 503 errors, or tamper with headers in real-time.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=NbPPoqCv3mY&quot;&gt;Demo: Simulating 503 Errors in Chrome (Visual)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;API for CI/CD&lt;/strong&gt;: Spin up and destroy proxies programmatically. No long-living servers to manage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The &quot;Rage Click&quot; Test&lt;/strong&gt;: Inject 3 seconds of latency into specific endpoints (e.g., &lt;code&gt;/api/pay&lt;/code&gt;) to ensure your UI disables buttons correctly before the user clicks twice.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native Mobile Support&lt;/strong&gt;: Since it works at the network level (HTTP Proxy), it supports Android Emulators and iOS Simulators perfectly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Response Fuzzing&lt;/strong&gt;: Automatically tamper with JSON bodies to see if your app crashes on malformed data.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;⚡️ &lt;strong&gt;See it in action&lt;/strong&gt;&lt;br&gt;
Here is how simple it is to inject a 503 Service Unavailable error into your checkout flow using curl:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -X PUT https://api.debuggo.app/v1/sessions/$SESSION_ID/rules \
  -H &quot;Authorization: Bearer $API_KEY&quot; \
  -d '{
    &quot;rules&quot;: [
      {
        &quot;url_pattern&quot;: &quot;*/api/checkout&quot;,
        &quot;failure_rate&quot;: 50,
        &quot;error_code&quot;: 503
      }
    ]
  }'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=x_S-guPwPEk&quot;&gt;Demo: Automating Network Chaos via Terminal (CLI)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How you can get involved&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I just launched the &lt;strong&gt;Public API Beta&lt;/strong&gt;. I am looking for QA Engineers and DevOps folks who are tired of &quot;flaky&quot; apps and want to build true resilience.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Try the Free Tier: You can start manually or via API for free.&lt;/li&gt;
&lt;li&gt;Break your App: Try the &quot;Rage Click&quot; test (Tip #5 on our blog).&lt;/li&gt;
&lt;li&gt;Feedback: Let me know what integration you need next!&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Stop trusting localhost. Start testing reality.&lt;/p&gt;
</description>
<category>Dev Tools</category>
<guid isPermaLink="true">https://coderlegion.com/8696/chaos-network-proxy</guid>
<pubDate>Sun, 21 Dec 2025 17:42:58 +0000</pubDate>
</item>
<item>
<title>Announcing Chaos Proxy API: Automate Network Chaos in CI/CD</title>
<link>https://coderlegion.com/8694/announcing-chaos-proxy-api-automate-network-chaos-in-ci-cd</link>
<description>&lt;p&gt;&lt;strong&gt;Moving Beyond &quot;Localhost&quot; Testing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Until now, Debuggo has been a fantastic tool for manual testing. You spin up a proxy, connect your phone, and verify how your app handles a 503 error or high latency. It works great for ad-hoc debugging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But manual testing doesn't scale.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You cannot ask your QA team to manually verify &quot;Offline Mode&quot; handling on every single Pull Request. You cannot manually check if your payment gateway handles double-clicks correctly before every deploy.&lt;/p&gt;
&lt;p&gt;To build truly resilient apps, you need &lt;strong&gt;Continuous Chaos&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Today, we are launching the &lt;strong&gt;Chaos Proxy API&lt;/strong&gt;. Now you can programmatically create proxies, configure chaos rules, and tear them down—all within your CI/CD pipeline (GitHub Actions, GitLab CI, Jenkins).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Architecture: How it works in CI&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The API gives you full control over the lifecycle of a Chaos Proxy directly from your pipeline scripts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create&lt;/strong&gt;: Spin up a fresh, isolated proxy instance on demand (&lt;code&gt;POST /sessions&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure&lt;/strong&gt;: Apply chaos rules (latency, errors, body tampering) via JSON (&lt;code&gt;PUT /rules&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Certify&lt;/strong&gt;: Download the CA certificate to install on Android Emulators or iOS Simulators (&lt;code&gt;GET /certs&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test&lt;/strong&gt;: Run your E2E suite (Playwright, Appium, Cypress) routing traffic through the proxy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Destroy&lt;/strong&gt;: Clean up resources when the test finishes (&lt;code&gt;DELETE /sessions&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Real-World Example&lt;/strong&gt;: GitHub Actions&lt;br&gt;
Here is a complete workflow. This script spins up a proxy, injects a &lt;strong&gt;3-second latency&lt;/strong&gt; to simulate a slow network, runs tests to ensure the UI handles &quot;Rage Clicks&quot; correctly, and then shuts everything down.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name:  Chaos E2E Tests

on: [push]

jobs:
  chaos-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      # 1. Start the Proxy
      - name:  Start Debuggo Proxy
        id: start_proxy
        run: |
          RESPONSE=$(curl -s -X POST https://chaos-proxy.debuggo.app/api/v1/sessions \
            -H &quot;Authorization: Bearer ${{ secrets.DEBUGGO_API_KEY }}&quot;)
          
          # Extract and save details to ENV
          echo &quot;PROXY_ID=$(echo $RESPONSE | jq -r .id)&quot; &amp;gt;&amp;gt; $GITHUB_ENV
          echo &quot;PROXY_HOST=$(echo $RESPONSE | jq -r .host)&quot; &amp;gt;&amp;gt; $GITHUB_ENV
          echo &quot;PROXY_PORT=$(echo $RESPONSE | jq -r .port)&quot; &amp;gt;&amp;gt; $GITHUB_ENV
          echo &quot;PROXY_AUTH=$(echo $RESPONSE | jq -r .auth)&quot; &amp;gt;&amp;gt; $GITHUB_ENV

      # 2. Configure Chaos (The &quot;Bad 3G&quot; Simulation)
      - name:  Configure Chaos Rules
        run: |
          curl -X PUT https://chaos-proxy.debuggo.app/api/v1/sessions/$PROXY_ID/rules \
            -H &quot;Authorization: Bearer ${{ secrets.DEBUGGO_API_KEY }}&quot; \
            -H &quot;Content-Type: application/json&quot; \
            -d '{
              &quot;rules&quot;: [
                {
                  &quot;url_pattern&quot;: &quot;*/api/checkout&quot;,
                  &quot;delay&quot;: 3000,
                  &quot;error_code&quot;: null
                }
              ]
            }'

      # 3. Run Tests
      - name:  Run Playwright Tests
        run: |
          # Route traffic through the authenticated proxy
          export HTTPS_PROXY=&quot;http://$PROXY_AUTH@$PROXY_HOST:$PROXY_PORT&quot;
          npx playwright test

      # 4. Cleanup (Always run this, even if tests fail)
      - name:  Cleanup
        if: always()
        run: |
          curl -X DELETE https://chaos-proxy.debuggo.app/api/v1/sessions/$PROXY_ID \
            -H &quot;Authorization: Bearer ${{ secrets.DEBUGGO_API_KEY }}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;API Reference&lt;/strong&gt;&lt;br&gt;
Use these endpoints to integrate Chaos Proxy into your custom scripts.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;br&gt;
Authenticate all requests by including your API Key in the header. You can generate a key in your Dashboard Settings.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Authorization: Bearer dbg_ci_YOUR_KEY
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Start Proxy Session&lt;br&gt;
Creates a new isolated proxy container. Returns the host, port, and credentials.&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;code&gt;POST /api/v1/sessions&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Response:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;id&quot;: &quot;sess_abc123&quot;,
  &quot;host&quot;: &quot;proxy-us-east.debuggo.app&quot;,
  &quot;port&quot;: 10245,
  &quot;auth&quot;: &quot;user:pass&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Configure Rules&lt;br&gt;
Updates the chaos logic in real-time. You can change rules mid-test (e.g., test success first, then inject failure).&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;code&gt;PUT /api/v1/sessions/{session_id}/rules&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Body Example:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &quot;rules&quot;: [
    {
      &quot;url_pattern&quot;: &quot;*/api/v1/checkout&quot;,
      &quot;failure_rate&quot;: 100,
      &quot;error_code&quot;: 503,
      &quot;delay&quot;: 0
    },
    {
      &quot;url_pattern&quot;: &quot;*/api/v1/search&quot;,
      &quot;delay&quot;: 2000
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Download CA Certificate&lt;br&gt;
Retrieves the Root CA certificate. Essential for automated setup of Android Emulators or iOS Simulators in CI.&lt;ul&gt;
&lt;li&gt;Endpoint: GET /api/v1/certs/ca.pem&lt;/li&gt;
&lt;li&gt;Usage:&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -O https://chaos-proxy.debuggo.app/api/v1/certs/ca.pem
# Then install via adb
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Stop Session&lt;br&gt;
Stops the proxy and releases the port.&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;code&gt;DELETE /api/v1/sessions/{session_id}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;Why automate Chaos?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Catch Regressions in &quot;Unhappy Paths&quot;&lt;/strong&gt; Developers often break error handling logic because they rarely see errors locally. Automating a 500 Error test ensures your &quot;Something went wrong&quot; screen never breaks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Validate Idempotency&lt;/strong&gt; By injecting latency into your payment endpoints during CI, you can verify that your backend correctly handles duplicate requests (Rage Clicks) before they reach production.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native Mobile Testing&lt;/strong&gt; Unlike Playwright’s built-in page.route (which only works in a browser context), Debuggo works at the system level. This allows you to test &lt;strong&gt;Native Android and iOS apps&lt;/strong&gt; running in emulators within your CI pipeline.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ready to break your build (on purpose)? &lt;a rel=&quot;nofollow&quot; href=&quot;https://chaos-proxy.debuggo.app/&quot;&gt;Get your API Key&lt;/a&gt;.&lt;/p&gt;
</description>
<category>QA Best Practices</category>
<guid isPermaLink="true">https://coderlegion.com/8694/announcing-chaos-proxy-api-automate-network-chaos-in-ci-cd</guid>
<pubDate>Sun, 21 Dec 2025 14:51:08 +0000</pubDate>
</item>
<item>
<title>The &quot;Spinner of Death&quot;: Why Localhost Latency is Lying to You</title>
<link>https://coderlegion.com/8636/the-spinner-of-death-why-localhost-latency-is-lying-to-you</link>
<description>&lt;p&gt;&lt;strong&gt;The &quot;Localhost&quot; Bias&lt;/strong&gt;&lt;br&gt;
We've all been there.&lt;/p&gt;
&lt;p&gt;On your machine, the API responds in &lt;strong&gt;5ms&lt;/strong&gt;. The UI updates instantly. You click &quot;Submit,&quot; the modal closes, and you move on to the next ticket. Status: &lt;strong&gt;Done&lt;/strong&gt;. ✅&lt;/p&gt;
&lt;p&gt;But on a user's 4G connection in a subway tunnel, that same API call takes &lt;strong&gt;2 seconds&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Because you tested on localhost (Gigabit Fiber), you missed critical race conditions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;️ &lt;strong&gt;The Double-Click Bug&lt;/strong&gt;: The user clicks &quot;Submit&quot; twice because &quot;nothing happened,&quot; charging their credit card twice.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Infinite Spinner&lt;/strong&gt;: The loader gets stuck forever because a packet was dropped.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;️ &lt;strong&gt;Race Conditions&lt;/strong&gt;: Data arrives out of order, overwriting the user's input.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Your app feels fast because you are cheating. &lt;strong&gt;0ms latency is a lie&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Wrong Solution&lt;/strong&gt;: &lt;code&gt;time.sleep()&lt;/code&gt;&lt;br&gt;
I often see tests that look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# ❌ Don't do this
page.click(&quot;#submit&quot;)
time.sleep(2) # Simulating &quot;network lag&quot;
expect(page.locator(&quot;.success&quot;)).to_be_visible()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;why-this-fails-sleep-just-pauses-the-test-execution-script-the-browser-engine-itself-is-still-blazing-fast-it-doesn-t-simulate-network-queues-slow-handshakes-or-constrained-bandwidth-you-aren-t-testing-the-network-you-re-just-making-your-test-suite-slower-&quot;&gt;&lt;strong&gt;Why this fails&lt;/strong&gt;: &lt;code&gt;sleep()&lt;/code&gt; just pauses the test execution script. The browser engine itself is still blazing fast. It doesn't simulate network queues, slow handshakes, or constrained bandwidth. You aren't testing the network; you're just making your test suite slower.&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The Right Solution: Network Throttling (CDP)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To test this properly in automation, you need to talk directly to the browser engine. You need to tell Chrome: &quot;&lt;em&gt;Pretend you are on a terrible 50kb/s connection.&lt;/em&gt;&quot;&lt;/p&gt;
&lt;p&gt;We can do this using the &lt;strong&gt;Chrome DevTools Protocol (CDP)&lt;/strong&gt; within Playwright. This forces the browser to handle packet delays and loading states exactly as a real user would experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Code (Python + Playwright)&lt;/strong&gt;&lt;br&gt;
Here is how to inject a &quot;Bad 3G&quot; connection into your test:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from playwright.sync_api import Page, expect

def test_slow_network_handling(page: Page):
    # 1. Connect to Chrome DevTools Protocol (CDP)
    # This gives us low-level access to the browser
    client = page.context.new_cdp_session(page)
    
    # 2.  CHAOS: Emulate &quot;Bad 3G&quot;
    # Latency: 2000ms (2 seconds)
    # Throughput: 50kb/s (Very slow)
    client.send(&quot;Network.emulateNetworkConditions&quot;, {
        &quot;offline&quot;: False,
        &quot;latency&quot;: 2000, 
        &quot;downloadThroughput&quot;: 50 * 1024,
        &quot;uploadThroughput&quot;: 50 * 1024
    })

    page.goto(&quot;https://myapp.com/search&quot;)
    
    # 3. Trigger the slow action
    page.fill(&quot;#search-box&quot;, &quot;Playwright&quot;)
    page.click(&quot;#search-btn&quot;)

    # 4. Resilience Assertion
    
    # Check 1: Does the UI prevent double submission?
    expect(page.locator(&quot;#search-btn&quot;)).to_be_disabled()
    
    # Check 2: Does the user get immediate feedback?
    expect(page.locator(&quot;.loading-spinner&quot;)).to_be_visible()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;why-this-matters-this-test-proves-your-ui-provides-feedback-if-a-user-clicks-a-button-and-waits-2-seconds-with-no-visual-feedback-they-will-assume-the-app-is-broken-&quot;&gt;&lt;strong&gt;Why this matters&lt;/strong&gt;: This test proves your UI provides feedback. If a user clicks a button and waits 2 seconds with no visual feedback, they will assume the app is broken.&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;But wait, what about Mobile Apps?&lt;/strong&gt; &lt;br&gt;
The script above is perfect for automated CI pipelines running Chrome. But CDP has a major limitation: &lt;strong&gt;It doesn't work on a physical iPhone or Android device&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If you are a Mobile Developer or manual QA, you can't &quot;attach Playwright&quot; to the phone in your hand to simulate a subway tunnel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Manual Alternative (System-Level Proxy)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To test latency on a real device without writing code, you need a &lt;strong&gt;System-Level Proxy&lt;/strong&gt; that sits between your phone and the internet.&lt;/p&gt;
&lt;p&gt;You can use desktop tools like Charles Proxy (if you enjoy configuring Java apps and firewalls), or you can use a cloud-based tool like &lt;a rel=&quot;nofollow&quot; href=&quot;https://chaos-proxy.debuggo.app/&quot;&gt;Chaos Proxy&lt;/a&gt; (which I'm building).&lt;/p&gt;
&lt;p&gt;It allows you to simulate &lt;strong&gt;&quot;Subway Mode&quot; (2s latency)&lt;/strong&gt; on any device—iPhone, Android, or Laptop—just by connecting to a Wi-Fi proxy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Workflow:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a &quot;Chaos Rule&quot; (e.g., Latency = 2000ms).&lt;/li&gt;
&lt;li&gt;Connect your phone to the proxy via QR code.&lt;/li&gt;
&lt;li&gt;&lt;h3 id=&quot;watch-your-app-struggle-and-then-fix-it-&quot;&gt;Watch your app struggle (and then fix it).&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stop trusting Localhost&lt;/strong&gt;. It hides your worst bugs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automated&lt;/strong&gt;: Use Playwright + CDP to inject latency in your E2E tests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manual/Mobile&lt;/strong&gt;: Use a Chaos Proxy to test resilience on physical devices.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;happy-testing-&quot;&gt;Happy testing! &lt;/h3&gt;
&lt;p&gt;If you found this useful, check out my previous post: &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/aragossa/stop-testing-success-kill-the-database-27mg&quot;&gt;Stop Testing Success. Kill the Database.&lt;/a&gt;&lt;/p&gt;
</description>
<category>QA Best Practices</category>
<guid isPermaLink="true">https://coderlegion.com/8636/the-spinner-of-death-why-localhost-latency-is-lying-to-you</guid>
<pubDate>Fri, 19 Dec 2025 15:19:20 +0000</pubDate>
</item>
<item>
<title>Don't Break Your WiFi: How to Simulate 503 Errors in a Single Browser Tab</title>
<link>https://coderlegion.com/8237/dont-break-your-wifi-how-to-simulate-503-errors-in-a-single-browser-tab</link>
<description>&lt;p&gt;Testing frontend error handling is a pain.&lt;/p&gt;
&lt;p&gt;You want to verify that your React/Vue app shows a nice &quot;Retry&quot; button when the API fails. Or you want to check if the Skeleton Loader looks good during a 10-second delay.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The traditional way&lt;/strong&gt;: Open Chrome DevTools, toggle &quot;Offline&quot; mode. &lt;strong&gt;The problem&lt;/strong&gt;: It kills the connection completely. You can't simulate a slow server that returns a specific HTTP 503 error code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The other way&lt;/strong&gt;: Use a system-wide proxy (like Charles). &lt;strong&gt;The problem&lt;/strong&gt;: It breaks your Spotify, Slack, and Zoom calls while you test.&lt;/p&gt;
&lt;p&gt;In this guide, I'll show you how to use &lt;strong&gt;FoxyProxy&lt;/strong&gt; and &lt;strong&gt;Debuggo Chaos Proxy&lt;/strong&gt; to inject network failures &lt;strong&gt;only into a specific browser tab&lt;/strong&gt;, leaving the rest of your machine online.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Tutorial (1:57)&lt;/strong&gt;&lt;br&gt;
See the full setup in action:&lt;br&gt;
youtube.com/watch?si=_ItP2sPSbkGy83KU&amp;amp;embeds_referring_euri=https%3A%2F%2Fdev.to%2F&amp;amp;source_ve_path=Mjg2NjQsMTY0NTA2&amp;amp;v=NbPPoqCv3mY&amp;amp;feature=youtu.be&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Stack&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FoxyProxy Standard: A browser extension (Chrome/Firefox) that routes traffic based on patterns.&lt;/li&gt;
&lt;li&gt;Chaos Proxy Debuggo: A cloud chaos proxy that adds delays and errors.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Configure the Chaos Rule&lt;/strong&gt;&lt;br&gt;
Let's break the internet (selectively). In the Debuggo dashboard, I set up a rule for &lt;code&gt;httpbin.org&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Delay&lt;/strong&gt;: 10 seconds (I really want to see that loading spinner).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Status&lt;/strong&gt;: 503 Service Unavailable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Probability&lt;/strong&gt;: 50%.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Set up FoxyProxy&lt;/strong&gt;&lt;br&gt;
Instead of configuring the proxy in MacOS System Settings (which affects the whole OS), we do it in the browser extension.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click Add New Proxy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Host&lt;/strong&gt;: chaos-proxy.debuggo.app&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Port&lt;/strong&gt;: 11997 (Your allocated port).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auth&lt;/strong&gt;: Enter the username/password provided by the service.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;em&gt;Tip: You can set &quot;URL Patterns&quot; in FoxyProxy to only route traffic for your staging API (e.g.,&lt;/em&gt; &lt;code&gt;*api.staging.com*&lt;/code&gt;&lt;em&gt;) through the chaos proxy.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: The Moment of Truth&lt;/strong&gt;&lt;br&gt;
Navigate to your target URL.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;First load&lt;/strong&gt;: You might see it load instantly. Why? Browsers are smart. They reuse existing TCP connections. Fix: Refresh the page or open a new tab to force a new connection through the proxy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Second load:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The browser tab spins... and spins... (The 10s delay works!).&lt;/li&gt;
&lt;li&gt;Finally, you see the &lt;strong&gt;503 Error Page&lt;/strong&gt; injected by the proxy.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Why do this?&lt;/strong&gt;&lt;br&gt;
This setup allows you to audit your UI's resilience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Infinite Scroll: Does the app crash if the &quot;Load More&quot; request times out?&lt;/li&gt;
&lt;li&gt;Form Submission: Does the &quot;Submit&quot; button re-enable if the server returns an error?&lt;/li&gt;
&lt;li&gt;Error Boundaries: Does your React Error Boundary actually catch the crash?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Chaos Engineering isn't just for backend infrastructure. Frontend developers need to verify that their UI allows users to recover gracefully from network glitches. Using a browser-scoped proxy is the least intrusive way to do it.&lt;/p&gt;
&lt;p&gt;Try creating your first rule at chaos-proxy.debuggo.app.&lt;/p&gt;
</description>
<category>Test Automation</category>
<guid isPermaLink="true">https://coderlegion.com/8237/dont-break-your-wifi-how-to-simulate-503-errors-in-a-single-browser-tab</guid>
<pubDate>Sun, 07 Dec 2025 07:15:00 +0000</pubDate>
</item>
<item>
<title>Stop Mocking Everything: How to Test API Resilience in Your Terminal (Curl + Chaos Proxy)</title>
<link>https://coderlegion.com/8178/stop-mocking-everything-how-to-test-api-resilience-in-your-terminal-curl-chaos-proxy</link>
<description>&lt;p&gt;&quot;It works on my machine.&quot;&lt;/p&gt;
&lt;p&gt;We've all said it. But does your bash script work when the third-party API takes 15 seconds to respond? Does your backend service gracefully handle a sudden spike of 503 errors from a payment provider?&lt;/p&gt;
&lt;p&gt;Writing a full mock server just to test a simple retry logic in a script is often overkill. In this tutorial, I'll show you a faster way: &lt;strong&gt;Chaos Engineering directly in the terminal&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;We will use &lt;code&gt;curl&lt;/code&gt; and a cloud-based Chaos Proxy to inject failures into real network requests without changing a single line of your application code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Problem: Localhost is Too Perfect&lt;/strong&gt;&lt;br&gt;
When developing locally, network latency is near zero. APIs either work (200 OK) or they don't (Connection Refused). But in production, you face:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;High Latency&lt;/strong&gt;: The server is busy.&lt;br&gt;
&lt;strong&gt;Intermittent Failures&lt;/strong&gt;: 5% of requests drop.&lt;br&gt;
&lt;strong&gt;Throttling&lt;/strong&gt;: You hit the rate limit.&lt;/p&gt;
&lt;p&gt;Simulating this in a terminal usually involves complex &lt;code&gt;iptables&lt;/code&gt; rules or local tools like &lt;code&gt;tc&lt;/code&gt; (Traffic Control). There is an easier way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Solution: Cloud Chaos Proxy&lt;/strong&gt;&lt;br&gt;
Instead of configuring your OS, we will route specific requests through a proxy that &quot;breaks&quot; the traffic according to rules we define.&lt;/p&gt;
&lt;p&gt;I'll be using chaos-proxy.debuggo.app for this, but the concept applies to any programmable proxy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Video Guide (1:27)&lt;/strong&gt;&lt;br&gt;
Prefer watching? &lt;a rel=&quot;nofollow&quot; href=&quot;https://www.youtube.com/watch?v=x_S-guPwPEk&quot;&gt;Here is the 90-second workflow: &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step-by-Step Tutorial&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Define the Failure&lt;/strong&gt;&lt;br&gt;
First, we need to tell the proxy what to break.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Target: &lt;code&gt;httpbin.org&lt;/code&gt; (or your API domain).&lt;/li&gt;
&lt;li&gt;Delay: &lt;code&gt;7 seconds&lt;/code&gt; (Simulate lag).&lt;/li&gt;
&lt;li&gt;Failure Rate: 1 (100% of requests will fail).&lt;/li&gt;
&lt;li&gt;Error Code: 503 Service Unavailable.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;2. Trust the Certificate (The &quot;One-Time&quot; Setup)&lt;/strong&gt;&lt;br&gt;
Since we are intercepting HTTPS traffic, we need to trust the proxy's CA certificate.&lt;/p&gt;
&lt;p&gt;Download the &lt;code&gt;mitmproxy-ca-cert.pem&lt;/code&gt; from the dashboard.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MacOS:&lt;/strong&gt; Add it to Keychain Access -&amp;gt; System and set &quot;Always Trust&quot;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux:&lt;/strong&gt; Copy to /usr/local/share/ca-certificates/ and update.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. The Magic Command&lt;/strong&gt;&lt;br&gt;
Now, we use &lt;code&gt;curl&lt;/code&gt; with the &lt;code&gt;-x&lt;/code&gt; (proxy) flag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -v -x http://user:*Emails are not allowed*:13979 https://httpbin.org/get
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Understanding the Output&lt;/strong&gt;&lt;br&gt;
When you run this command multiple times:&lt;/p&gt;
&lt;p&gt;Scenario A (The Chaos): You'll notice the terminal &quot;hangs&quot; for 7 seconds (our delay). Then:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt; HTTP/1.1 500 Internal Server Error
&amp;lt; content-length: 56
&amp;lt; content-type: text/plain
...
Debuggo Chaos Injection: 500 Error
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Scenario B (Success)&lt;/strong&gt;: The other 50% of the time, the request passes through to the real server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt; HTTP/1.1 200 OK
...
{
  &quot;args&quot;: {}, 
  &quot;headers&quot;: { ... }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Real World Use Cases&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Testing CI Pipelines&lt;/strong&gt;: Verify that your deployment scripts don't crash if a dependency is slow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cron Jobs&lt;/strong&gt;: Ensure your nightly data sync retries correctly on failure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quick Sanity Checks&lt;/strong&gt;: Before pushing code, verify how the API client handles a 503 error.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
You don't need heavy infrastructure to test network resilience. A simple proxy setup allows you to inject chaos into any HTTP client—be it &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, or your Python/Node.js scripts.&lt;/p&gt;
&lt;p&gt;Happy Breaking! &lt;/p&gt;
</description>
<category>Getting Started</category>
<guid isPermaLink="true">https://coderlegion.com/8178/stop-mocking-everything-how-to-test-api-resilience-in-your-terminal-curl-chaos-proxy</guid>
<pubDate>Fri, 05 Dec 2025 07:15:00 +0000</pubDate>
</item>
</channel>
</rss>