<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Benjamin Cane on Medium]]></title>
        <description><![CDATA[Stories by Benjamin Cane on Medium]]></description>
        <link>https://medium.com/@madflojo?source=rss-96013faddf78------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*mu9eLLugJ68QrlRwLPBmwA@2x.jpeg</url>
            <title>Stories by Benjamin Cane on Medium</title>
            <link>https://medium.com/@madflojo?source=rss-96013faddf78------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 03 Oct 2026 21:33:31 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@madflojo/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Message queues are great for handing off work, but how do you know the work actually happens?]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://itnext.io/message-queues-are-great-for-handing-off-work-but-how-do-you-know-the-work-actually-happens-4eb07db9296f?source=rss-96013faddf78------2"><img src="https://cdn-images-1.medium.com/max/2600/0*lp8_o3RNFD8anvaQ" width="4353"></a></p><p class="medium-feed-link"><a href="https://itnext.io/message-queues-are-great-for-handing-off-work-but-how-do-you-know-the-work-actually-happens-4eb07db9296f?source=rss-96013faddf78------2">Continue reading on ITNEXT »</a></p></div>]]></description>
            <link>https://itnext.io/message-queues-are-great-for-handing-off-work-but-how-do-you-know-the-work-actually-happens-4eb07db9296f?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/4eb07db9296f</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 02 Oct 2026 15:31:01 GMT</pubDate>
            <atom:updated>2026-10-02T20:05:48.806Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Some architecture principles should be rules. Others should be guidelines.]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://itnext.io/some-architecture-principles-should-be-rules-others-should-be-guidelines-0df71698ca91?source=rss-96013faddf78------2"><img src="https://cdn-images-1.medium.com/max/2600/0*ZKYPzNNpV8r10eAb" width="6000"></a></p><p class="medium-feed-snippet">Not all architecture principles should be treated the same.</p><p class="medium-feed-link"><a href="https://itnext.io/some-architecture-principles-should-be-rules-others-should-be-guidelines-0df71698ca91?source=rss-96013faddf78------2">Continue reading on ITNEXT »</a></p></div>]]></description>
            <link>https://itnext.io/some-architecture-principles-should-be-rules-others-should-be-guidelines-0df71698ca91?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/0df71698ca91</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-architecture]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 25 Sep 2026 17:31:01 GMT</pubDate>
            <atom:updated>2026-09-26T17:12:55.458Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Mishandling concurrency is one of the most common root causes of software bugs]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://itnext.io/mishandling-concurrency-is-one-of-the-most-common-root-causes-of-software-bugs-e9e3803cc124?source=rss-96013faddf78------2"><img src="https://cdn-images-1.medium.com/max/2600/0*KTDrhxuptj3Cul1q" width="6000"></a></p><p class="medium-feed-snippet">Of all the software bugs I&#x2019;ve seen, mishandling concurrency is one of the most common root causes.</p><p class="medium-feed-link"><a href="https://itnext.io/mishandling-concurrency-is-one-of-the-most-common-root-causes-of-software-bugs-e9e3803cc124?source=rss-96013faddf78------2">Continue reading on ITNEXT »</a></p></div>]]></description>
            <link>https://itnext.io/mishandling-concurrency-is-one-of-the-most-common-root-causes-of-software-bugs-e9e3803cc124?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/e9e3803cc124</guid>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 18 Sep 2026 17:16:01 GMT</pubDate>
            <atom:updated>2026-09-18T22:45:16.575Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[At what point does better performance stop being worth it?]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://itnext.io/at-what-point-does-better-performance-stop-being-worth-it-b529b5f13646?source=rss-96013faddf78------2"><img src="https://cdn-images-1.medium.com/max/2600/0*O-bRO0Xtzc0hk_g3" width="4507"></a></p><p class="medium-feed-snippet">Photo by Scott Rodgerson on Unsplash</p><p class="medium-feed-link"><a href="https://itnext.io/at-what-point-does-better-performance-stop-being-worth-it-b529b5f13646?source=rss-96013faddf78------2">Continue reading on ITNEXT »</a></p></div>]]></description>
            <link>https://itnext.io/at-what-point-does-better-performance-stop-being-worth-it-b529b5f13646?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/b529b5f13646</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 11 Sep 2026 20:41:01 GMT</pubDate>
            <atom:updated>2026-09-11T22:05:24.560Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Sometimes good engineering looks like over-engineering]]></title>
            <link>https://itnext.io/sometimes-good-engineering-looks-like-over-engineering-bdf90b4e7442?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/bdf90b4e7442</guid>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[software-development]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 04 Sep 2026 20:41:00 GMT</pubDate>
            <atom:updated>2026-09-04T22:34:15.642Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BaY0De3xCyIWq458" /><figcaption>Photo by <a href="https://unsplash.com/@manuel_luikenga?utm_source=medium&amp;utm_medium=referral">Manuel Luikenga</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>Sometimes good engineering looks like over-engineering.</p><p>I was recently putting together a talk that walks through some architecture and engineering decisions I’ve made over the last eight-plus years when something stood out to me.</p><p>Without context, many of those decisions probably look like over-engineering.</p><h3>🤔 An Example: Operational Toggles</h3><p>In several mission-critical payment applications, we follow a simple philosophy:</p><p>If a dependency isn’t required to process customer traffic, we should be able to turn it off.</p><p>For example, metrics.</p><p>Metrics are important, but they aren’t more important than processing transactions. If something goes wrong with our metrics implementation, we want to be able to turn off metrics while continuing to process traffic.</p><p>The same applies to out-of-band management messages and data updates. We typically use message brokers for this, and if there is an issue with that integration or a bug in the message handlers, we want the ability to stop consuming those messages without taking down the application.</p><p>Why?</p><p>Because we want fine-grained operational control over our platform. A non-critical capability shouldn’t be able to take down the critical path.</p><h3>🤯 Isn’t That Over-Engineering?</h3><p>Maybe.</p><p>These operational toggles add complexity to the system: flags that need to be managed, tests that need to be written and executed, and operational procedures for failures that might never happen.</p><p>For many applications, it’s probably not worth it.</p><p>If a metrics library causes a memory leak in an application that does batch processing, restarting to release the memory is perfectly acceptable.</p><p>If a message handler crashes an application that is automatically restarted, it might be ok depending on the application. Not great, but if requests are retried and nothing truly fails, no harm, no foul.</p><p>Not every application needs the complexity of these operational toggles.</p><p>But when an application crash could cause impact, when the system is mission-critical, and every failure is potentially impactful, the equation changes.</p><h3>🧠 Context Determines Everything</h3><p>For the batch and non-critical application examples, these operational toggles could easily be considered over-engineering.</p><p>But for a mission-critical, always-on, large-scale platform, when a situation occurs and these operational toggles are used, they become incredibly valuable.</p><p>The above examples are not hypothetical.</p><p>A change in metrics causes a spike in memory usage. An unsafe type assertion in a data sync handler from a message broker causes an application to crash.</p><p>These are real scenarios, scenarios that I’ve seen in mission-critical systems. Because these operational toggles existed, these scenarios were not disastrous or even inconvenient.</p><p>These operational toggles let us turn off the cause of an issue. More importantly, they gave us time. Time to understand what happened, build and properly test a fix, and validate that the fix actually solved the root problem.</p><p>All without rushing a change to production while the platform was unstable.</p><h3>🧐 Final Thoughts</h3><p>If you look at the way we use operational toggles, it could easily feel like over-engineering. But building critical systems means planning for failure scenarios even if they are unlikely.</p><p>Sometimes that additional complexity might look unnecessary. But when something goes wrong, you’re thankful it’s there.</p><p>Originally posted on <a href="https://bencane.com/posts/2026-08-26-good-engineering-looks-like-over-engineering/">#Bengineering</a>.</p><p>For the canonical version and future updates, read it here: <a href="https://bencane.com/posts/2026-08-26-good-engineering-looks-like-over-engineering/">Sometimes good engineering looks like over-engineering</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bdf90b4e7442" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/sometimes-good-engineering-looks-like-over-engineering-bdf90b4e7442">Sometimes good engineering looks like over-engineering</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI makes code cheap to create, not cheap to own]]></title>
            <link>https://itnext.io/ai-makes-code-cheap-to-create-not-cheap-to-own-e9d510165f9f?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/e9d510165f9f</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 28 Aug 2026 20:11:01 GMT</pubDate>
            <atom:updated>2026-08-29T08:07:16.564Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*G9VbX5eYjiFvWAYS" /><figcaption>Photo by <a href="https://unsplash.com/@cgower?utm_source=medium&amp;utm_medium=referral">Christopher Gower</a> on <a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>AI has made code cheap to create, but more code means more overhead.</p><p>Before coding agents, creating more code cost time and effort because engineers had to write it.</p><p>That naturally encouraged us to reuse code as much as possible: libraries, frameworks, keeping implementations concise, and thinking twice before rebuilding functionality that already existed.</p><p>Coding agents have dramatically reduced that natural cost.</p><p>Today, generating another implementation costs almost nothing. But you still have to maintain it.</p><h3>🤖 Just Let the Agent Build It</h3><p>There’s a growing mindset that because agents can generate code quickly, there’s less reason to worry about reuse.</p><p>Why spend time finding an existing library when an agent can recreate the functionality in seconds? And initially, that might feel faster, better.</p><p>But let’s say you have six applications that all need to validate email addresses against your internal requirements.</p><p>Instead of creating a common package, you let your coding agent implement email validation directly in each application. As long as the prompt is the same, it’s fine, right? Not necessarily. You can easily end up with six implementations, all slightly different.</p><p>Then you find a bug.</p><h3>🪳 Creation is Cheap, Maintenance Isn’t</h3><p>Fixing the application with the bug is easy.</p><p>Tell the agent about the bug; it fixes the implementation, maybe it adds some tests, done.</p><p>What about those five other implementations? Do they also have this bug?</p><p>Maybe, maybe not. Because each application has a different implementation, they may have the same bug or different bugs.</p><p>You’ve essentially found yourself in a situation where, depending on the application, an email might work, or it might not. Maybe it works in three of the six, or two. What happens if that email works for a registration page, but not the login page?</p><p>Not a great user experience.</p><h3>🧱 Reuse Still Matters</h3><p>Compare that to using a shared package. You write it once, everyone uses the same package.</p><p>You find a bug, fix it once, add tests, and release a new version.</p><p>Every instance using that new version has that bug fixed.</p><p>Now your suite of applications is consistent, and consistency matters most. Rejecting a valid email isn’t great, but if you’re consistent about it, that’s a much better experience than it sometimes working and sometimes not.</p><p>That consistency is much easier to manage if the implementation is in one reusable library.</p><h3>⚖️ Don’t Go DRY Crazy</h3><p>Don’t use the above example to go to the other extreme, where every similar three lines of code turns into a shared library. Breaking everything into its own little shared library creates overhead costs, too.</p><p>It’s important to strike a balance between reusable and duplicative.</p><p>If you’re writing something with complex or nuanced behavior that’s needed across multiple applications, or more importantly, needs to behave consistently across them, a shared library is probably a good idea.</p><p>If it’s simple, situationally unique, and unlikely to change, don’t bother.</p><h3>🧐 Final Thoughts</h3><p>The cost of creating code has changed significantly. But the cost of managing it hasn’t.</p><p>Testing it, patching it, securing it, and keeping implementations consistent all become more expensive as the amount of code you own grows.</p><p>AI has made it incredibly cheap to create more code. Don’t confuse cheap to generate with cheap to own.</p><p>Originally posted on <a href="https://bencane.com/posts/2026-08-19-ai-code-cheap-to-create-not-cheap-to-own/">#Bengineering</a>.</p><p>For the canonical version and future updates, read it here: <a href="https://bencane.com/posts/2026-08-19-ai-code-cheap-to-create-not-cheap-to-own/">AI makes code cheap to create, not cheap to own</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e9d510165f9f" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/ai-makes-code-cheap-to-create-not-cheap-to-own-e9d510165f9f">AI makes code cheap to create, not cheap to own</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[“We can’t run locally” is usually a design smell]]></title>
            <link>https://itnext.io/we-cant-run-locally-is-usually-a-design-smell-81b8715dad89?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/81b8715dad89</guid>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 21 Aug 2026 17:16:01 GMT</pubDate>
            <atom:updated>2026-08-21T22:48:15.486Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZdJS6EvpTayVMsBY" /></figure><p>I’m a believer that, as an engineer, you should be able to run your software locally. But I hear it often: “We can’t run locally because of some reason.”</p><p>Sometimes it’s valid. There are architectures and platforms out there that prevent running locally. But more often than not, when it comes to backend distributed systems, it’s a design or implementation decision that nobody has challenged.</p><h3>Why This Matters</h3><p>Everyone these days is focused on speeding up software delivery. Today, that generally means coding agents, AI tooling, and code generation.</p><p>But writing code faster doesn’t matter much if validating a one-line change takes an hour.</p><p>The speed of software delivery is often dictated by validation, not code generation.</p><h3>The Problem with Shared Dev Environments</h3><p>Many teams still rely on shared development environments as their primary way of validating changes.</p><p>That process usually looks something like this:</p><ul><li>Make a change</li><li>Commit the change</li><li>Push the branch</li><li>Wait for a build</li><li>Wait for a deployment</li><li>Run tests</li></ul><p>If everything goes well, you can validate your change. If a mistake was made, or something doesn’t work right, you have to fix it and start over.</p><p>The result is a slow feedback loop, which can sometimes influence behavior.</p><p>The more friction there is to validate a change, the larger that change becomes. If testing takes a long time, you will naturally focus on making sure everything is perfect before spending time validating.</p><h3>Local Validation Influences Good Behavior</h3><p>Compare the above process to one that uses a locally running service.</p><ul><li>Make a change</li><li>Build</li><li>Start the service</li><li>Run tests</li></ul><p>The process is dramatically shorter and, more importantly, faster. This encourages engineers to make smaller changes, test more frequently, iterate their implementations, and find mistakes earlier.</p><p>This all results in better software.</p><h3>The Excuses</h3><p>“My service depends on too many other services.”</p><p>Run the services you own locally. Mock the services you don’t.</p><p>“I need a database or message broker.”</p><p>Run those locally too. There’s very likely a Docker container for each of them.</p><p>“We use cloud services.”</p><p>This one can be harder, but emulators exist for some services. Other services might have a Dockerized open-source alternative. For those that don’t, you could mock them.</p><p>There will always be exceptions: mainframes, specialized hardware, or unique managed services.</p><p>But I find many teams jump straight to “we can’t run locally” before they’ve seriously explored how they could.</p><h3>Running Local Doesn’t Mean Everything</h3><p>You don’t need to recreate your entire production environment on a laptop, though if you can, go for it.</p><p>The goal is to validate your change without depending on a shared or non-local environment that takes forever to test against.</p><p>Local development isn’t about recreating production. It’s about creating enough of the environment to validate your change. If that means turning off some functionality or creating mock services, it might be worth it.</p><h3>Why This Matters Even More Now</h3><p>Validating changes quickly is becoming more important as teams adopt coding agents. An agent can generate code in seconds.</p><p>But if every iteration with your coding agent requires committing, pushing, building, deploying, and waiting, the feedback loop becomes the bottleneck.</p><h3>Final Thoughts</h3><p>Agents make mistakes. Humans make mistakes.</p><p>The faster you can validate a change, the faster you can correct those mistakes. That’s why local execution isn’t just a convenience.</p><p>It’s one of the most effective ways to shorten the feedback loop.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=81b8715dad89" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/we-cant-run-locally-is-usually-a-design-smell-81b8715dad89">“We can’t run locally” is usually a design smell</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[To make a service more stable, eliminate dependencies]]></title>
            <link>https://itnext.io/to-make-a-service-more-stable-eliminate-dependencies-d60d1c1a65bc?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/d60d1c1a65bc</guid>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[coding]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 14 Aug 2026 17:11:01 GMT</pubDate>
            <atom:updated>2026-08-15T22:20:58.093Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Vp16Ii3eCZdX9Zl1" /></figure><p>One of the simplest reliability rules I’ve learned is this: Every dependency is another way for your service to fail.</p><h3>Why Dependencies Matter</h3><p>Every service has dependencies.</p><ul><li>Databases</li><li>Caches</li><li>Configuration services</li><li>Secrets managers</li><li>Logging pipelines</li><li>Tracing backends</li></ul><p>All of these dependencies can fail, and when they do, the typical service will fail with them.</p><p>The more dependencies a service has, the more failures it inherits. Every dependency adds features, but it also adds failure modes.</p><p>Reliability is often about deciding which dependencies are actually worth the tradeoff.</p><h3>Why Edge Systems Tend to Be Dependency-Light</h3><p>I recently wrote about how systems closest to the customer carry the greatest responsibility for availability.</p><p>This is one reason edge systems tend to be dependency-light.</p><p>Load balancers, API gateways, and routers are responsible for availability.</p><p>Every dependency added to these systems creates another opportunity to take down the entire platform. So they tend to avoid dependencies whenever possible.</p><h3>Eliminating Dependencies Isn’t Always Necessary</h3><p>Sometimes removing a dependency entirely isn’t practical.</p><p>A better question is:</p><ul><li>What happens if the dependency disappears?</li><li>Can the service continue operating?</li><li>Can it use cached data?</li><li>Can it fall back to a last-known-good configuration?</li><li>Can it degrade gracefully?</li></ul><p>If the answer is yes, you’ve significantly improved reliability even though the dependency still exists.</p><h3>A Real-World Example</h3><p>Take Envoy Proxy. Envoy can receive configuration from an xDS service. But it doesn’t call xDS for every request.</p><p>Instead:</p><ul><li>Configuration is fetched periodically</li><li>Stored in memory</li><li>Used locally during request processing</li></ul><p>If the xDS service becomes unavailable, Envoy continues routing traffic using its last known configuration. The dependency still exists, but request processing no longer depends on its availability.</p><p>That’s a very different reliability model.</p><h3>Don’t Make Observability a Hard Dependency</h3><p>One of the most common mistakes I see is making observability a required dependency.</p><p>If your logging or tracing backend becomes unavailable, should customer traffic stop flowing? No.</p><p>In most cases, observability should be a best effort.</p><p>Use asynchronous logging, buffering, and truncation policies so customer traffic continues to flow even when your observability platform is experiencing issues.</p><p>Operational visibility is important, but customer availability is more important.</p><h3>Final Thoughts</h3><p>You’ll never eliminate every dependency. But you can eliminate unnecessary ones.</p><p>And for the remaining dependencies, you can design your service to survive failures.</p><p>The most reliable services aren’t dependency-free. They’re designed to survive dependency failures.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d60d1c1a65bc" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/to-make-a-service-more-stable-eliminate-dependencies-d60d1c1a65bc">To make a service more stable, eliminate dependencies</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Caching isn’t hard. Some data is hard to cache]]></title>
            <link>https://itnext.io/caching-isnt-hard-some-data-is-hard-to-cache-2b074873c11a?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/2b074873c11a</guid>
            <category><![CDATA[technology]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-engineering]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 07 Aug 2026 17:11:01 GMT</pubDate>
            <atom:updated>2026-08-15T22:21:45.101Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*p8_XVjjzwk5SDSBH" /></figure><p>You’ve all heard the advice: “Avoid caching because caching is difficult to get right.” I agree with part of that statement. Caching can absolutely be difficult. But I think the reality is more nuanced.</p><p>The difficulty level of caching depends heavily on the type of data you are caching.</p><h3>Not All Data Is Equal</h3><p>When engineers talk about caching complexity, they’re usually thinking about data that changes frequently and requires strong consistency.</p><p>That’s the hardest kind of data to cache. Because you need to answer some difficult questions.</p><ul><li>How do you invalidate the cache?</li><li>How do you handle updates?</li><li>What happens when the cache population fails?</li><li>How stale is too stale?</li></ul><p>These problems are real, but they don’t apply to all data.</p><h3>Frequently Updated Data</h3><p>Some data changes constantly and has strict accuracy requirements. Account balances, inventory counts, active orders, and similar records. This is where caching is difficult.</p><p>Every stale read has a consequence, and in some cases, it’s not worth the complexity.</p><h3>Infrequently Updated Data</h3><p>Some data changes occasionally, once an hour, once a day, or even longer. Configuration data, product catalogs, country codes, and similar records.</p><p>In these cases, a small amount of staleness might be fine. If data changes hourly and your cache refreshes every few minutes, that’s often a reasonable tradeoff. The less frequently data changes, the less sensitive you become to cache staleness.</p><p>Caching is much easier with infrequently updated data.</p><h3>Immutable Data</h3><p>Immutable data is the easiest to cache. Because it never changes. Ledger entries, event records, receipts, and other immutable records.</p><p>Once immutable data is loaded into a cache, cache invalidation largely disappears as a problem. Cache complexity for immutable data is more about balancing performance and hit-miss ratios.</p><p>Most of the time, immutable data is an ideal candidate for caching.</p><h3>The Real Question</h3><p>Instead of asking, “Should I cache?” Ask yourself, “How often does this data change? How accurate does it need to be?”</p><p>The answers will give you an idea of how complex caching will be.</p><h3>Final Thoughts</h3><p>Caching isn’t inherently hard.</p><p>Maintaining correctness for frequently changing data is hard.</p><p>The more stable the data, the less complex the caching needs to be.</p><p>Like most things in system design, you can’t just take all-or-none answers like “always cache” or “never cache.” It’s important to understand the trade-offs, constraints, and consistency requirements of the data you’re working with.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2b074873c11a" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/caching-isnt-hard-some-data-is-hard-to-cache-2b074873c11a">Caching isn’t hard. Some data is hard to cache</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The closer to the edge, the more stable a platform must be]]></title>
            <link>https://itnext.io/the-closer-to-the-edge-the-more-stable-a-platform-must-be-008f5682c301?source=rss-96013faddf78------2</link>
            <guid isPermaLink="false">https://medium.com/p/008f5682c301</guid>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[software-development]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[devops]]></category>
            <dc:creator><![CDATA[Benjamin Cane]]></dc:creator>
            <pubDate>Fri, 31 Jul 2026 17:06:01 GMT</pubDate>
            <atom:updated>2026-08-18T07:28:28.309Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*doa9_wh5ADS-Itir" /></figure><p>The closer a component is to the customer, the greater its responsibility for keeping the entire platform available, even when everything behind it is having a bad day.</p><h3>Not All Services Carry the Same Reliability Burden</h3><p>Let’s consider a typical platform.</p><p>Customer -&gt; Load Balancer -&gt; API Gateway -&gt; Orchestrator -&gt; Microservices -&gt; Database</p><p>Every layer has a different job. But every layer also has a different level of responsibility for resiliency.</p><p>As you move toward the customer, that responsibility increases.</p><h3>Deep Services Focus on Business Logic</h3><p>At the deepest layers of the platform, services are usually focused on business capabilities.</p><p>They process orders, transfer money, manage inventory, and store data.</p><p>These services often have databases, business rules, stateful operations, and multiple dependencies.</p><p>Resiliency matters, but it’s often focused on correctness.</p><p>If a database call fails:</p><ul><li>Should the transaction roll back?</li><li>Should the service fail over?</li><li>Should a compensating transaction occur?</li></ul><p>These services are primarily concerned with business outcomes.</p><h3>The Middle Layers Absorb Failures</h3><p>Move up a layer, and you often find orchestrators and workflow services. These components coordinate work across multiple services.</p><p>If one service fails, the orchestrator may retry, execute fallback logic, trigger compensating actions, or roll back a workflow. Their job is not just executing business logic, it’s ensuring execution succeeds despite failures.</p><h3>The Edge Exists to Protect Everything Behind It</h3><p>At the edge, things change.</p><p>Load balancers and API gateways are often stateless, dependency-light, highly available, and extremely fast.</p><p>Why?</p><p>Because their primary responsibility is availability. Everything behind them is allowed to fail, and they absorb as much of that failure as possible.</p><p>They:</p><ul><li>Route around failures</li><li>Shed load</li><li>Fail over traffic</li><li>Enforce timeouts</li><li>Apply retries</li><li>Protect backend systems</li></ul><p>The edge isn’t just resilient for itself. It’s resilient on behalf of everything behind it.</p><h3>Final Thoughts</h3><p>The deepest services in a platform should be focused on business logic. The edge should be focused on availability.</p><p>The more failures your edge can absorb, the less every downstream service needs to care. That’s why the closer you get to the customer, the more stable the platform must become.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=008f5682c301" width="1" height="1" alt=""><hr><p><a href="https://itnext.io/the-closer-to-the-edge-the-more-stable-a-platform-must-be-008f5682c301">The closer to the edge, the more stable a platform must be</a> was originally published in <a href="https://itnext.io">ITNEXT</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>