<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ShiftMag</title>
	<atom:link href="https://shiftmag.dev/feed/" rel="self" type="application/rss+xml" />
	<link>https://shiftmag.dev/</link>
	<description>Insightful engineering content &#38; community</description>
	<lastBuildDate>Fri, 16 Oct 2026 11:18:06 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://shiftmag.dev/wp-content/uploads/2026/09/cropped-Shift-32x32.webp</url>
	<title>ShiftMag</title>
	<link>https://shiftmag.dev/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Chris Davidson, Atlassian: &#8220;Ask AI to challenge you&#8221;</title>
		<link>https://shiftmag.dev/chris-davidson-atlassian-ask-ai-to-challenge-you-12526/</link>
		
		<dc:creator><![CDATA[Ivan Simic]]></dc:creator>
		<pubDate>Fri, 16 Oct 2026 11:18:06 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Atlassian]]></category>
		<category><![CDATA[chris davidson]]></category>
		<category><![CDATA[Developer Productivity]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Infobip Shift 2026]]></category>
		<category><![CDATA[Shift Conference]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12526</guid>

					<description><![CDATA[<p>As a Solutions Engineer at Atlassian, Chris Davidson works with clients in an effort to make the most of Atlassian's tools and has first-hand experience of how we adapt to using AI.</p>
<p>The post <a href="https://shiftmag.dev/chris-davidson-atlassian-ask-ai-to-challenge-you-12526/">Chris Davidson, Atlassian: &#8220;Ask AI to challenge you&#8221;</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">During <a href="https://shiftmag.dev/tag/infobip-shift-2026/" target="_blank" rel="noreferrer noopener">this year&#8217;s Infobip Shift</a> in Zadar, Croatia, Chris spoke to us about AI tools and gave us some inside information on <strong>how Atlassian</strong>, the creators of Jira and Confluence, <strong>work with AI internally</strong>. With his role considering lots of work with clients, he also had things to say about how we use (or try to use) AI tools efficiently.</p>



<p class="wp-block-paragraph">Chris has seen his share of enthusiastic implementations that don&#8217;t always work out. Funnily enough, it&#8217;s not always the clients and partners that get carried away with AI; sometimes it&#8217;s Atlassian. Chris noted that the company is just like many others, trying to <strong>figure out the impact of AI as they go on</strong>. The one thing to point out is the usage of agents:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">I think about agents inside Atlassian, and as a team member adopting them, it&#8217;s really interesting to see how quickly they get spun up, but then how quickly they only have only one or two uses. </p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Then you even get to the point where there&#8217;s almost like a clean up process. Many agents, duplicated names and activities, and you have to clean those up. You almost need agents to clean up agents.</p>
</blockquote>



<p class="wp-block-paragraph">Chris told us that, in Atlassian, they&#8217;re trying to move fast and react to what customers need and want. This often results in making services and face challenges in duplication. </p>



<h2 class="wp-block-heading">Don&#8217;t use AI selfishly</h2>



<p class="wp-block-paragraph">Despite AI agents and tools&#8217; ability to understand almost everything about software, building things with AI is something most of us do by ourselves. We create tools and use AI to write code we&#8217;re working on, but rarely we go and seek how we could work with others. You could argue that using AI has become a bit of a selfish thing; we&#8217;re all trying to see what we can do on our own. Chris told us that teams that legitimately change the way they work with AI <strong>are usually the ones who use it to collaborate with others.</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Maybe they&#8217;re opening up more of an interface that&#8217;s like self-serve to another part of the organization. You know, you think like QA management and test and development, that interfance, how can we make that better?</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">It&#8217;s not about what we&#8217;re coding in our IDE, it&#8217;s more about how that work is then moving to the next part of the organization. So I really look for where are connections across that whole development lifecycle, not just the coding bit.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="ai-is-magnifying-some-challenges">AI is magnifying some challenges</span></h2>



<p class="wp-block-paragraph">An interesting trend in software development today is adding AI for the sake of AI, thus adding more steps in an otherwise very streamlined process. Chris said that we, as humans, need to be very intentional in finding steps where AI can help. We should not just<strong> try and apply AI to every single part</strong> of every development lifecycle. Doing that just causes something Chris calls &#8220;drag&#8221;:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Where it causes drag is when poor quality comes down the pipe. We&#8217;ve known for years that it costs a lot more to fix poor quality later in the lifecycle than earlier, and I just think we&#8217;re magnifying that challenge with AI because it&#8217;s so convincing. </p>
</blockquote>



<p class="wp-block-paragraph">Humans can be a little bit lazy sometimes, said Chris, and added that we might let a lot of things pass through unintentionally. Those things get further down the pipeline and<strong> AI then causes a real drag</strong> because it&#8217;s harder to find and fix, and it takes more effort from everyone. </p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Why Teams Quietly Quit Their AI Tools?" width="500" height="281" src="https://www.youtube.com/embed/U2izoZODpkI?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading">It&#8217;s challenging to lead in the AI era</h2>



<p class="wp-block-paragraph">Engineering leaders today, such as higher-level managers and executives, do not have it easy today. Chris echoed this statement, saying that he &#8220;feels for engineering leaders at the moment&#8221;, and adding that there&#8217;s a whole other layer of dealing with both the technical and human challenges of this AI era. </p>



<p class="wp-block-paragraph">In terms of where leaders go wrong, Chris used a <strong>high reliance on data as an example. </strong>In his opinion, with more data of all sorts available today, leaders tend to rotate more towards it than towards qualitative metrics:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Managers can defend and they can articulate well with data. There is a risk that you over-rotate purely to data and not those qualitative metrics. So, engineering managers need to also keep qualitative metrics, developer surveys and developer pulses.</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">That&#8217;s how you stay close to what the feeling is on the ground, from both a performance perspective but also a human perspective.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="ask-your-ai-to-challenge-you">Ask your AI to challenge you</span></h2>



<p class="wp-block-paragraph">Using AI tools without being skeptical and critical of them might be the single worst trend not just in software development today, but in almost every industry (and in personal lives of many). Chris noted that it&#8217;s really dangerous how convincingly wrong AI tools and agents might be, and without knowing how to properly work with them, you might be a victim of their hallucinations without ever noticing it. Chris explained:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">A practice I see many teams do is you use AI to challenge you. You have to have a viewpoint and a hypothesis about what you&#8217;re doing and why you&#8217;re doing it and how you&#8217;re approaching it. Then you use AI to challenge that. </p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Guaranteed, it will come up with things you didn&#8217;t think of. It will come up with elements of code or something in the code that you wouldn&#8217;t have seen, and it would not have been detected had it not been for AI.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="ask-how-you-could-use-ai-to-help-other-teams">Ask how you could use AI to help other teams</span></h2>



<p class="wp-block-paragraph">Wrapping up our chat with Chris, we asked him how would he advise those working with AI every day to make the most of their experience, and collaboration with AI tools:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">A practical change might be to take some time out of your week, draw a circle and put all the teams that you work with around that circle, and then start to pull your top three or five teams that are critical to that flow of work, and ask yourself, how could we be using AI better in our relationship with those teams?</p>
</blockquote>



<p class="wp-block-paragraph">If you switch your thought process related to AI from thinking how can the technology make your job easier to how it can make working with others easier, it <strong>might just be the thing you need</strong> to get the edge. Just don&#8217;t go using it without questioning the things it says. </p>


<figure class="wp-block-post-featured-image"><img fetchpriority="high" decoding="async" width="2100" height="1400" src="https://shiftmag.dev/wp-content/uploads/2026/10/Chris_Davidson_final-scaled.jpg?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="Chris Davidson, Atlassian, on Infobip Shift 2026" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/Chris_Davidson_final-scaled.jpg 2100w, https://shiftmag.dev/wp-content/uploads/2026/10/Chris_Davidson_final-300x200.jpg 300w, https://shiftmag.dev/wp-content/uploads/2026/10/Chris_Davidson_final-1024x683.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/Chris_Davidson_final-768x512.jpg 768w" sizes="(max-width: 2100px) 100vw, 2100px" /></figure><p>The post <a href="https://shiftmag.dev/chris-davidson-atlassian-ask-ai-to-challenge-you-12526/">Chris Davidson, Atlassian: &#8220;Ask AI to challenge you&#8221;</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>I Talk to Production Every Morning. It Talks Back.</title>
		<link>https://shiftmag.dev/i-talk-to-production-every-morning-it-talks-back-12679/</link>
		
		<dc:creator><![CDATA[Hrvoje Rancic]]></dc:creator>
		<pubDate>Thu, 15 Oct 2026 13:22:52 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[Developer Productivity]]></category>
		<category><![CDATA[Engineer Explains]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12679</guid>

					<description><![CDATA[<p>A lot of people are leaving software engineering because agent-based workflows killed their joy. I don't have that problem; I never liked the job in the first place.</p>
<p>The post <a href="https://shiftmag.dev/i-talk-to-production-every-morning-it-talks-back-12679/">I Talk to Production Every Morning. It Talks Back.</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I was good at math and algorithm coding challenges in high school, and I knew I would rather not be poor, if possible, and the salary of a software engineer is decent. I started working with a naive assumption that soon I will know how to do the job well, it would become a routine and then I would just cruise through it. </p>



<p class="wp-block-paragraph">I soon learned that <strong>college did not prepare me for the job</strong>, got some kind of idea of the skills and knowledge required to ship production software, and figured out that the more I knew the less stressful the job would be.</p>



<p class="wp-block-paragraph">So over the course of many years, much against my will, <strong>I became an expert</strong>. Then AI came into the picture, and nothing fundamentally changed, because the job of a software engineer is to help achieve business goals by leveraging their understanding of the technology, and now there was yet another technology to learn.</p>



<h2 class="wp-block-heading"><span id="get-ahead-of-security-issues">Get ahead of security issues</span></h2>



<p class="wp-block-paragraph">I have decided to <strong>focus on making the job less miserable for me</strong>. My original approach, once I learned how to use tools such as Claude, was to do the same amount of work as before and then just chill.</p>



<p class="wp-block-paragraph">Nobody ever complained about my performance, so I figured if I just did the same amount of stuff in less time, I would have time for the things I enjoyed, like drinking coffee with other slackers on the balcony or writing pieces <a href="https://shiftmag.dev/postmortem-the-boiler-incident-6986/" target="_blank" rel="noreferrer noopener">such as this one</a>.</p>



<p class="wp-block-paragraph">This felt good for a while, but still there were annoying things that needed to be done. One of them is upgrading packages to mitigate security issue. I don’t know about you, but I fall asleep each time I need to read a <a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures" target="_blank" rel="noreferrer noopener">CVE Record</a>.</p>



<p class="wp-block-paragraph">So I get AI to write me a short horror story written from the perspective of a sarcastic and frustrated application security engineer whose warnings companies have ignored at their own peril. </p>



<p class="wp-block-paragraph">The story always has some snippets that <strong>help me understand how this exploit might happen on services I am responsible for</strong>, and it always ends up with my company going bankrupt, this really makes the lessons stick and motivates me to fix the issues.</p>



<p class="wp-block-paragraph">Sure I could completely automate the bumping, but where is fun in that, and what do I learn?</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1-1024x538.png?x32039" alt="" class="wp-image-12706" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1.png 1200w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="the-production-can-be-cruel">The production can be cruel</span></h2>



<p class="wp-block-paragraph">The other thing I don’t like is the production; <strong>the production is cruel</strong>. You surround your code with all kinds of tests, you create the production like environment with simulated traffic, you use feature flags, you deploy small increments often, and still production finds the ways to surprise you, and it has a tendency not to do that during business hours.</p>



<p class="wp-block-paragraph">So you do what you must, add a bunch of observability, create runbooks and alerts. Now, with all that telemetry in place and a coding agent I can finally engage with production properly: not reactively when something goes wrong, but every day <strong>I can chat with the production</strong>, ask it about its concerns, about what is going on lately, if something feels wrong.</p>



<p class="wp-block-paragraph">I do this by invoking the skill that gathers all the data and then reports it with a certain tone of voice. And I’ll tell you one thing, gaze long enough into production telemetry and the production gazes back.</p>



<h2 class="wp-block-heading"><span id="chat-instead-of-jot">Chat instead of jot</span></h2>



<p class="wp-block-paragraph">One last example, and I envy the juniors for having the ability to do this from the start, is t<strong>he change in the way how I learn stuff</strong>. When I was starting, I used to jot down the things and concepts I did not understand, I would look them up in articles and books, I would go through half-baked internet tutorials, blog posts and man pages, and still come out with questionable understanding.</p>



<p class="wp-block-paragraph">Now I start a chat session with an AI model, give him a personality, most often it is an old and grumpy but well-mannered distinguished engineer who explains topics with a lot of examples and then asks challenging questions while throwing casual insults, he asks me a challenging question and then roasts my answer before proceeding with the next lesson.</p>



<p class="wp-block-paragraph">Hope you find some of these ideas useful, because I feel much of the talk has been on how to use AI to speed things up, and too little of the talk is about how to use AI to make software more reliable or the process of building and maintaining it more enjoyable.</p>


<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-2.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-2.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-2-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-2-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-2-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure><p>The post <a href="https://shiftmag.dev/i-talk-to-production-every-morning-it-talks-back-12679/">I Talk to Production Every Morning. It Talks Back.</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Why Early Releases Often Fail in Multi-Team Organizations</title>
		<link>https://shiftmag.dev/why-early-releases-often-fail-in-multi-team-organizations-12368/</link>
		
		<dc:creator><![CDATA[Vedran Petrović]]></dc:creator>
		<pubDate>Tue, 13 Oct 2026 11:12:07 +0000</pubDate>
				<category><![CDATA[Engineering Management]]></category>
		<category><![CDATA[Product Management]]></category>
		<category><![CDATA[Developer Productivity]]></category>
		<category><![CDATA[early release]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12368</guid>

					<description><![CDATA[<p>It all starts with one simple question from the business side: "Can we ship this early?"</p>
<p>The post <a href="https://shiftmag.dev/why-early-releases-often-fail-in-multi-team-organizations-12368/">Why Early Releases Often Fail in Multi-Team Organizations</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">At best, it means: </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">What&#8217;s the earliest reduced version we can put in front of real customers to validate against something we actually want to learn?</p>
</blockquote>



<p class="wp-block-paragraph">At worst, it’s just a <strong>date and an announcement</strong> with nothing clearly scoped behind it, so that gap needs to be closed before anyone starts building toward it.</p>



<p class="wp-block-paragraph">That’s where things usually start to go wrong. </p>



<h2 class="wp-block-heading">Business, product, and engineering often mean different things by &#8220;early release&#8221;</h2>



<p class="wp-block-paragraph">Once one customer flow is split across several teams, an early release becomes<strong> real coordination work</strong>. </p>



<p class="wp-block-paragraph">Someone has to lead it end to end, and that usually falls to no one. The reduced scope drifts and nobody is coordinating the whole release.&nbsp;With each new team that holds a certain piece of the project, coordinating them gets harder. The fix is good management, and it requires someone to actually lead the release.</p>



<p class="wp-block-paragraph">Part of the trouble is that the <strong>same words mean different things to different people </strong>who are, of course, the part of the same meeting. When the business asks for an early release, it usually means a reduced scope of something, made to be more of a barebones product than a full-sized one. This is something that’s enough to validate assumptions and deliver value while the rest is still being built.&nbsp;</p>



<p class="wp-block-paragraph">To most engineers, &#8220;done&#8221; means complete, so &#8220;early release&#8221; gets heard as &#8220;the whole thing, but fast.&#8221; Put an MVP, the smallest version that tests your least-sure assumption in the mix alongside full GA, the finished product for everyone, and one phrase is now pointing at three different targets.</p>



<p class="wp-block-paragraph">Nobody draws the line between them, so scope drifts toward GA by default: <strong>a team builds one target while the plan assumed another</strong>, and that drift is what sinks these releases.&nbsp;</p>



<h2 class="wp-block-heading">How one customer journey becomes nobody&#8217;s problem&nbsp;</h2>



<p class="wp-block-paragraph">Multi-team releases break along a predictable line, and it was mapped a long time ago. In 1968, Melvin Conway published a paper called <em><a href="https://www.melconway.com/Home/pdf/committees.pdf" target="_blank" rel="noreferrer noopener">How Do Committees Invent?</a></em> with an observation that later became known as <a href="https://en.wikipedia.org/wiki/Conway%27s_law" target="_blank" rel="noreferrer noopener">Conway&#8217;s Law</a>. The law states that organizations that design systems are constrained to <strong>produce designs that copy their own communication structure</strong>.&nbsp;&nbsp;</p>



<p class="wp-block-paragraph">Applied to a release, it predicts the break before anyone writes code: split one customer journey across five teams that mostly talk within their own walls, and the software inherits the same boundaries the organization has. The release breaks at the boundary between two teams, where the calls that need the whole picture don&#8217;t belong to anyone.</p>



<p class="wp-block-paragraph">Put that prediction next to a real feature. I kept it deliberately small here, just to picture the shape; <strong>the real ones are bigger and messier.&nbsp;&nbsp;</strong></p>



<p class="wp-block-paragraph">A customer sends across dozens of destinations, each with its own registration rules. Provisioning sets the customer up to send, sender registration gets each sender approved per destination. The hard cases raise questions neither team can answer alone: when a sender is fine in one country and refused in the next, does provisioning collect a fallback, does registration substitute one, or does the campaign ship partial?&nbsp;&nbsp;</p>



<h2 class="wp-block-heading"><span id="no-owners-means-no-decisions">No owners means no decisions</span></h2>



<p class="wp-block-paragraph">Since there&#8217;s no owner, there is no decision. </p>



<p class="wp-block-paragraph">Instead, <strong>each team codes to its own assumption and passes its own tests</strong>, and the assumptions only collide in some cases that cross between teams. The first customer with a mixed set of destinations goes live approved in some and silently refused in others. This is a fix that looks obvious at this size, but at real scale it&#8217;s dozens of these calls across five teams, and the <em>someone</em> who should make them is still <em>no one</em>.&nbsp;</p>



<p class="wp-block-paragraph">It starts when the date is set before the scope or target customer is clear. Then teams start building without knowing where to stop. One team works on an edge case for full GA, while another builds for customers who aren’t onboarded yet.</p>



<p class="wp-block-paragraph">&#8220;Early release&#8221; becomes &#8220;the whole thing&#8221; slowly, one decision at a time. It stays invisible because each team is doing good work on its own. <strong>The drift only exists at the level nobody is watching</strong>, which is the whole end-to-end journey, or the <em>big picture</em>. A release that goes out with no defined scope, no chosen customer, and no one leading it pushes the risk onto whoever is downstream.</p>



<p class="wp-block-paragraph">Cutting scope on purpose is different. You choose what to leave out and handle the rest manually, so the customer still gets value without needing the unfinished parts.</p>



<h2 class="wp-block-heading"><span id="the-case-against-shared-ownership">The case against shared ownership</span></h2>



<p class="wp-block-paragraph">Shared ownership across those teams is where the whole falls through. Everybody owns a piece, which really means no one owns the whole. </p>



<p class="wp-block-paragraph"><strong>When multiple teams each hold a piece of a customer journey, someone has to lead the end-to-end release.</strong> This should ideally be one or two people who know the flow in real detail: which service does what, where the boundaries between teams are, what a real customer actually experiences from first call to final result. &nbsp;</p>



<p class="wp-block-paragraph">A steering committee can set priorities and handle escalations, but it can’t lead the release day to day. A manager who only sees team status reports can’t do that either. The details that decide the release depend on how the pieces fit together, and neither of them is close enough to manage that.</p>



<p class="wp-block-paragraph">In practice, <strong>that leadership is coordination work, not a box on the chart</strong>. The owner learns the whole flow and keeps it in their head. They draw the reduced-scope line and publish it, so every team is working from the same picture of what &#8220;first version&#8221; means. &nbsp;</p>



<p class="wp-block-paragraph">They watch for symptoms of a team drifting, which can include&nbsp;hardening a GA edge case or generalizing too early in the process. They decide where &#8220;reduced scope&#8221; ends and &#8220;next phase&#8221; begins and call the release. Most orgs already have someone near this role. Often, that’s a <strong>product manager or a TPM</strong>.&nbsp;</p>



<h2 class="wp-block-heading"><span id="try-making-one-person-responsible-for-the-release-end-to-end">Try making one person responsible for the release end to end</span></h2>



<p class="wp-block-paragraph">Define the reduced scope and target customer before you set the date. Write it down. Give it one owner who understands the whole flow. And when the first customer hits a gap, fix it in the shared path so the next customer doesn’t run into it too.</p>



<p class="wp-block-paragraph">The reason it doesn&#8217;t happen is that leading five teams end to end is hard, unglamorous management work, and in most organizations it isn&#8217;t any single manager&#8217;s job. Each manager runs one team and looks after that team&#8217;s part of the release. <strong>The coordination across teams is no one&#8217;s job</strong>.</p>



<p class="wp-block-paragraph">Some organizations avoid this because leading the whole is already built into someone&#8217;s job, or the structure is flat enough that the whole stays visible. The teams aren&#8217;t weak and nobody is being lazy; the job that needs doing simply isn&#8217;t anyone&#8217;s job. The fix is to make one person responsible for the release end to end, and to give them the room to actually lead it.&nbsp;</p>



<p class="wp-block-paragraph">Sometimes, though, one person genuinely can&#8217;t lead the whole thing, however skilled they are. In a matrix organization, an agency where the client signs off every step, or a regulated field where the approval path is set from outside, the flow crosses boundaries a single coordinator can&#8217;t reach across.&nbsp;</p>



<p class="wp-block-paragraph">If your structure genuinely prevents one person from leading end to end, no release process will fix it, because the real constraint is how the organization is wired. The release is only where that constraint <strong>first becomes visible.&nbsp;</strong></p>


<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-1.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-1.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-1-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure><p>The post <a href="https://shiftmag.dev/why-early-releases-often-fail-in-multi-team-organizations-12368/">Why Early Releases Often Fail in Multi-Team Organizations</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Netflix Engineering Levels Explained: L3 to L7 Career Ladder, Scope, and Pay</title>
		<link>https://shiftmag.dev/netflix-engineering-levels-explained-l3-to-l7-career-ladder-scope-and-pay-12572/</link>
		
		<dc:creator><![CDATA[Marko Crnjanski]]></dc:creator>
		<pubDate>Mon, 12 Oct 2026 12:01:46 +0000</pubDate>
				<category><![CDATA[Career]]></category>
		<category><![CDATA[Developer Experience]]></category>
		<category><![CDATA[career leader]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12572</guid>

					<description><![CDATA[<p>Want to become a Netflix software engineer? Here’s an overview of Netflix’s engineering career ladder, from entry-level L3 to Software Engineer L7.</p>
<p>The post <a href="https://shiftmag.dev/netflix-engineering-levels-explained-l3-to-l7-career-ladder-scope-and-pay-12572/">Netflix Engineering Levels Explained: L3 to L7 Career Ladder, Scope, and Pay</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Netflix&#8217;s public engineering job titles include Software Engineer 3, Software Engineer 4, Senior Software Engineer (L5), Staff Software Engineer (L6), and Software Engineer L7. </p>



<p class="wp-block-paragraph">This article looks at those five individual-contributor levels. It uses <strong>Netflix job descriptions</strong>, t<strong>he company’s culture and compensation policies</strong>, and <strong>reported pay data from <a href="https://www.levels.fyi/?tab=levels" target="_blank" rel="noreferrer noopener">Levels.fyi </a></strong>to show the kind of work associated with each level. Those hiring examples should not be treated as Netflix’s internal promotion criteria.</p>



<h1 class="wp-block-heading"><span id="engineering-levels-and-compensation">Engineering levels and compensation</span></h1>



<p class="wp-block-paragraph">Levels.fyi labels L3 through L7 as Engineer, Engineer II, Senior Engineer, Staff Engineer, and Principal Engineer. Netflix&#8217;s recruiting titles vary, sometimes using only a number. The examples below describe particular advertised roles; <strong>they are not a uniform specification for every engineer at that level</strong>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="256" src="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.31-1024x256.png?x32039" alt="" class="wp-image-12583" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.31-1024x256.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.31-300x75.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.31-767x192.png 767w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.31.png 1147w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Based on the last information checked on October 9, 2026, the individual US level pages on Levels.fyi displayed average annual total compensation of approximately <strong>$214K at L3, $321K at L4, $509K at L5, $704K at L6, and $1.14M at L7</strong>. </p>



<p class="wp-block-paragraph">Separately, the company overview reported a median of $430K across US software engineer submissions. What should be noted is these are reported compensation figures, not Netflix&#8217;s official pay bands or a representative census of its employees.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="259" src="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.18-1024x259.png?x32039" alt="" class="wp-image-12584" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.18-1024x259.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.18-300x76.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.18-766x194.png 766w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.18.png 1145w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Netflix&#8217;s engineering listings generally describe annual compensation without a separate bonus. Its <em><a href="https://jobs.netflix.com/work-life-philosophy" target="_blank" rel="noreferrer noopener">Work Life Philosophy</a></em> says eligible employees <strong>choose each year how much compensation to receive as salary or stock options</strong>. Under its Personal Top of Market approach, the company assesses an individual&#8217;s market value rather than defining the market through fixed bands and grades. The advertised ranges still depend on the role and can vary by location.</p>



<p class="wp-block-paragraph">For example, the L4 DevOps listing specifies $250K to $413K, and the L6 Developer Productivity listing specifies $600K to $1.066M. The published L7 Growth Engineering description gives a range of $240K to $1.2M. Such overlapping ranges are a reason to check the specific role and offer: <strong>they cannot be used as a standard salary schedule for L4, L6, or L7</strong>.</p>



<h1 class="wp-block-heading"><span id="l3-and-l4-experience-requirements-and-project-ownership">L3 and L4 Experience requirements and project ownership</span></h1>



<p class="wp-block-paragraph">Netflix has a dedicated US <a href="https://jobs.netflix.com/careers/new-grads" target="_blank" rel="noreferrer noopener">new-graduate program</a> that includes technical roles, onboarding, and training. Its careers page says new-graduate openings typically appear in September or October, depending on hiring needs. Levels.fyi identifies L3 as entry level, but that <strong>does not mean every Software Engineer 3 vacancy is suitable for someone straight out of university</strong>.</p>



<p class="wp-block-paragraph">The Software Engineer 3 role at Ink, for example, asks for three to five years of software engineering experience, preferably in animation production. It involves working with senior colleagues on tools and platforms for AI-assisted production. That is a specific hiring requirement for a specialist role, not a universal experience threshold for L3.</p>



<p class="wp-block-paragraph">Speaking about L4, the DevOps and CI/CD posting asks for at least four years of professional experience or equivalent practical experience. It describes work on defined parts of larger platform initiatives, with guidance from senior engineers and a manager. An Android L4 posting expects ownership from project scoping through delivery, while still stressing the importance of team support.</p>



<p class="wp-block-paragraph">Together, those examples suggest <strong>increasing independence at L4, with the amount of guidance depending on the role</strong>. Project ownership and support from more experienced colleagues appear together in these descriptions.</p>



<h1 class="wp-block-heading"><span id="l5-senior-engineering-and-system-ownership">L5 Senior engineering and system ownership</span></h1>



<p class="wp-block-paragraph">Globally popular streaming platform has advertised Senior Software Engineer positions at L5. A useful example is its Analysis role in the Experimentation Platform team, which combines responsibility for production systems with input into architecture and the team&#8217;s roadmap.</p>



<p class="wp-block-paragraph">The archived Analysis listing describes workflows processing billions of events each day. Its responsibilities include developing experiment-analysis tooling, responding to incidents, improving reliability, and agreeing data and API contracts with other teams. <strong>The engineer is also expected to understand how product teams use experiments</strong>. These details show that the job extends beyond implementing a predefined feature.</p>



<p class="wp-block-paragraph">In this role, senior responsibility includes <strong>accounting for the operational consequences of a design</strong> and the needs of the teams using it. Netflix&#8217;s emphasis on independent judgment provides context for that work, but the Culture Memo applies across the company rather than defining separate expectations for L5.</p>



<h1 class="wp-block-heading"><span id="l6-staff-engineering-across-teams">L6 Staff engineering across teams</span></h1>



<p class="wp-block-paragraph">At L6, Netflix explicitly advertises <strong>Staff Software Engineer roles</strong>. The AIMS Platform Systems examples make the wider scope concrete: the engineer works on infrastructure used by other engineering and research teams.</p>



<p class="wp-block-paragraph">The <strong>Developer Productivity role</strong> covers development environments, build and test systems, CI/CD, and tools used to move research into production experiments. It also calls for measuring build times and iteration speed, supporting adoption, and setting shared technical standards.</p>



<p class="wp-block-paragraph">The <strong>Staff ML role</strong> focuses on observability, infrastructure cost, and reliability, alongside contributing to architecture and migration planning with other teams.</p>



<p class="wp-block-paragraph">These examples suggest <strong>that Staff responsibility includes getting shared systems adopted and making them useful across AIMS</strong>. The developer productivity posting makes that test concrete: the tools need to improve how other teams build and run experiments. The work combines hands-on engineering with coordination across teams.</p>



<h1 class="wp-block-heading"><span id="l7-technical-direction-across-an-organization">L7 Technical direction across an organization</span></h1>



<p class="wp-block-paragraph">Levels.fyi calls Netflix L7 Principal Engineer, while the Growth Engineering job description uses Software Engineer L7. Its responsibilities are defined around the Growth Engineering organization, so the scope is more informative than the title alone.</p>



<p class="wp-block-paragraph">The published role reports to a Senior Director <strong>and asks for at least 15 years of professional software development experience as an individual contributor</strong>. It includes setting architectural direction across Growth Engineering, connecting business goals to technology investments, and working with senior leaders and other L7 engineers. The experience requirement belongs to this vacancy, not to a published rule for every L7 role.</p>



<p class="wp-block-paragraph">The remit is broad technical leadership within Growth Engineering. It combines architectural decisions with continued expertise in production systems and mentoring other engineers, including helping managers support their teams&#8217; development.</p>



<h1 class="wp-block-heading"><span id="comparing-level-names-across-companies">Comparing level names across companies</span></h1>



<p class="wp-block-paragraph">Level numbers are company-specific. Levels.fyi places <a href="https://shiftmag.dev/google-career-ladder-explained-for-engineers-10368/" data-type="post" data-id="10368" target="_blank" rel="noreferrer noopener">Google&#8217;s Senior Software Engineer title</a> at L5 and Staff at L6, while Amazon uses L6 for Senior SDE and L7 for Principal SDE. Meta uses E-level labels in the same database. These naming conventions can help a candidate navigate vacancies, but they do not establish equivalent responsibilities or hiring standards.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="261" src="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.02-1024x261.png?x32039" alt="" class="wp-image-12585" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.02-1024x261.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.02-766x195.png 766w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.02-300x76.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/Screenshot-2026-10-09-at-12.51.02.png 1147w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">The distinction matters most above Senior. For example, Google&#8217;s L7 is Senior Staff and its Principal title appears at L8, whereas Levels.fyi labels Netflix L7 Principal. <strong>A shared title or similar number does not show where an engineer would be placed after changing companies</strong>. The role&#8217;s technical remit and the employer&#8217;s assessment remain necessary context.</p>



<h1 class="wp-block-heading"><span id="how-culture-affects-engineering-work">How culture affects engineering work</span></h1>



<p class="wp-block-paragraph">Netflix&#8217;s <a href="https://jobs.netflix.com/culture" target="_blank" rel="noreferrer noopener">Culture Memo</a> highlights <strong>judgment, candid feedback, and giving employees enough context to make decisions</strong>. It also expects managers to stay involved and coach their teams. Autonomy should therefore not be mistaken for an absence of support, nor treated as a benefit reserved for senior levels.</p>



<p class="wp-block-paragraph">The keeper test is part of that performance culture. Managers are asked whether they would try to retain someone or choose to hire them again.<strong> If the answer is no, Netflix says it favors ending the employment relationship promptly</strong>. The memo also says to assess a person&#8217;s overall record, discuss performance regularly, and support employees through short-term setbacks.</p>



<p class="wp-block-paragraph">For a candidate, the practical next step is to ask how the hiring team defines scope at the advertised level, what support is available, and how progression is assessed. Public postings can help frame that conversation. They cannot supply a guaranteed promotion timetable or the terms of an individual offer.</p>


<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1672" height="941" src="https://shiftmag.dev/wp-content/uploads/2026/10/netflix-career-ladder.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/netflix-career-ladder.png 1672w, https://shiftmag.dev/wp-content/uploads/2026/10/netflix-career-ladder-300x169.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/netflix-career-ladder-768x432.png 768w, https://shiftmag.dev/wp-content/uploads/2026/10/netflix-career-ladder-1024x576.png 1024w" sizes="auto, (max-width: 1672px) 100vw, 1672px" /></figure><p>The post <a href="https://shiftmag.dev/netflix-engineering-levels-explained-l3-to-l7-career-ladder-scope-and-pay-12572/">Netflix Engineering Levels Explained: L3 to L7 Career Ladder, Scope, and Pay</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How 5,000 RPS Exposed the Real Bottleneck in Our Jetty Messaging Service</title>
		<link>https://shiftmag.dev/performance-tuning-is-about-finding-the-real-bottleneck-11823/</link>
		
		<dc:creator><![CDATA[Slawomir Luty]]></dc:creator>
		<pubDate>Fri, 09 Oct 2026 12:50:10 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[performance testing]]></category>
		<category><![CDATA[reactive programming]]></category>
		<category><![CDATA[virtual threads]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=11823</guid>

					<description><![CDATA[<p>We started with a simple question: how much traffic can the service really handle? The answer was in understanding the system’s real limits.</p>
<p>The post <a href="https://shiftmag.dev/performance-tuning-is-about-finding-the-real-bottleneck-11823/">How 5,000 RPS Exposed the Real Bottleneck in Our Jetty Messaging Service</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1350" height="709" src="https://shiftmag.dev/wp-content/uploads/2026/09/measure-your-service.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/09/measure-your-service.png 1350w, https://shiftmag.dev/wp-content/uploads/2026/09/measure-your-service-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/09/measure-your-service-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/09/measure-your-service-768x403.png 768w" sizes="auto, (max-width: 1350px) 100vw, 1350px" /></figure>


<p class="wp-block-paragraph">In my team in Infobip, we handle message sending and serve as an endpoint for OTT providers such as WhatsApp, Viber, and Apple. Because of that, <strong>message sending is our core responsibility</strong>, and we need to be aware of any bottlenecks.</p>



<p class="wp-block-paragraph">Initially, our service was measured at around 1,000 requests per second, but we didn’t know why. </p>



<p class="wp-block-paragraph">From time to time, this raised concerns in the team: <strong>we should understand better where the bottleneck is</strong> and what causes it. Once we know that, we can make informed decisions to address client needs &#8211; for example, answering whether we can handle the traffic they expect to send. That was partly what led to this investigation.</p>



<h2 class="wp-block-heading"><span id="how-to-run-the-tests">How to run the tests</span></h2>



<h3 class="wp-block-heading"><span id="application">Application</span></h3>



<p class="wp-block-paragraph">Initially, with no experience in performance testing, I viewed the service as a set of methods &#8211; essentially a stack of calls. I assumed I could analyze it with a profiler. I also knew I shouldn’t run it on my computer, because other applications would affect the service’s performance.</p>



<p class="wp-block-paragraph">That turned out to be a bad assumption. I’d suggest starting by <strong>measuring the application as a whole</strong> to get a broader view of its performance.</p>



<h3 class="wp-block-heading"><span id="integration">Integration</span></h3>



<p class="wp-block-paragraph">Since our application forwards messages further down the infrastructure and ultimately to the provider, it had to be adapted so that it would not send real traffic, while preserving as much of the original logic as possible.</p>



<p class="wp-block-paragraph">Initial tests of this version showed that the service could handle a request in 0 ms, which seemed unrealistic. I realized that I needed to introduce a <strong>delay based on production</strong>, where the rounded average request processing time is around 50 ms.</p>



<h3 class="wp-block-heading"><span id="initial-measurements">Initial measurements</span></h3>



<p class="wp-block-paragraph">Having established that the service handles one request in 50 ms, we can estimate that it can process about 20 requests per second. Since the service is Jetty-based, it has roughly 200 threads available by default, which gives a theoretical peak of around<strong> 4,000 requests per second</strong>. With that in place, the service can now be tested.</p>



<h3 class="wp-block-heading"><span id="testing-environment">Testing environment</span></h3>



<ul class="wp-block-list">
<li>DO NOT run such tests on a local machine.</li>



<li>Dedicated machine on our testing env was created for it.</li>



<li>K6 was chosen as test suite.</li>



<li>Rundeck to automate and parameterize remotely run tests.</li>
</ul>



<h3 class="wp-block-heading"><span id="endpoints-to-be-tested-against">Endpoints to be tested against:</span></h3>



<ul class="wp-block-list">
<li><code>/mapi-mock/1/dummy</code>&nbsp;&#8211; performs <code>Thread.sleep(50)</code> &#8211; so it is blocking code run on Jetty thread pool</li>



<li><code>/mapi-mock/1/dummyReactor</code>&nbsp;&#8211; also performs&nbsp;<code>Thread.sleep(50)</code>but publishing result on boundedElastic thread pool &#8211; it is still blocking code, but in that case one thread of reactor&#8217;s pool will be used</li>



<li><code>/mapi-mock/1/messages</code>&nbsp;&#8211; non-blocking code which sends request through WebClient to real service</li>



<li><code>/mapi-mock/1/messagesReactor</code>&nbsp;&#8211; non-blocking code which sends request through WebClient but publishing it on boundedElastic</li>
</ul>



<h3 class="wp-block-heading"><span id="jvm-tuning">JVM tuning</span></h3>



<p class="wp-block-paragraph">Make sure the correct memory parameter is used. In my case, <code>HEAP_PERCENT</code> was set to 60, meaning the JVM heap used 60% of the machine’s RAM. That allowed me to focus on machine RAM only, and the heap size would be adjusted automatically. This is not ideal, but it was good enough for our tests.</p>



<h3 class="wp-block-heading"><span id="metrics-gathering">Metrics gathering</span></h3>



<p class="wp-block-paragraph">Initially, I ran the tests for 40 seconds, but I forgot that the metrics were collected every 30 seconds. That explains why I didn’t see any issues in the service metrics during the first run. When I extended the test duration to 180 seconds (a value I borrowed from similar tests) everything became visible.</p>



<p class="wp-block-paragraph"><strong>You can also observe the machine directly with tools like <code>htop</code> or <code>top</code></strong>, or any other tool that shows current CPU and memory usage. In the end, you can use whichever tool helps you complete the task.</p>



<p class="wp-block-paragraph">One obvious but important rule: <strong>do not change two variables at the same time unless you know what you are doing</strong>. If you do, you won’t know which parameter had the effect. Change one thing, test it, then change the next thing, and repeat until you understand what is happening.know what is going on.</p>



<h2 class="wp-block-heading"><span id="gathering-measurements">Gathering measurements</span></h2>



<p class="wp-block-paragraph">Initially, <strong>I decided to send up to 5k requests toward the service</strong> &#8211; it is below theoretical machine efficiency, but higher than what was experienced in the past. Lower CPU and RAM measurements are somewhat weird: 4 GB of RAM is not recommended as a base machine setup, because there is less than 2 GB of RAM left for the operating system, where not only our service lives, but also supporting applications. But both measurements for 2 CPU showed that it is way too low for handling any traffic efficiently and it showed quite high CPU and RAM usage, meaning that it could be improved. I finished the tests with 5k requests/s, when performance was quite near predicted performance.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="643" src="https://shiftmag.dev/wp-content/uploads/2026/10/s2-1024x643.jpg?x32039" alt="" class="wp-image-12547" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/s2-1024x643.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/s2-768x482.jpg 768w, https://shiftmag.dev/wp-content/uploads/2026/10/s2-300x188.jpg 300w, https://shiftmag.dev/wp-content/uploads/2026/10/s2.webp 1088w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">The theoretical peak was reached, so it was time to check whether it could be improved. <strong>I tried switching from Jetty pool to Reactor pool</strong>, but it turned out (my bad for not remembering Project Reactor documentation by heart) that to reach the initial performance I had to configure the machine with 20 CPU, because Reactor constructs the pool to have 10 * CPU threads. So when I matched theoretical performance again, but now with the Reactor pool, I thought about what could be done next to improve. The last thing to check was how non-blocking code would perform, so I started using the <code>/mapi-mock/1/messages*</code> endpoints for testing. As one would predict, it was hit. The application peaked at 7,000 requests/s, but with quite large demands for hardware. So the last thing to check was to try to find reasonable settings to have big enough performance with not much resources assigned.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="574" src="https://shiftmag.dev/wp-content/uploads/2026/10/s3-1024x574.jpg?x32039" alt="" class="wp-image-12548" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/s3-1024x574.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/s3-300x168.jpg 300w, https://shiftmag.dev/wp-content/uploads/2026/10/s3-767x430.jpg 767w, https://shiftmag.dev/wp-content/uploads/2026/10/s3.webp 1339w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">Now we are focusing on the <strong>non-blocking endpoint</strong>, so it more reflects the real-case scenario, and on limiting resources. The first thing that is apparent is that when it comes to non-blocking code, there is no difference between Jetty thread pool and boundedElastic thread pool (the latter results in some queuing because the rule of 10 * CPU threads is always true). We can see performance downgrade with CPUs removal, but not apparently linear. I had to say &#8220;stop&#8221; somewhere, and I decided to stop with 8 CPU and 8 GB of RAM, for which we received ~3.5k requests/s. Good enough with not much resources assigned. As we can scale horizontally, adding more machines will use more resources, but give more resiliency back.<img decoding="async" srcset="https://media-cdn.atlassian.com/file/8dff5700-9afa-4aae-a04c-bd06a3193a66/image/cdn?allowAnimated=true&amp;client=978ef90e-12de-4e06-8440-5a847a8913b7&amp;collection=contentId-575373490&amp;height=125&amp;max-age=2592000&amp;mode=full-fit&amp;source=mediaCard&amp;token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI5NzhlZjkwZS0xMmRlLTRlMDYtODQ0MC01YTg0N2E4OTEzYjciLCJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpjb2xsZWN0aW9uOmNvbnRlbnRJZC01NzUzNzM0OTAiOlsicmVhZCJdfSwiZXhwIjoxNzg4MzU0NzY5LCJuYmYiOjE3ODgzNTE4ODksImFhSWQiOiI3MTIwMjA6OGQ5MzU5MzEtNjhjZC00MDkyLWE4MTQtOThiYjM3Y2NhYTFhIiwiaHR0cHM6Ly9pZC5hdGxhc3NpYW4uY29tL2FwcEFjY3JlZGl0ZWQiOmZhbHNlLCJhdXRoVHlwZSI6InNlc3Npb24ifQ.FyDYJ8GOtTYn3qys-d5COcquLC4e2LvFovDCLTvyxwU&amp;width=1339#media-blob-url=true&amp;id=8dff5700-9afa-4aae-a04c-bd06a3193a66&amp;clientId=978ef90e-12de-4e06-8440-5a847a8913b7&amp;contextId=contentId-575373490&amp;collection=contentId-575373490 1x, https://media-cdn.atlassian.com/file/8dff5700-9afa-4aae-a04c-bd06a3193a66/image/cdn?allowAnimated=true&amp;client=978ef90e-12de-4e06-8440-5a847a8913b7&amp;collection=contentId-575373490&amp;height=250&amp;max-age=2592000&amp;mode=full-fit&amp;source=mediaCard&amp;token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI5NzhlZjkwZS0xMmRlLTRlMDYtODQ0MC01YTg0N2E4OTEzYjciLCJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpjb2xsZWN0aW9uOmNvbnRlbnRJZC01NzUzNzM0OTAiOlsicmVhZCJdfSwiZXhwIjoxNzg4MzU0NzY5LCJuYmYiOjE3ODgzNTE4ODksImFhSWQiOiI3MTIwMjA6OGQ5MzU5MzEtNjhjZC00MDkyLWE4MTQtOThiYjM3Y2NhYTFhIiwiaHR0cHM6Ly9pZC5hdGxhc3NpYW4uY29tL2FwcEFjY3JlZGl0ZWQiOmZhbHNlLCJhdXRoVHlwZSI6InNlc3Npb24ifQ.FyDYJ8GOtTYn3qys-d5COcquLC4e2LvFovDCLTvyxwU&amp;width=2678#media-blob-url=true&amp;id=8dff5700-9afa-4aae-a04c-bd06a3193a66&amp;clientId=978ef90e-12de-4e06-8440-5a847a8913b7&amp;contextId=contentId-575373490&amp;collection=contentId-575373490 2x" src="https://media-cdn.atlassian.com/file/8dff5700-9afa-4aae-a04c-bd06a3193a66/image/cdn?allowAnimated=true&amp;client=978ef90e-12de-4e06-8440-5a847a8913b7&amp;collection=contentId-575373490&amp;height=125&amp;max-age=2592000&amp;mode=full-fit&amp;source=mediaCard&amp;token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI5NzhlZjkwZS0xMmRlLTRlMDYtODQ0MC01YTg0N2E4OTEzYjciLCJhY2Nlc3MiOnsidXJuOmZpbGVzdG9yZTpjb2xsZWN0aW9uOmNvbnRlbnRJZC01NzUzNzM0OTAiOlsicmVhZCJdfSwiZXhwIjoxNzg4MzU0NzY5LCJuYmYiOjE3ODgzNTE4ODksImFhSWQiOiI3MTIwMjA6OGQ5MzU5MzEtNjhjZC00MDkyLWE4MTQtOThiYjM3Y2NhYTFhIiwiaHR0cHM6Ly9pZC5hdGxhc3NpYW4uY29tL2FwcEFjY3JlZGl0ZWQiOmZhbHNlLCJhdXRoVHlwZSI6InNlc3Npb24ifQ.FyDYJ8GOtTYn3qys-d5COcquLC4e2LvFovDCLTvyxwU&amp;width=1339#media-blob-url=true&amp;id=8dff5700-9afa-4aae-a04c-bd06a3193a66&amp;clientId=978ef90e-12de-4e06-8440-5a847a8913b7&amp;contextId=contentId-575373490&amp;collection=contentId-575373490" alt=""></p>



<h2 class="wp-block-heading">&nbsp;The thing with VT&#8230;</h2>



<p class="wp-block-paragraph">As you can see, I focused on measuring reactive vs non-reactive code. </p>



<p class="wp-block-paragraph">It was our go-to architecture at that time, while VT was being adopted slowly (we were afraid of thread pinning, so we waited until it was addressed in JDK 24 to start adoption). After I published it internally, I was asked specifically about VT &#8211; how the app would perform when configured to use this not-so-new-but-fixed feature. </p>



<p class="wp-block-paragraph"><strong>It turned out that VT gave the app a boost.</strong> With optimal configuration (8 CPU and 8 GB of RAM) the app was able to handle 10k requests/s. Why is that? Any code, regardless of whether it is blocking or not, will be run on a virtual thread, which ideally should not block a system thread, leading to the case where system threads are used only for real logic and not for waiting. VT can improve applications where there is a lot of blocking code. In the rest of the cases, it is &#8220;just&#8221; syntactic freedom, no more looking at <a href="https://projectreactor.io/docs/core/release/reference/apdx-operatorChoice.html" target="_blank" rel="noreferrer noopener">which operator do I need</a>?</p>



<h2 class="wp-block-heading"><span id="the-outcome">The outcome</span></h2>



<p class="wp-block-paragraph">When I performed the tests, I observed that just switching to <code>boundedElastic</code> (i.e. “use Reactor and you will get higher TPS”) didn’t increase throughput &#8211; it actually reduced it. Not remembering the Project Reactor documentation by heart, I was surprised, but after some research I found that <code>boundedElastic</code> provides <code>10 * CPU</code> threads, which gave us a total of 60 threads to service all requests previously handled by 200 Jetty threads.</p>



<p class="wp-block-paragraph">When the CPU count was adjusted to match 200 Jetty threads (20 CPUs) we reached the expected throughput. But it was wasteful in terms of resources. In the Reactor world, people often say that blocking is bad, and my service was actually doing exactly that, on purpose. I thought it was time to switch to a different endpoint.</p>



<p class="wp-block-paragraph">So <strong>I was able to nearly reach the estimated performance of the service</strong>, which was good. That allowed me to move on and investigate other ways of improving it, such as using non-blocking code or VT.</p>



<h2 class="wp-block-heading"><span id="what-i%e2%80%99ve-learned">What I’ve learned</span></h2>



<p class="wp-block-paragraph">It is always about<strong> finding the bottleneck and finding out if we can improve it</strong>, for example by adding resources or redesigning it. If it is not to be improved, then this is the peak capacity of the service.</p>



<p class="wp-block-paragraph"><strong>Sometimes questions from clients can actually help</strong>. It is just like with a new person joining the team: they will ask obvious questions about all-known solutions, but if you want to respond accurately, you have to dig deeper, and sometimes you find out that this simple question leads to an investigation and even to questioning whether it is correct at all.</p>



<p class="wp-block-paragraph">Also,<strong> be aware of architecture</strong>. In that scenario, we tested a service which accepts requests, so it is one of the first applications, or APIs, which the client experiences. Being first means that there is the rest of the system, which can in turn have throttling applied. What does it mean? Even if we accept 10k requests/s, sometimes we cannot send them immediately, because an independent system cannot handle, for example, more than 2k requests/s. So we can be fast for clients, in the sense that we accept their traffic as fast as they want, but we should always remember that this is not the whole picture, and the client should be informed about it.</p>



<p class="wp-block-paragraph"><strong>In my test there was no DB, just API-to-API calls</strong>. Having any limited, and even worse blocking, resource like a DB in the way of processing a request will definitely impact its performance.</p>
<p>The post <a href="https://shiftmag.dev/performance-tuning-is-about-finding-the-real-bottleneck-11823/">How 5,000 RPS Exposed the Real Bottleneck in Our Jetty Messaging Service</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Real Problem in Voice AI Is Latency</title>
		<link>https://shiftmag.dev/voice-ai-is-an-infrastructure-problem-not-just-a-model-problem-12540/</link>
		
		<dc:creator><![CDATA[Marin Pavelić]]></dc:creator>
		<pubDate>Fri, 09 Oct 2026 10:37:21 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[Infobip Shift 2026]]></category>
		<category><![CDATA[Kosta Pribić]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Voice AI]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12540</guid>

					<description><![CDATA[<p>Voice AI may be sold as a model problem, but the real bottleneck is whether the system can survive real-time demands, stay reliable, and do it at a cost that makes sense.</p>
<p>The post <a href="https://shiftmag.dev/voice-ai-is-an-infrastructure-problem-not-just-a-model-problem-12540/">The Real Problem in Voice AI Is Latency</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="720" src="https://shiftmag.dev/wp-content/uploads/2026/10/kosta-pribicevic-vocie-ai.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/kosta-pribicevic-vocie-ai.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/10/kosta-pribicevic-vocie-ai-300x180.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/kosta-pribicevic-vocie-ai-767x460.png 767w, https://shiftmag.dev/wp-content/uploads/2026/10/kosta-pribicevic-vocie-ai-1024x614.png 1024w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">&#8220;Voice AI is an infrastructure problem because <strong>voice itself is an infrastructure problem</strong>,&#8221; says Kosta Pribić, a Senior Principal Engineer at Infobip. </p>



<p class="wp-block-paragraph">He works with voice services &#8211; real-time communications across the globe, across multiple data centers, and for everyone reachable on the planet. Yep, it’s a lot.</p>



<p class="wp-block-paragraph">That scale makes voice AI a <strong>much more complex challenge than developers might initially expect</strong>.<br></p>



<h2 class="wp-block-heading"><span id="developers-can-take-control-of-the-call-in-real-time">Developers can take control of the call in real time</span></h2>



<p class="wp-block-paragraph">Kosta sees voice AI as a two-layer system. <strong>Smaller models built into phones can handle real-time issues</strong> like packet loss and background noise. They should do their work quietly in the background, so the device just feels like it works.</p>



<p class="wp-block-paragraph"><strong>Larger models</strong>, meanwhile, <strong>usually run in the cloud</strong> and need access to the audio being exchanged between devices. That’s where Infobip comes in: it provides the communications infrastructure developers need to process that audio in real time.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">We give you control over the call. We enable you to interject, do something smart with the media.</p>
</blockquote>



<p class="wp-block-paragraph">He says a lot of the infrastructure behind this, from global data centers to enterprise deployments, was originally built for web pages. But <strong>web pages aren’t real-time communication</strong>.</p>



<p class="wp-block-paragraph">So when teams use that infrastructure for voice AI, they end up carrying over decisions that were made decades ago. Those systems weren’t built for a live AI-assisted call, which means developers are often stuck working around constraints they probably wouldn’t choose if they were starting from scratch today.</p>



<h2 class="wp-block-heading"><span id="biggest-challenges-are-real-time-performance-and-cost">Biggest challenges are real-time performance and cost</span></h2>



<p class="wp-block-paragraph">Developers entering <a href="https://www.infobip.com/blog/ai-voice-assistants" target="_blank" rel="noreferrer noopener">voice AI</a> <strong>often expect hallucinations to be the biggest challenge</strong>. But Kosta says they usually run into a different set of problems first, like custom signaling protocols, real-time delivery, and tricky networking edge cases. Networks aren’t built for this kind of traffic by default, so for developers without a voice background, it can feel like a completely new set of problems to learn.</p>



<p class="wp-block-paragraph">&#8220;The main problem is understanding all of this. It’s completely new,&#8221; he says. That’s why Infobip’s first internally built LLM-enabled application was a voice AI troubleshooter. <strong>Kosta sees troubleshooting as a practical place to start</strong>, because teams first need to understand the communication problems they’re actually dealing with.</p>



<p class="wp-block-paragraph">From there, model choice comes down to the <strong>business case and the margins</strong>. Kosta says a large model can make sense when latency isn’t a major concern and the economics work. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">If your business case allows for using huge LLMs and you don’t care that much about latency, great, go for it.</p>
</blockquote>



<p class="wp-block-paragraph">But <strong>in most cases</strong>, he says, <strong>latency matters</strong>. Teams may need smaller LLMs to process calls, or fast, lightweight models to handle audio. Cost matters too, especially when a model is running on every call, because a large model can become expensive fast.</p>



<h2 class="wp-block-heading"><span id="voice-ai-has-to-be-private-reliable-and-real-time">Voice AI has to be private, reliable, and real-time</span></h2>



<p class="wp-block-paragraph">People expect voice-enabled communications to be private and confidential, Kosta says. They also expect calls to be as reliable as the telecom services they already use, which he describes as operating at &#8220;five nines.&#8221; <strong>Once that trust is lost, it’s much harder to win back</strong>.</p>



<p class="wp-block-paragraph">For developers who are new to voice, understanding those expectations is part of understanding the system they’re building.</p>



<p class="wp-block-paragraph">That becomes especially clear in <strong>assistive use cases</strong>. Kosta points to an Infobip customer using a generative model to create voices for people with damaged vocal cords:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">They can speak in a whisper while the person on the other end hears the generated voice. That’s, I think, the most heartwarming implementation I’ve ever done.</p>
</blockquote>



<p class="wp-block-paragraph">In the end, before choosing a model, developers need to understand how a call works, where it can break down, and how much delay and cost the application can handle. Even the best model won’t help if its response can’t make it back to the caller in time.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Inside an AI Phone Call" width="500" height="281" src="https://www.youtube.com/embed/xEWWc0tVPjY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://shiftmag.dev/voice-ai-is-an-infrastructure-problem-not-just-a-model-problem-12540/">The Real Problem in Voice AI Is Latency</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Make Honesty Less Risky Than Silence for Your Engineering Team</title>
		<link>https://shiftmag.dev/make-honesty-less-risky-than-silence-for-your-engineering-team-12382/</link>
		
		<dc:creator><![CDATA[Marko Sertić]]></dc:creator>
		<pubDate>Thu, 08 Oct 2026 10:52:46 +0000</pubDate>
				<category><![CDATA[Engineering Management]]></category>
		<category><![CDATA[Software Engineering]]></category>
		<category><![CDATA[career development]]></category>
		<category><![CDATA[communication]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12382</guid>

					<description><![CDATA[<p>Your team may already know the risk. The question is whether they feel safe saying it.</p>
<p>The post <a href="https://shiftmag.dev/make-honesty-less-risky-than-silence-for-your-engineering-team-12382/">Make Honesty Less Risky Than Silence for Your Engineering Team</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/ShiftMag-article-banner-3-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">It is Thursday afternoon, and your team is preparing a release promised for Monday. The deadline has already moved once. Sales and leadership know about it, and everybody wants this thing to ship.</p>



<p class="wp-block-paragraph">During the final review, <strong>one of the engineers notices something strange in the database migration</strong>. Nothing is obviously broken, no dashboard is red, and no test is failing. But something just doesn’t feel right.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">We reviewed this three times already. Are we really reopening this now?</p>
</blockquote>



<p class="wp-block-paragraph">There is a short silence, then: &#8220;No, no. It’s probably fine.&#8221;</p>



<p class="wp-block-paragraph">So they ship. </p>



<p class="wp-block-paragraph">On Monday, <strong>production goes down</strong>, and during the incident review someone asks, &#8220;How did we not see this coming?&#8221;</p>



<p class="wp-block-paragraph">The interesting part is that somebody did but the problem was that <strong>saying more about the risk felt more dangerous than staying quiet</strong>.</p>



<p class="wp-block-paragraph">That is what psychological safety is really about: not whether people are nice to each other, but a more useful question &#8211; what does honesty cost on your team?</p>



<h2 class="wp-block-heading"> &#8220;If I stay silent, probably nothing happens to me today. &#8220;</h2>



<p class="wp-block-paragraph">People constantly make small risk calculations at work. If I speak up, I might look difficult or incompetent, annoy my manager, or damage my reputation. If I stay silent, probably nothing happens to me today. </p>



<p class="wp-block-paragraph">When the social risk of speaking is higher than the immediate risk of staying quiet, teams learn silence.</p>



<p class="wp-block-paragraph">Amy Edmondson defines psychological safety as a <strong>shared belief that the team is safe for interpersonal risk-taking</strong>. My engineering translation is simpler:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Can I say the thing that might make me look bad?</p>
</blockquote>



<p class="wp-block-paragraph">In engineering teams, that risk shows up in ordinary moments: <strong>admitting a mistake</strong>, <strong>challenging someone’s thinking</strong>, <strong>bringing bad news, or saying</strong> <strong>&#8220;I don’t know.&#8221;</strong></p>



<p class="wp-block-paragraph">Those moments all ask the same thing: what happens if I say this out loud?</p>



<p class="wp-block-paragraph">That is why I think of them as four simple tests: if you want to understand a team, just<strong> watch what happens when someone says one of them</strong>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="576" src="https://shiftmag.dev/wp-content/uploads/2026/10/the-signal-gets-lost-1024x576.webp?x32039" alt="" class="wp-image-12522" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/the-signal-gets-lost-1024x576.webp 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/the-signal-gets-lost-300x169.webp 300w, https://shiftmag.dev/wp-content/uploads/2026/10/the-signal-gets-lost-768x432.webp 768w, https://shiftmag.dev/wp-content/uploads/2026/10/the-signal-gets-lost.webp 1672w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">As in life, what you mean is often not what comes across to the other person. </figcaption></figure>



<h2 class="wp-block-heading"><span id="psychological-safety-is-not-about-being-nice">Psychological safety is not about being nice</span></h2>



<p class="wp-block-paragraph">A common misunderstanding is that psychological safety means avoiding conflict or lowering standards but it&#8217;s not. Sometimes the safest thing to say is, “This is not good enough.”</p>



<p class="wp-block-paragraph">That can be uncomfortable, but the goal is <strong>having hard conversations early enough to change something</strong>.</p>



<p class="wp-block-paragraph">For example, in a design review, a senior engineer sees a scaling concern but doesn&#8217;t want to turn a thirty-minute meeting into another debate. So they say:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Looks good overall, just one small thought: maybe we should think a bit more about how this scales, but definitely not a blocker.</p>
</blockquote>



<p class="wp-block-paragraph">The manager hears: &#8220;No blocker.&#8221;</p>



<p class="wp-block-paragraph">The meeting ends, everyone was polite, nobody was aggressive, and nobody left uncomfortable.</p>



<p class="wp-block-paragraph">Three weeks later, the system starts struggling and the is a question:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Why didn’t anyone raise this during the design review?</p>
</blockquote>



<p class="wp-block-paragraph">The engineer thinks: &#8220;I did.&#8221;</p>



<p class="wp-block-paragraph">The manager thinks: &#8220;No, you didn’t, you said it wasn’t a blocker.&#8221;</p>



<p class="wp-block-paragraph"><strong>Neither person is the villain here</strong>. The engineer was trying to be polite, but the manager heard something different. The gap between what was meant and what was said was the problem.</p>



<p class="wp-block-paragraph">The engineer meant: &#8220;This could seriously hurt us in production. Maybe we should keep an eye on it.&#8221;</p>



<p class="wp-block-paragraph">The manager heard: &#8220;No real concern.&#8221;</p>



<p class="wp-block-paragraph">Words like <em>just</em>, <em>small</em>, <em>maybe</em>, <em>perhaps</em>, and <em>not a blocker </em>can soften a message until the point gets lost. <strong>The answer is clarity without extra threat</strong>. The goal is candor with high standards.</p>



<h2 class="wp-block-heading">Let&#8217;s talk about mistakes without blame</h2>



<p class="wp-block-paragraph">Another common misunderstanding is that psychological safety means a comfort zone where everyone is nice and nobody gets challenged, but that’s just low standards.</p>



<p class="wp-block-paragraph"><strong>We can challenge each other and still expect excellent work</strong>.</p>



<p class="wp-block-paragraph">Psychological safety also makes it easier to talk about mistakes without blame. And every hard conversation teaches people how costly honesty feels here &#8211; whether it’s saying, &#8220;I made a mistake,&#8221; &#8220;I think you’re wrong,&#8221; &#8220;I have bad news,&#8221; or &#8220;I don’t know.&#8221;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://shiftmag.dev/wp-content/uploads/2026/10/image-20260926-202807-1024x683.png?x32039" alt="" class="wp-image-12428" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/image-20260926-202807-1024x683.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/image-20260926-202807-300x200.png 300w, https://shiftmag.dev/wp-content/uploads/2026/10/image-20260926-202807-768x512.png 768w, https://shiftmag.dev/wp-content/uploads/2026/10/image-20260926-202807.png 1536w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">&#8220;I made a mistake.&#8221;</h2>



<p class="wp-block-paragraph">Imagine an engineer saying, &#8220;I pushed the wrong config. This incident is on me.&#8221;</p>



<p class="wp-block-paragraph">A very natural response, especially when production is down, is: &#8220;How did you let this happen?&#8221;</p>



<p class="wp-block-paragraph">Maybe the person saying it is not trying to blame anyone. They are stressed, customers are affected, and everyone wants to know what happened. But the effect can still be the same: <strong>next time, make sure you have a defense before admitting the mistake</strong>.</p>



<p class="wp-block-paragraph">A more useful first response could be: &#8220;Thanks for raising it quickly. Let’s stabilize first, then understand what happened, what was in your control, and what we need to change.&#8221;</p>



<p class="wp-block-paragraph"><strong>Psychological safety means safe to report but it doesn&#8217;t mean free from accountability</strong>.</p>



<h2 class="wp-block-heading">&#8220;I think you are wrong.&#8221;</h2>



<p class="wp-block-paragraph">This sentence gets more expensive as the other person gets more senior. <strong>Disagreeing with a peer is one thing; disagreeing with your manager, principal engineer, architect or VP is another</strong>.</p>



<p class="wp-block-paragraph">When raising a concern, separate the decision from the person who made it. Instead of, &#8220;This architecture is wrong,&#8221; try, &#8220;I’m worried about X because of Y. Can we test that assumption?&#8221; For example: &#8220;I’m worried about what happens when traffic doubles because the queue becomes a single bottleneck. Can we test that assumption before we commit?&#8221;</p>



<p class="wp-block-paragraph">The concern is still there, but <strong>the conversation stays on the work, not the person</strong>.</p>



<p class="wp-block-paragraph">The same applies on the receiving side. Instead of, &#8220;We already decided this,&#8221; try, &#8220;What are you seeing that I’m not?&#8221; or &#8220;What evidence would make us reconsider?&#8221;</p>



<p class="wp-block-paragraph"><strong>Challenge assumptions, decisions and behaviour before you challenge identity.</strong></p>



<h2 class="wp-block-heading">&#8220;I have bad news.&#8221;</h2>



<p class="wp-block-paragraph">Psychological safety doesn&#8217;t eliminate bad news, just brings it earlier, while it is still a risk rather than an incident.</p>



<p class="wp-block-paragraph"><strong>The earlier we talk about it, the more options we usually have</strong>. But engineers often want to bring a solution with the problem, so they wait, investigate a little longer, and try one more thing.</p>



<p class="wp-block-paragraph">Sometimes the most professional thing you can say is: &#8220;We may miss the deadline. I don’t have the solution yet, but you should know now.&#8221;</p>



<p class="wp-block-paragraph">And the response matters too: &#8220;I would rather know today than next Friday. What changed? What options do we have?&#8221;</p>



<p class="wp-block-paragraph"><strong>If you punish early bad news, you do not get better news &#8211; you get later news</strong>.</p>



<h2 class="wp-block-heading">&#8220;I don’t know.&#8221;</h2>



<p class="wp-block-paragraph">The fourth sentence is quieter. <strong>&#8220;I don’t know&#8221; gets harder to say as your title gets longer</strong>.</p>



<p class="wp-block-paragraph">In engineering, pretending to understand can look professional for about five minutes and then it becomes risk. Because of that you need to <strong>ask the &#8220;stupid&#8221; question before uncertainty becomes hidden risk</strong>.</p>



<p class="wp-block-paragraph">For senior people, model fallibility. When someone senior says they are unsure, they show that not knowing is okay and that asking questions does not reduce your status. That can be as simple as saying, &#8220;I’m not sure either,&#8221; or &#8220;What assumption are we making here?&#8221; or  &#8220;Can someone explain this from first principles?&#8221;</p>



<p class="wp-block-paragraph"><strong>When someone senior says that, it becomes easier for everyone else to stop pretending and start asking</strong>.</p>



<h2 class="wp-block-heading"><span id="the-first-10-seconds-matter">The first 10 seconds matter</span></h2>



<p class="wp-block-paragraph">Most leaders don&#8217;t destroy psychological safety through dramatic intimidation, and most teams do not become silent because of one movie-villain manager. Usually, it is smaller than that: an eye roll or interrupting someone with &#8220;No, because&#8230;&#8221;</p>



<p class="wp-block-paragraph">The hard part is that your intention is private, but your reaction is observable. You may mean to move the discussion forward quickly and the other person may hear: do not bring this up again.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="768" src="https://shiftmag.dev/wp-content/uploads/2026/10/10-seconds-graphic-1024x768.webp?x32039" alt="" class="wp-image-12520" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/10-seconds-graphic-1024x768.webp 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/10-seconds-graphic-300x225.webp 300w, https://shiftmag.dev/wp-content/uploads/2026/10/10-seconds-graphic-768x576.webp 768w, https://shiftmag.dev/wp-content/uploads/2026/10/10-seconds-graphic.webp 1448w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">So the first few seconds matter. When someone challenges your decision, brings bad news, or points out a risk, your instinct may be to explain, defend, or correct. That is human but <strong>you do not have to act on it right away</strong>.</p>



<p class="wp-block-paragraph">Instead of asking, &#8220;How do I defend my position?&#8221;, ask, &#8220;What might they be seeing that I’m not?&#8221;</p>



<p class="wp-block-paragraph">Sometimes the simplest thing is: &#8220;Tell me more.&#8221; You are not agreeing with the person, just trying to understand what they are actually seeing. You can also ask, &#8220;What makes you concerned?&#8221; or &#8220;What would happen if we are wrong?&#8221;</p>



<p class="wp-block-paragraph"><strong>The goal is to show curiosity</strong>. If they can see you are trying to understand before judging, the next uncomfortable conversation gets a little easier.</p>



<h2 class="wp-block-heading"><span id="what-if-you-are-not-the-leader">What if you are not the leader?</span></h2>



<p class="wp-block-paragraph">There is a danger in talking about communication skills in this context because it can sound like the answer to a bad culture is simply: employees need to learn how to speak better.</p>



<p class="wp-block-paragraph">If you are not the leader, you are not responsible for fixing the whole culture yourself. Communication skills help, but they can&#8217;t make up for an environment where speaking honestly repeatedly comes at a cost. What you can often do is <strong>make your signal easier to hear</strong>.</p>



<p class="wp-block-paragraph">Instead of, &#8220;This architecture is bad,&#8221; say, &#8220;I’m concerned about X because Y. The consequence could be Z.&#8221;</p>



<p class="wp-block-paragraph">You can also calibrate your certainty: &#8220;I may be wrong, but…&#8221; &#8220;I’m about 60% sure that…&#8221; &#8220;I’ve seen this fail before, although the context was slightly different.&#8221;</p>



<p class="wp-block-paragraph"><strong>Uncertainty and assertiveness are not opposites</strong>.</p>



<p class="wp-block-paragraph">Good communication can improve a difficult conversation but it cannot fix a pattern where honesty is repeatedly met with defensiveness or dismissal. That is why it matters to read the pattern, not just one reaction. One defensive response can be a bad moment but repeatedly making candor expensive is a signal about the environment.</p>



<h2 class="wp-block-heading"><span id="back-to-thursday">Back to Thursday</span></h2>



<p class="wp-block-paragraph">Now go back to the database migration. It is the same team, the same deadline, and the same engineer with the same concern.</p>



<p class="wp-block-paragraph">Engineer: &#8220;I’m not convinced this migration is safe.&#8221;</p>



<p class="wp-block-paragraph">Manager: &#8220;Okay. What are you seeing? How confident are you?&#8221;</p>



<p class="wp-block-paragraph">Engineer: &#8220;Maybe 60%.&#8221;</p>



<p class="wp-block-paragraph">That conversation doesn’t magically produce the right technical decision but that’s not the point. Psychological safety doesn&#8217;t guarantee the right decision but <strong>it gives the team access to more of the information that already exists, and that changes how they handle uncertainty</strong>.</p>



<p class="wp-block-paragraph">You still have hard conversations, and you still make wrong decisions. The difference is that you catch them early enough to respond.</p>



<h2 class="wp-block-heading"><span id="polite-open-assertive">Polite. Open. Assertive.</span></h2>



<p class="wp-block-paragraph">I like a simple communication profile for these conversations: POA &#8211; Polite, Open, Assertive.</p>



<p class="wp-block-paragraph">Polite means respecting the person. Open means staying curious. Assertive means saying the real thing clearly.</p>



<p class="wp-block-paragraph"><strong>Together, they give you respect, curiosity, and clarity</strong>. Polite keeps candor from becoming cruelty. Open keeps it from becoming ego. Assertive keeps it from becoming vague.</p>



<p class="wp-block-paragraph">It doesn&#8217;t create psychological safety by itself, but it gives both sides of a difficult conversation something practical to work with.</p>



<p class="wp-block-paragraph"><strong>Your engineers already see problems, the question is whether you get to hear about them.</strong></p>



<p class="wp-block-paragraph">Psychological safety makes it easier to raise uncomfortable truths while there is still something you can do about them.</p>



<p class="wp-block-paragraph">Make honesty less risky than silence.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://shiftmag.dev/make-honesty-less-risky-than-silence-for-your-engineering-team-12382/">Make Honesty Less Risky Than Silence for Your Engineering Team</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How We Catch Messaging Campaign Drift Before It Spreads</title>
		<link>https://shiftmag.dev/how-we-catch-messaging-campaign-drift-before-it-spreads-11136/</link>
		
		<dc:creator><![CDATA[Adna Šestić]]></dc:creator>
		<pubDate>Wed, 07 Oct 2026 13:21:46 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=11136</guid>

					<description><![CDATA[<p>Over time, the content a messaging campaign sends can shift away from what was originally approved. We call this campaign drift, and in business messaging, it's a real and recurring problem.</p>
<p>The post <a href="https://shiftmag.dev/how-we-catch-messaging-campaign-drift-before-it-spreads-11136/">How We Catch Messaging Campaign Drift Before It Spreads</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/08/ShiftMag-article-banner-1.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/08/ShiftMag-article-banner-1.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/08/ShiftMag-article-banner-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/08/ShiftMag-article-banner-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/08/ShiftMag-article-banner-1-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">When businesses create messaging campaigns on Infobip, <strong>they must go through an approval process</strong>. They share brand details and campaign information, such as the purpose, target age group, and campaign type, which is checked for consistency and compliance with platform safety rules like WhatsApp or Viber terms of use.</p>



<p class="wp-block-paragraph">Once a campaign goes live, it’s our job as developers to ensure the messages being sent continue to reflect what was approved.</p>



<p class="wp-block-paragraph"><strong>There’s a whole spectrum of ways a campaign can drift</strong>, though. Some changes are obvious safety problems, like phishing or illegal content. Others are more subtle, like using the wrong brand voice, adding marketing language to transactional messages, or changing personalized content outside the approved template. The hardest cases are the ones that look compliant at first but still blur the line.</p>



<p class="wp-block-paragraph">&#8230;and that&#8217;s precisely what makes this a tough engineering problem.</p>



<h2 class="wp-block-heading"><span id="keyword-matching-isn%e2%80%99t-enough-to-catch-message-drift">Keyword matching isn’t enough to catch message drift</span></h2>



<p class="wp-block-paragraph"><strong>Legitimate traffic and drifting traffic can look very similar</strong>, even when they mean different things. Rule-based systems and keyword matching can’t always tell the difference. Detecting drift requires understanding meaning, context, and who is sending the message.</p>



<p class="wp-block-paragraph">If that&#8217;s a little hard to picture in the abstract, here&#8217;s an example. It&#8217;s rarely this overt in practice, but it makes the shape of the problem obvious.</p>



<p class="wp-block-paragraph">Imagine you&#8217;re a long-time client of an eye clinic. Every year, like clockwork, you receive the same familiar birthday message from the same phone number:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Hello Sam, this is Clermont Family Eyecare, we want to wish you a happy birthday! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60e.png" alt="😎" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f389.png" alt="🎉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
</blockquote>



<p class="wp-block-paragraph">Generic, but consistent &#8211; a small customer-care touch from a business you trust.</p>



<p class="wp-block-paragraph">This year, the message arrives slightly altered, from that same number:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Hello Sammy, this is For Your Eyes Only Eye Care, we want to wish you a very happy birthday!</p>
</blockquote>



<p class="wp-block-paragraph">The tone is friendly and the structure looks the same. But the brand name has changed, and the link is new. You tap it, and suddenly you’re on a page with explicit content, not eyecare. <strong>In one click, trust is broken</strong> &#8211; even though the message came from the same number and passed every superficial check.</p>



<p class="wp-block-paragraph">On average, this system, when completed, is meant to process just short of 300 million SMS and RCS messages daily (crazy, right?). So, the engineering question becomes: how do you detect drift semantically, in production, at that scale, without reasoning about every message individually? Let me walk you through how we got to an answer.</p>



<h2 class="wp-block-heading"><span id="the-system-needs-to-be-designed-from-first-principles">The system needs to be designed from first principles</span></h2>



<p class="wp-block-paragraph">A few observations about the traffic led to the architecture.</p>



<p class="wp-block-paragraph">The first is the most obvious: <strong>messaging campaigns are repetitive by nature</strong>. Messages are templated, sometimes identical within a campaign. At our scale, this immediately points toward grouping messages and reasoning about drift at the group level rather than per message.</p>



<p class="wp-block-paragraph">There’s an important operational detail here you should know: when businesses create messaging campaigns on our platform, they go through an approval process. They provide brand information and campaign metadata like intent, recipient age or campaign type categorization, which is reviewed for internal consistency and against platform safety guidelines (think WhatsApp or Viber Terms of Use). Once a campaign goes live, it’s our job to ensure the messages being sent continue to reflect what was approved.</p>



<p class="wp-block-paragraph">You can see that the problem isn’t really about tracking a semantic distribution of campaign messages and watching it shift over time, even though the word drift might suggest that. Historical traffic isn’t what defines drift here. The problem is closer to <strong>continuous content validation</strong>: preserving the intent stated in the original campaign metadata and looking for new patterns that warrant separate interpretation and potential action.</p>



<p class="wp-block-paragraph">Even though this framing focuses on novel data,<strong> historical traffic still matters</strong>. If incoming messages reliably match traffic that has already been evaluated, we can decide in real time whether they’re legitimate or drifting. Messages that match approved intent should be handled immediately, and only unexplained content needs to be isolated for further analysis.</p>



<p class="wp-block-paragraph">A message entering our system takes one of two paths:</p>



<ul class="wp-block-list">
<li>A real-time <strong>classification path</strong>, which assigns it to a previously observed group with a known verdict, or</li>



<li>A deferred <strong>discovery path</strong>, where it’s held aside to help form a new group.</li>
</ul>



<p class="wp-block-paragraph">And there you have it: the gist of the design. The rest of the post is about how we turn that into a production system.</p>



<h2 class="wp-block-heading"><span id="the-architecture">The architecture</span></h2>



<p class="wp-block-paragraph">In practice, this is a multi-stage microservice pipeline. A message flows through it as follows:</p>



<ol class="wp-block-list">
<li><strong>Ingestion and reassembly</strong>.<strong> </strong>The orchestrator service ingests incoming traffic and reassembles multi-part messages into their original textual form.</li>



<li><strong>Vectorization</strong>. To compare messages by intent rather than wording, we map them into a shared semantic space. A dedicated vectorization service takes a batch of messages and returns their embedding vectors. Messages expressing similar intent end up close together in this space, even when the wording differs. That way, grouping by proximity in the embedding space gives us grouping by semantics.</li>



<li><strong>Search</strong>.<strong> </strong>The orchestrator queries an Elasticsearch index of known cluster representatives using the message’s embedding. If a match is found, the message is assigned to that cluster, and the cluster signature is promoted to a local cache, so subsequent traffic from the same sender resolves faster. This is the classification path in action.</li>



<li><strong>Noise accumulation</strong>.<strong> </strong>If no match is found, the message takes the discovery path: it’s written to a <em>noise</em> index. The name comes from clustering terminology: technically, it’s an “unclassified” index, holding candidate data for future clusters.</li>



<li><strong>Clustering</strong>.<strong> </strong>A scheduled job continuously pulls accumulated noise and runs clustering to discover new semantic groups. Clustering is performed on sender level. In practice, we’ve observed that for a sender, message volume is a great primary signal for parameter configuration, and after an obscene amount of per-sender experiments, we did manage to settle on a base of volume-keyed parameter sets. Although not as ubiquitously successful as maybe a best-of-n configs approach would have been, at our scale the compute savings make it the right call.</li>



<li><strong>LLM-as-a-judge</strong>.<strong> </strong>Finally, cluster representatives are relayed to an LLM, which produces a verdict for the <em>cluster</em>, not for individual messages. The model also outputs per-message reasoning, which is what makes the verdict actionable downstream.</li>
</ol>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="614" src="https://shiftmag.dev/wp-content/uploads/2026/10/clustering_3200x1920-1024x614-1.jpg?x32039" alt="" class="wp-image-12434" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/clustering_3200x1920-1024x614-1.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/clustering_3200x1920-767x460.jpg 767w, https://shiftmag.dev/wp-content/uploads/2026/10/clustering_3200x1920-300x180.jpg 300w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="walking-the-eyecare-message-through-the-pipeline">Walking the eyecare message through the pipeline</span></h2>



<p class="wp-block-paragraph">Let’s replay the message path from the start with this architecture in mind.</p>



<p class="wp-block-paragraph"><strong>The message arrives at ingestion</strong> alongside other traffic from the same eyecare clinic sender. The orchestrator reassembles it and the vectorization service returns its embedding. The orchestrator queries Elasticsearch for known clusters associated with this sender, and let’s imagine that there are several: the standard birthday message, an annual check-up reminder, a glasses-ready-for-pickup notification.</p>



<p class="wp-block-paragraph">The incoming embedding sits near the birthday cluster, but not near enough to match. The brand name swap and the shift from “Sam” to “Sammy” are subtle on paper, but they move the vector just far enough away.</p>



<p class="wp-block-paragraph">No match. The message goes to the noise index.</p>



<p class="wp-block-paragraph">Over the next clustering interval, <strong>more messages like it accumulate</strong> (you can be pretty sure they would, this reads like a classic sender takeover). The clustering job runs, a new cluster forms around them, and a handful of representatives are stored and passed to the LLM judge.</p>



<p class="wp-block-paragraph">The judge compares the cluster against the sender’s approved campaign metadata and <strong>flags it for brand impersonation</strong>. (The changed recipient personalization remains unflagged: on its own, it&#8217;s a minor surface variation that doesn&#8217;t shift the underlying intent.) Reasoning is attached. A human reviewer picks it up, and the sender is paused before the next batch of spam goes out.</p>



<p class="wp-block-paragraph">The message arrived through the same number, used the same structure, and would have passed any rule-based check. The only reason the system caught it was because the meaning had shifted.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="614" src="https://shiftmag.dev/wp-content/uploads/2026/10/message_path_3200x1920-1024x614.jpg?x32039" alt="" class="wp-image-12435" srcset="https://shiftmag.dev/wp-content/uploads/2026/10/message_path_3200x1920-1024x614.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/10/message_path_3200x1920-300x180.jpg 300w, https://shiftmag.dev/wp-content/uploads/2026/10/message_path_3200x1920-767x460.jpg 767w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="clustering-is-the-leverage-point">Clustering is the leverage point</span></h2>



<p class="wp-block-paragraph">At 300 million messages a day, per-message <strong>LLM inference is a non-starter on cost and latency alone</strong>. It would also be wasteful, because most incoming traffic is heavily templated or duplicated. Grouping by intent first means we make one judgment instead of a million.</p>



<p class="wp-block-paragraph">Embeddings group messages together, the cluster amortizes the cost of judging them, and the LLM is reserved for the moment judgment is actually necessary: when something new appears.</p>



<p class="wp-block-paragraph">Two (in my opinion) interesting<strong> design decisions</strong> follow from this:</p>



<ul class="wp-block-list">
<li>First, <strong>we deliberately don&#8217;t let clusters evolve</strong>. A cluster represents a stable behavior snapshot, a fixed meaning at a point in time. Letting clusters expand would let them quietly absorb new variations in intent and language, which is exactly what we&#8217;re trying to detect. Keeping them fixed forces any notable change in semantics to surface as a new cluster, and makes downstream judgment more coherent because the examples within a cluster genuinely belong together.</li>



<li>Second, <strong>this tightening of group intent allows us to represent each cluster by a few select examples rather than its full membership</strong>. This keeps the classification index lean for fast matching, and it gives the next stage, cluster judgment, a focused, reviewable input.</li>
</ul>



<h2 class="wp-block-heading"><span id="tradeoffs-we-accepted">Tradeoffs we accepted</span></h2>



<p class="wp-block-paragraph">As no architecture is without its flaws, the most interesting one is <strong>overclustering</strong>. </p>



<p class="wp-block-paragraph">The system inherits the limitations of its embedding model: embeddings capture intent well, but not every kind of shift. We expected greedy cluster expansion, but in practice the embedding space often treats benign surface variation (like a swapped greeting or different recipient name) as meaningfully different. Legitimate traffic from one campaign gets fragmented across many clusters, which inflates downstream cost and dilutes the signal we care about. </p>



<p class="wp-block-paragraph">The lesson is that embeddings alone won’t always get us to clean intent groups.</p>



<p class="wp-block-paragraph">The other two costs are more predictable:</p>



<ul class="wp-block-list">
<li><strong>Discovery latency. </strong>The classification path is real-time, but the discovery path isn&#8217;t: messages that don&#8217;t match an existing cluster sit in the noise index until the next clustering job runs. For genuinely novel drift, this means a delay between first appearance and first judgment. We tune the noise accumulation period to keep this window short for senders above a certain message volume, assuming that low-volume senders will continue to grow with time and graduate to a size above the threshold.</li>



<li><strong>Cluster proliferation from non-evolving clusters.</strong> Forcing semantic shifts to surface as new clusters means a sender with legitimate variation across message templates ends up represented by many clusters. We manage this with cluster aging policies explicitly, but the lean cluster representations also help in that regard, so the memory cost remains bounded.</li>
</ul>



<h2 class="wp-block-heading"><span id="model-provides-a-recommendation-not-a-decision">Model provides a recommendation, not a decision</span></h2>



<p class="wp-block-paragraph">A verdict on a cluster may end the pipeline, but <strong>the case is only closed when a human says it is</strong>.</p>



<p class="wp-block-paragraph">When the LLM judge flags a cluster, the verdict and reasoning go to a human review queue. Reviewers see the cluster representatives, the approved campaign metadata, and the model’s reasoning side by side. They can confirm the verdict, override it, or adjust its severity, and their decision propagates downstream.</p>



<p class="wp-block-paragraph">From there, <strong>action depends on severity</strong>: mild drift leads to client notification and guidance, more serious cases can block specific message types and trigger a root cause analysis, and the most severe, spam-grade drift can block senders entirely.</p>



<p class="wp-block-paragraph">The important thing to note is that the model provides a recommendation, not a decision.</p>



<h2 class="wp-block-heading"><span id="the-scariest-drift-is-the-one-that-still-looks-trusted">The scariest drift is the one that still looks trusted</span></h2>



<p class="wp-block-paragraph">A few things became clearer as we built this out than they were going in:</p>



<ul class="wp-block-list">
<li><strong>The most interesting drift is quiet</strong>: a message that looks familiar, comes from the same number, but means something slightly different and slowly erodes trust before anyone notices.</li>



<li><strong>Judging clusters instead of individual messages changes the question</strong>. <em>Is this message okay? </em>is narrow and easy to answer wrong. <em>What is this sender doing now?</em> is the question that matters, and a group of similar intent is the right unit to ask it about.</li>
</ul>



<p class="wp-block-paragraph">What’s immediately next is concrete, on two fronts.</p>



<ol class="wp-block-list">
<li>The first is <strong>resolving the overclustering issue</strong> described earlier: collapsing benign surface variation back into single clusters so the LLM judge isn&#8217;t doing redundant work.&nbsp; Lightweight named entity recognition and a smidge of the old regex to capture emails or phone numbers should do the trick, we hope.</li>



<li>The second is <strong>scaling</strong>: the system currently runs in a subset of regions and handles on the order of tens of millions of messages a week, and the immediate work is extending that toward the 300-million-a-day ceiling it&#8217;s designed for.</li>
</ol>



<p class="wp-block-paragraph">The eyecare message at the start of this post is just a small example of a bigger problem. What we’re really trying to defend is the meaning of a trusted channel.</p>



<p class="wp-block-paragraph">And for now, <strong>please don’t click weird links in your text</strong>s. Sam learned the hard way, and we’re not quite there yet on link-checking.</p>
<p>The post <a href="https://shiftmag.dev/how-we-catch-messaging-campaign-drift-before-it-spreads-11136/">How We Catch Messaging Campaign Drift Before It Spreads</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>QA Is What Happens When Software Meets Reality</title>
		<link>https://shiftmag.dev/qa-is-what-happens-when-software-meets-reality-11744/</link>
		
		<dc:creator><![CDATA[Aldijana Culezovic]]></dc:creator>
		<pubDate>Tue, 06 Oct 2026 10:25:12 +0000</pubDate>
				<category><![CDATA[Quality Assurance]]></category>
		<category><![CDATA[QA]]></category>
		<category><![CDATA[software testing]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=11744</guid>

					<description><![CDATA[<p>Developers can prove the code works in a controlled environment. QA checks whether it survives the messy, unpredictable world customers actually live in.</p>
<p>The post <a href="https://shiftmag.dev/qa-is-what-happens-when-software-meets-reality-11744/">QA Is What Happens When Software Meets Reality</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/09/developer-vs.-QA.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/09/developer-vs.-QA.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/09/developer-vs.-QA-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/09/developer-vs.-QA-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/09/developer-vs.-QA-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">The developer already tested it, so why do you need to test it too?</p>
</blockquote>



<p class="wp-block-paragraph">If you work in tech, <strong>you’ve probably heard this sentence a thousand times</strong>.</p>



<p class="wp-block-paragraph">A developer writes the code, runs the checks, all the tests pass, and the feature works.</p>



<p class="wp-block-paragraph">So why do companies still hire Quality Assurance (QA) engineers? Are we just here to double-check developers’ work, or is there a deeper purpose?</p>



<p class="wp-block-paragraph">The short answer is: no.</p>



<p class="wp-block-paragraph">The longer answer is that <strong>there’s a fundamental difference between writing code and creating a great customer experience</strong>. The value of QA lies in perspective, risk awareness, and understanding how people actually use a product.</p>



<h2 class="wp-block-heading"><span id="the-builder">The builder</span></h2>



<p class="wp-block-paragraph">To build a truly great product, you need <strong>two very different mindsets</strong>: the builder and the chaos maker.</p>



<p class="wp-block-paragraph">A developer’s brain is wired for creation, logic, and structure. While QA starts the day with a finished product, a developer starts with a blank screen. Their job is to create something out of nothing and assemble the many moving parts of a complex system into something that works exactly as intended.</p>



<p class="wp-block-paragraph"><strong>Developers are responsible for creating the magic</strong>. To build even a single feature, they have to master a labyrinth of tools, frameworks, databases, and configurations. They carry the responsibility of making sure the architecture is secure, the system can handle heavy load, and the new code integrates cleanly with millions of lines of existing logic. Their work is highly complex and demands deep understanding, precision, and sustained focus. They are the architects of the digital world.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Because their primary mission is building and stabilizing the system, their testing mindset naturally reflects that. When developers test their code, they are checking whether their blueprint holds up. They focus on the happy path, along with a few common scenarios, in a controlled environment, using standard data to confirm that the core functionality works as intended. Their attention is on making sure the foundation is solid.</p>
</blockquote>



<p class="wp-block-paragraph">Think of a developer as an architect and engineer combined. They design a beautiful, highly complex door, check that the handle turns smoothly, inspect the hinges, and confirm that it opens perfectly.</p>



<p class="wp-block-paragraph"><strong>Now what? Aren’t developers already responsible for the whole thing?</strong></p>



<h2 class="wp-block-heading"><span id="the-chaos-maker">The chaos maker</span></h2>



<p class="wp-block-paragraph">While developers are incredibly skilled at what they do, they cannot be expected to carry the entire burden of the user experience alone. That is where QA steps in &#8211; to relieve some of that pressure and help refine the product for the real world.</p>



<p class="wp-block-paragraph">If a developer’s brain is wired for creation, a <strong>QA’s brain is wired for exploration and chaos</strong>. The goal is not to prove that the software works, but to discover what happens when the scenario is not perfect. We test unusual cases, unpredictable behavior, and the edge cases that real users may actually trigger. We test for the messy real world.</p>



<p class="wp-block-paragraph">Because of this, QA goes far beyond engineering. The work calls for empathy, human psychology, and an eye for the emotional, reliability, and invisible factors that make customers want to use a product.</p>



<p class="wp-block-paragraph">As a QA, <strong>I’m constantly stepping into the user’s shoes</strong> and asking myself a very different set of questions:</p>



<ul class="wp-block-list">
<li>Is this accessible and intuitive to use?</li>



<li>What emotion does this product create for me &#8211; frustration or delight?</li>



<li>Would I still enjoy using it tomorrow, or would it already be starting to annoy me?</li>
</ul>



<h2 class="wp-block-heading"><span id="what-happens-in-the-real-world">What happens in the real world</span></h2>



<p class="wp-block-paragraph">To make this point come to life, let me share a personal experience. </p>



<p class="wp-block-paragraph">I’ve seen that <strong>even a large team of skilled developers means every single scenario is not automatically covered</strong>. Tight deadlines, heavy workloads, and the sheer mental focus required to build complex architecture make it nearly impossible for any single perspective to catch everything. Once a feature is done with implementation, it’s QA’s turn to step in, look beyond the happy path, and hunt down every possible edge case.</p>



<h3 class="wp-block-heading">The &#8220;blank space&#8221; API trap</h3>



<p class="wp-block-paragraph">For instance, when new feature was implemented, it was time to test it. My team and I ran automated tests for our Voice APIs.</p>



<p class="wp-block-paragraph">During testing, <strong>I decided to try something slightly unusual</strong>: I sent a call using a sender name that contained a space. Immediately, the calls started failing. This turned out to be a critical issue. If a real client wanted to do something as simple and common as putting a space in their sender name (e.g., &#8220;Global Bank&#8221; instead of &#8220;GlobalBank&#8221;), their entire voice campaign would fail. We only discovered this flaw because we had an automated QA project specifically designed to stress-test the exact parameters our clients use daily, which even shows the importance of regression tests and their benefits before the release.</p>



<h3 class="wp-block-heading"><span id="the-edge-case-that-shouldn%e2%80%99t-break-the-system">The edge case that shouldn’t break the system</span></h3>



<p class="wp-block-paragraph">Another instance happened while I was testing the delivery reports for our system. The documentation stated that the record limit field was limited to 1 to 1000. My QA brain asked, &#8220;What happens if a user accidentally types 0?&#8221; <strong>When I entered 0, the system crashed and returned a 500 Internal Server Error</strong>. </p>



<p class="wp-block-paragraph">Technically, it was just a wrong number. But from a customer experience standpoint, this is a big deal. A 500 error tells the client, &#8220;Your servers are broken,&#8221; which causes panic, especially during real-time actions. It should have gracefully returned a 400 Bad Request, which politely tells the user, &#8220;Oops, your input was invalid, please try again.&#8221; </p>



<p class="wp-block-paragraph">Logically, it makes no sense for a user to request 0 records. But it is our duty as QA to make sure that even when a user does something illogical, the system handles it elegantly instead of catching on fire.</p>



<h3 class="wp-block-heading"><span id="the-trapped-user">The trapped user</span></h3>



<p class="wp-block-paragraph">The chaos isn’t always in the backend, either. Recently, while performing manual UI testing, I found a scenario where a user could fill out an entire complex form, only to find that the <strong>&#8220;Save&#8221; button remained permanently disable</strong>d because of a tiny edge-case conflict in the UI logic. Imagine the frustration of spending ten minutes typing out intricate details, only to be trapped at the finish line and unable to save the work. </p>



<p class="wp-block-paragraph">All of these instances prove why additional testing is necessary. It is incredibly easy for crucial edge cases to slip through when a team’s primary focus is building complex core functionality. No one should set a limit to 0. A sender name shouldn’t break an API. But humans aren’t strictly logical, and neither is the real world. That is why QA exists.</p>



<h2 class="wp-block-heading"><span id="qa-and-devs-are-two-halves-of-the-same-brain">QA and devs are two halves of the same brain</span></h2>



<p class="wp-block-paragraph">Ultimately, this story comes back to the same point: success. Despite our different approaches, <strong>both teams are chasing the same finish line</strong>. We come together, we collaborate, and we bring an idea to life in the best possible way.</p>



<p class="wp-block-paragraph">Both developers and QA want the same thing: to deliver a product that is simple, easy to use, unique, and highly functional. We want to build something so reliable and intuitive that the end user does not even have to think about how it works under the hood &#8211; it just does.</p>



<p class="wp-block-paragraph">Because my job involves finding edge cases, logging bugs, and occasionally breaking a developer’s hard work, it is easy for outsiders to assume that developers and QA are at war. But that is far from the truth. <strong>We are not enemies; we are an essential partnership</strong>. We are a continuous feedback loop where logic meets empathy.</p>



<p class="wp-block-paragraph">Just like a human being cannot function with only half a brain, a truly great product cannot survive in the wild with only one mindset. It needs the builder’s solid foundation, and it needs the chaos maker’s reality check.</p>



<p class="wp-block-paragraph"><strong>The developer brain ensures the software is built right. The QA brain ensures we’re building the right software for the customer.</strong> Together we create the product that customers love.</p>



<h2 class="wp-block-heading">Before you go&#8230;</h2>



<p class="wp-block-paragraph">Next time someone asks, &#8220;The developer already tested it, why do you need to test it too?&#8221; you’ll know exactly what to say: </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Code lives on servers, but customer experience lives in the real world, and QA is the bridge between the two.</p>
</blockquote>
<p>The post <a href="https://shiftmag.dev/qa-is-what-happens-when-software-meets-reality-11744/">QA Is What Happens When Software Meets Reality</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>OpenAI&#8217;s Luis Velasco: Code is very cheap to produce, but the system around it isn&#8217;t</title>
		<link>https://shiftmag.dev/openai-fde-code-is-very-cheap-to-produce-12341/</link>
		
		<dc:creator><![CDATA[Anastasija Uspenski]]></dc:creator>
		<pubDate>Fri, 02 Oct 2026 13:20:51 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[Infobip Shift 2026]]></category>
		<category><![CDATA[Luis Velasco]]></category>
		<category><![CDATA[OpenAI]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=12341</guid>

					<description><![CDATA[<p>Luis Velasco works as a Forward Deployed Engineer at OpenAI. For him, code is becoming very cheap to produce, while building the system around the model is becoming critical.</p>
<p>The post <a href="https://shiftmag.dev/openai-fde-code-is-very-cheap-to-produce-12341/">OpenAI&#8217;s Luis Velasco: Code is very cheap to produce, but the system around it isn&#8217;t</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">At the <a href="https://shiftmag.dev/tag/infobip-shift-2026/" target="_blank" rel="noreferrer noopener">Shift conference in Zadar</a> this September, we sat down with <a href="https://shiftmag.dev/openai-says-the-real-work-in-ai-coding-is-building-the-system-around-it-11976/" target="_blank" rel="noreferrer noopener">Luis Velasco, a Forward Deployed Engineer at OpenAI</a>, who describes his role simply:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">We help companies put AI to work in real environments.</p>
</blockquote>



<p class="wp-block-paragraph">We spoke with him about what it takes to move AI agents into production, how developers can make them reliable and secure, and which skills will matter most as AI changes software development.</p>



<h3 class="wp-block-heading"><span id="production-starts-with-evals"><strong>Production starts with evals</strong></span></h3>



<p class="wp-block-paragraph">As Luis hinted in the intro, Forward Deploy Engineers (FDE) help companies turn AI demos into real products. So we asked him what developers most often underestimate when they make that jump.</p>


<figure class="wp-block-post-featured-image"><img loading="lazy" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2026/09/luis.png?x32039" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2026/09/luis.png 1200w, https://shiftmag.dev/wp-content/uploads/2026/09/luis-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2026/09/luis-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2026/09/luis-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">According to him, <strong>the real challenge starts when a demo reaches production</strong>. A demo can work well in controlled conditions, but production forces teams to understand exactly what works, what does not, and why failures happen.</p>



<p class="wp-block-paragraph">That is where eval-driven (Evaluation-driven) development becomes important. He says OpenAI uses it extensively in its engagements to track and measure different workflows and tasks:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">We have a scientific approach to measure the performance of the models doing a task. When, basically, you clear those benchmarks, those evals, you are good to go to production in a really good and safe way.</p>
</blockquote>



<h3 class="wp-block-heading"><span id="the-deployment-gap-is-the-real-challenge"><strong>The deployment gap is the real challenge</strong></span></h3>



<p class="wp-block-paragraph">We wanted to understand what makes an AI agent reliable enough for production, rather than something that only works well in a controlled environment.</p>



<p class="wp-block-paragraph">Luis said<strong> it all comes down to “cracking the evals.”</strong> As he explained, today’s models already have impressive intelligence, but putting them to work in a company’s own environment requires giving them access to the company’s data, procedures, and tools:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">You know, those three things, we kind of call the deployment gap, right? And this is what we&#8217;re trying to close as FD, basically.</p>
</blockquote>



<h3 class="wp-block-heading"><span id="agents-went-from-six-minute-to-16-hour-tasks"><strong>Agents went from six-minute to 16-hour</strong> tasks</span></h3>



<p class="wp-block-paragraph">But what happens when an agent works on a task for hours rather than minutes? How should developers think about errors, memory, context, and human approval as those workflows become longer?</p>



<p class="wp-block-paragraph">Luis answered with an example from his own experience. While checking the latest data from METR’s long time horizon benchmark, he was surprised by how quickly agents had improved. In just over three years, they went from <strong>handling tasks that would take a human around six minutes to tasks that would take around 16 hours.</strong></p>



<p class="wp-block-paragraph">That represents a massive jump, he said:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">On one hand, you have the models getting better at long-term coherency and persistence, but on the other hand, you also have the harnesses improving a lot. Back in the days, a developer needed to care about context management, memory creation, and all of that. Right now, as I say, with harnesses such as Codex, all that is gone.</p>
</blockquote>



<p class="wp-block-paragraph">For Luis, that progress comes from combining more capable models with more powerful harnesses. Together, they allow engineers and developers to run increasingly complex workflows over much longer periods of time.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="683" src="https://shiftmag.dev/wp-content/uploads/2026/09/SHIFT_MAINSTAGE-19-1024x683.jpg?x32039" alt="" class="wp-image-12352" srcset="https://shiftmag.dev/wp-content/uploads/2026/09/SHIFT_MAINSTAGE-19-1024x683.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2026/09/SHIFT_MAINSTAGE-19-300x200.jpg 300w, https://shiftmag.dev/wp-content/uploads/2026/09/SHIFT_MAINSTAGE-19-768x512.jpg 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption class="wp-element-caption">Credit: Filip Popović</figcaption></figure>



<h3 class="wp-block-heading"><span id="agents-should-follow-the-same-access-rules-as-employees"><strong>Agents should follow the same access rules as employees</strong></span></h3>



<p class="wp-block-paragraph">When it comes to security, we wanted to understand the safest way to connect AI agents to company data without creating new permission and access risks.</p>



<p class="wp-block-paragraph">Luis explained it through a familiar workplace example. When a company onboards someone who works in finance, it gives that person access to financial data, but not to HR data they do not need.</p>



<p class="wp-block-paragraph">He argues that companies can apply the same principle to AI agents, using the same access controls and permission rules they already use for employees:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">In the same way that when you onboard an employee into your company, and let&#8217;s say he or she is working in finance, you only give access to the finance data. You don&#8217;t give access to the HR data, right? So, in the same way, those same principles, those same ACLs, can also apply to AI agents, right?</p>
</blockquote>



<p class="wp-block-paragraph">For him, the principle comes down to giving agents access only to what they require to perform their tasks:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">So, in my view, it&#8217;s about having the roles, the permissions, and the setup for the agents to only see what they need to see for completing their workflow, basically.</p>
</blockquote>



<h3 class="wp-block-heading"><span id="evals-are-fundamental-to-ai-development"><strong>Evals are fundamental to AI development</strong></span></h3>



<p class="wp-block-paragraph">Finally, we asked Luis what developers should test and measure before releasing an AI agent to real users.</p>



<p class="wp-block-paragraph">Once again, he came back to evals. He said he keeps returning to the concept because it remains critical and fundamental to AI development:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">I think we go back to evals once again, right? And I keep coming back to that concept because it&#8217;s absolutely critical and fundamental for AI development, right? If you&#8217;re able to put together that representative eval set containing easy cases, medium cases, and also edge cases, and you&#8217;re able to highly lean on your skills, on your guardrails, on the prompts you send to the model, that will give you the guarantees that when you deploy to production, nothing will break.</p>
</blockquote>



<p class="wp-block-paragraph">He added that evals also give developers a way to test for regressions when they upgrade to a new model and make sure the change does not break existing workflows:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Furthermore, when you upgrade your model to a new one, you have a way to test regressions and make sure that that upgrade won&#8217;t break anything.</p>
</blockquote>



<h3 class="wp-block-heading"><span id="system-design-taste-will-never-go-away"><strong>System design taste will never go away</strong></span></h3>



<p class="wp-block-paragraph">Before joining OpenAI, Luis also worked at Google, so over the years he has seen plenty of developers, roles, and career dilemmas up close. That is why, to close the interview, we asked him which skills developers should focus on today to stay relevant in the age of AI agents.</p>



<p class="wp-block-paragraph">He believes that, in this new era, engineers will no longer create code as their primary output, because <strong>code has become very cheap to produce</strong>.</p>



<p class="wp-block-paragraph">Instead, he sees much more value in everything developers build around the model:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">I think now, in this new era we&#8217;re entering, the primary thing that engineers are creating is not code anymore. Code is very cheap to produce. It&#8217;s all about building the system around it, so the system of intent, the guardrails, the constraints for the agent to work reliably, right? So I think creating those harnesses around the model will be absolutely critical.</p>
</blockquote>



<p class="wp-block-paragraph">Luis ended our interview with a simple but sharp statement:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Plus, I always say, like, system design taste will never go away.</p>
</blockquote>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Open AI on Why AI Demos Break in Production" width="500" height="281" src="https://www.youtube.com/embed/wCiFGPgtQvw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>
<p>The post <a href="https://shiftmag.dev/openai-fde-code-is-very-cheap-to-produce-12341/">OpenAI&#8217;s Luis Velasco: Code is very cheap to produce, but the system around it isn&#8217;t</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: shiftmag.dev @ 2026-10-18 10:34:19 by W3 Total Cache
-->