{"id":2957,"date":"2026-07-01T09:30:00","date_gmt":"2026-07-01T09:30:00","guid":{"rendered":"https:\/\/mugnos-it.com\/?p=2957"},"modified":"2026-07-06T16:39:24","modified_gmt":"2026-07-06T16:39:24","slug":"concurrency-is-not-parallelism-and-confusing-the-two-can-be-costly","status":"publish","type":"post","link":"https:\/\/mugnos-it.com\/pt\/concurrency-is-not-parallelism-and-confusing-the-two-can-be-costly\/","title":{"rendered":"Concurrency is NOT Parallelism! And confusing the two can be costly"},"content":{"rendered":"<p>A few days ago I got pulled into a curious conversation: the team was excited, implementing <strong>autoscaling on queue-consumer pods<\/strong>, trying to increase throughput.<\/p>\n\n\n<p>All good so far, right?<\/p>\n\n\n<p>But then came the question:<\/p>\n\n\n<p><em>&#8220;Why are we spinning up more pods if we&#8217;re not even using the resources well inside a single pod?&#8221;<\/em><\/p>\n\n\n<p>Silence.<\/p>\n\n\n<p>And that&#8217;s exactly where the problem lives. Just because your infrastructure is scalable doesn&#8217;t mean you should go full &#8220;Let it Go&#8221; on the pods \u2014 and leave the bill (of CPU, memory, and chaos) for someone else to deal with.<\/p>\n\n\n<p>Today, let&#8217;s talk about a common mistake: <strong>confusing concurrency with parallelism<\/strong>.<\/p>\n\n\n<p>Spoiler: they&#8217;re not the same thing. And the difference between them can decide whether your system <strong>scales well<\/strong> or <strong>just burns resources<\/strong>.<\/p>\n\n\n<h2 class=\"wp-block-heading\">Concurrency \u2260 Parallelism<\/h2>\n\n\n<h3 class=\"wp-block-heading\">Concurrency<\/h3>\n\n\n<p>Concurrency is about <strong>dealing with multiple tasks at the same time<\/strong>, <strong>but not necessarily executing them simultaneously<\/strong>.<\/p>\n\n\n<p>It&#8217;s as if a single core were handling several things at once, jumping from one to another whenever it hits a wait (like I\/O calls, database access, external APIs, etc).<\/p>\n\n\n<p>You gain performance <strong>not by doing everything at the same time<\/strong>, but by <strong>not sitting idle waiting<\/strong>.<\/p>\n\n\n<p><strong>Practical example:<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>A worker consumes a queue, makes a request to an API and\u2026 waits.\n<ul class=\"wp-block-list\">\n<li>During that time, it could be processing another task.<\/li>\n\n\n<li>Solution: apply concurrency, like goroutines (Go), lightweight threads (Java), async\/await (Node, Python).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n<h3 class=\"wp-block-heading\">Parallelism<\/h3>\n\n\n<p>Parallelism, on the other hand, is when you have <strong>multiple cores<\/strong> processing <strong>different things at the same time<\/strong>, for real.<\/p>\n\n\n<p>Ideal for heavy tasks, like <strong>data transformation<\/strong>, <strong>batch processing<\/strong>, <strong>machine learning<\/strong>, etc.<\/p>\n\n\n<p><strong>Practical example:<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>Processing 1 million records with Spark, distributing the work across multiple nodes at the same time.<\/li>\n<\/ul>\n\n\n<p>But be careful: <strong>blind parallelism with heavy I\/O can be inefficient<\/strong>.<\/p>\n\n\n<p>You spin up a bunch of workers\u2026 that just sit there waiting for a network response.<\/p>\n\n\n<h2 class=\"wp-block-heading\">When to use each one?<\/h2>\n\n\n<p><strong>Use concurrency when\u2026<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>Your code depends on external calls (APIs, databases, legacy systems)<\/li>\n\n\n<li>You want better utilization of a single resource (e.g. a pod)<\/li>\n<\/ul>\n\n\n<p><strong>Use parallelism when\u2026<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>You&#8217;re dealing with <strong>CPU-bound<\/strong> tasks<\/li>\n\n\n<li>You need to scale real processing, not just orchestration<\/li>\n<\/ul>\n\n\n<p>Even though I explain them separately, using one doesn&#8217;t rule out the other! In fact, you need to use both \u2014 but the way you implement each is different.<\/p>\n\n\n<p>Think of it like this: inside <strong>a single pod<\/strong>, you use concurrency so you don&#8217;t waste time sitting in waits. Once that pod is already at a healthy limit, <em>then<\/em> you scale horizontally (real parallelism, more replicas). Order matters \u2014 scaling before optimizing means paying a premium for inefficiency.<\/p>\n\n\n<h2 class=\"wp-block-heading\">The SRE connection<\/h2>\n\n\n<p>This is where it stops being operating-system theory and becomes a <strong>reliability and cost decision<\/strong>.<\/p>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Eliminating toil and waste:<\/strong> spinning up a pod by reflex is the opposite of efficiency. Before touching the HPA, look at the real utilization <em>inside<\/em> the pod. If a worker spends 80% of its time waiting on I\/O, the problem isn&#8217;t a lack of replicas \u2014 it&#8217;s a lack of concurrency.<\/li>\n\n\n<li><strong>Monitoring that matters:<\/strong> CPU and memory aren&#8217;t enough. Measure <strong>effective per-pod utilization<\/strong>, queue depth, processing latency, and time spent waiting on I\/O. Those signals tell you <em>which<\/em> lever to pull.<\/li>\n\n\n<li><strong>Error budget and blast radius:<\/strong> uncontrolled concurrency turns into <em>race conditions<\/em> and <em>deadlocks<\/em> in production \u2014 and that burns error budget fast. Parallelism without <em>rate limiting<\/em> takes down downstream dependencies. Reliability is about sizing with intention.<\/li>\n\n\n<li><strong>FinOps is an SRE responsibility:<\/strong> every unnecessary replica is money burned every single month. Making good use of a single pod before scaling is cost optimization at its core.<\/li>\n<\/ul>\n\n\n<h2 class=\"wp-block-heading\">And the risks?<\/h2>\n\n\n<p><strong>Concurrency without control<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>Pushing too much concurrency makes it constantly switch context between tasks (<em>context switching<\/em>), and excessive context switching generates overhead.<\/li>\n\n\n<li>It can blow up into <em>race conditions<\/em>, <em>deadlocks<\/em>, and freeze everything (which is why you need to be careful and handle it with mutexes and locks).<\/li>\n<\/ul>\n\n\n<p><strong>Poorly sized parallelism<\/strong><\/p>\n\n\n<ul class=\"wp-block-list\">\n<li>Creating too many pods without evaluating real usage.<\/li>\n\n\n<li>Increasing the number of threads without control (and hardware is finite, remember?).<\/li>\n\n\n<li>Scaling without applying <em>rate limits<\/em> \u2192 a disaster waiting to happen.<\/li>\n<\/ul>\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n<p>The difference between concurrency and parallelism may seem subtle, but ignoring it can be costly \u2014 in performance, in money, and in unnecessary complexity.<\/p>\n\n\n<p>Go back to the beginning: the team wanted more pods. But the right question wasn&#8217;t <em>&#8220;how many replicas?&#8221;<\/em> \u2014 it was <em>&#8220;am I making good use of what I already have?&#8221;<\/em>.<\/p>\n\n\n<p>The truth is that a lot of architecture is being decided on impulse. Solutions get sold as indispensable, the hype takes over\u2026 and suddenly we&#8217;re paying a premium for infrastructure that doesn&#8217;t even bring real value to the business.<\/p>\n\n\n<p>A good technical choice is one made with <strong>intention, clarity, and purpose<\/strong> \u2014 understanding what your system actually needs before you start scaling.<\/p>\n\n\n<p>If this kind of reflection resonates with you, and you want to learn how to use technology to scale your technical capacity (without becoming a hostage to tooling), make sure to follow me on social media and keep up with the newsletter!<\/p>\n\n\n<p>Cheers,<\/p>\n\n\n<p>Douglas Mugnos<\/p>\n\n\n<p>MUGNOS-IT \ud83d\ude80<\/p>","protected":false},"excerpt":{"rendered":"<p>A few days ago I got pulled into a curious conversation: the team was excited, implementing autoscaling on queue-consumer pods, trying to increase throughput. All good so far, right? But then came the question: &#8220;Why are we spinning up more pods if we&#8217;re not even using the resources well inside a single pod?&#8221; Silence. And [&hellip;]<\/p>","protected":false},"author":3,"featured_media":2977,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-2957","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/mugnos-it.com\/wp-content\/uploads\/2026\/07\/59-2.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/2957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/comments?post=2957"}],"version-history":[{"count":4,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/2957\/revisions"}],"predecessor-version":[{"id":2963,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/posts\/2957\/revisions\/2963"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/media\/2977"}],"wp:attachment":[{"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/media?parent=2957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/categories?post=2957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mugnos-it.com\/pt\/wp-json\/wp\/v2\/tags?post=2957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}