<?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>Backend Archives - ShiftMag</title>
	<atom:link href="https://shiftmag.dev/category/backend/feed/" rel="self" type="application/rss+xml" />
	<link>https://shiftmag.dev/category/backend/</link>
	<description>Insightful engineering content &#38; community</description>
	<lastBuildDate>Mon, 03 Nov 2025 11:14:23 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://shiftmag.dev/wp-content/uploads/2024/08/cropped-ShiftMag-favicon-32x32.png</url>
	<title>Backend Archives - ShiftMag</title>
	<link>https://shiftmag.dev/category/backend/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Debugging in the Age of AI Isn’t About Fixing Broken Code</title>
		<link>https://shiftmag.dev/debugging-ai-era-6681/</link>
		
		<dc:creator><![CDATA[Marko Crnjanski]]></dc:creator>
		<pubDate>Mon, 03 Nov 2025 10:59:09 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[Developer Productivity]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=6681</guid>

					<description><![CDATA[<p>It’s no longer about fixing syntax errors - it’s about figuring out why a billion-parameter model did something totally unexpected.</p>
<p>The post <a href="https://shiftmag.dev/debugging-ai-era-6681/">Debugging in the Age of AI Isn’t About Fixing Broken Code</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Developers are facing a whole new breed of bugs and these aren’t syntax errors you can catch with a linter. We’re talking <strong>unpredictable model outputs</strong>, <strong>data drift</strong>, or <strong>hidden biases in training sets</strong>. </p>



<p class="wp-block-paragraph">When your &#8220;code&#8221; is a neural network with billions of parameters, traditional debugging tools barely scratch the surface. </p>



<p class="wp-block-paragraph">So, the real challenge has shifted from fixing deterministic code to <strong>making sense of probabilistic behavior</strong>. </p>



<p class="wp-block-paragraph">To explore this, we spoke with <strong>Zvonimir Petkovic</strong>, Senior Software Engineer at Infobip.</p>



<h2 class="wp-block-heading">AI-assisted debugging &#8211; helping hands or crutches?</h2>



<p class="wp-block-paragraph">When asked how AI is reshaping debugging, and whether it’s making developers sharper or just more reliant on automation, Zvonimir says it all comes down to mindset: it depends on <strong>whether a developer has truly embraced AI coding in a &#8220;vibe&#8221; way or not</strong>.</p>



<p class="wp-block-paragraph">Regardless, AI tools often make debugging easier &#8211; even if you never tell Cursor to &#8220;pls fix this.&#8221;</p>



<p class="wp-block-paragraph">But when AI is doing more of the heavy lifting in debugging, what happens to a developer’s critical thinking? Here’s how Petkovic sees it:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">It comes down to mindset: for most people, the process offers a <strong>learning opportunity</strong>, but whether they actually benefit depends on having the time and will to dig in &#8211; or whether the project’s pace leaves no room for deeper exploration.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="why-ai-struggles-with-legacy-code">Why AI struggles with legacy code</span></h2>



<p class="wp-block-paragraph">When asked about <strong>the biggest challenges of using AI for debugging</strong> &#8211; particularly around accuracy and understanding context &#8211; Zvonimir points to one major issue: legacy projects. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Greenfield projects are easy, but try debugging a years-old, messy, poorly documented codebase, and it quickly turns into a nightmare.</p>
</blockquote>



<p class="wp-block-paragraph">Petkovic also noted that AI models have limits when it comes to context &#8211; they can’t always understand everything at once. That’s why <a href="https://shiftmag.dev/you-already-know-context-engineering-even-if-you-dont-know-the-name-5619/" target="_blank" rel="noreferrer noopener">context engineering</a> is more crucial than ever.</p>



<p class="wp-block-paragraph">We also asked Zvonimir how junior developers fare with AI-assisted debugging compared to senior engineers &#8211; does it speed up their learning, or risk slowing down their skill development? He explained:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">GenAI has proven a major boost for juniors or developers transitioning to a new stack. In most cases, it helps them learn faster, without having to call a senior every time they hit a problem.</p>
</blockquote>



<h2 class="wp-block-heading"><span id="the-dark-side-of-ai-autonomy-bugs-and-tech-debt">The dark side of AI autonomy? Bugs and tech debt</span></h2>



<p class="wp-block-paragraph">Debugging isn’t just about fixing bugs. It’s also about <strong>keeping code secure and products reliable</strong>. Zvonimir pointed out the risks of leaning too heavily on AI to automatically fix problems.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">AI-generated code can quickly become a mess and a major source of technical debt if left unchecked and the same goes for automated bug fixes, especially when you push AI autonomy beyond what’s safe today.</p>
</blockquote>



<p class="wp-block-paragraph">He also warned about the risks of a Git-connected AI agent that <strong>automatically merges PRs</strong> and performs code reviews without a human in the loop. Today’s models are much more capable, but still far from fully autonomous.</p>



<h2 class="wp-block-heading">GenAI coding assistants won&#8217;t replace your principal engineers</h2>



<p class="wp-block-paragraph">Finally, Petkovic shared his thoughts on whether AI can really grasp the intent behind code well enough to spot deeper logic or architectural bugs:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">With enough context (code and docs) GenAI assistants won’t replace your principal engineers, but they can help them see problems from new angles and iterate faster.</p>
</blockquote>



<p class="wp-block-paragraph">Looking ahead, one big question is the balance between human and AI-driven debugging: could we ever reach a point where the process is fully automated?</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">It’s heading in that direction. GitHub is rolling out more AI-driven debuggers that not only triage problems based on code and comments but also attempt to propose solutions.</p>
</blockquote>



<p class="wp-block-paragraph">&#8220;With GenAI models becoming better and better, and with context improving with different sources <a href="https://shiftmag.dev/how-infobips-mcp-enables-true-agentic-ai-5220/" target="_blank" rel="noreferrer noopener">expandable by the MCP</a>, I see these becoming just better over time. Still, it’s hard to say how quickly they will be totally independent, even though some major companies are allowing this sort of action in isolated projects,&#8221; Zvonimir concluded.</p>


<figure class="wp-block-post-featured-image"><img fetchpriority="high" decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2025/10/debugging_1_.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2025/10/debugging_1_.png 1200w, https://shiftmag.dev/wp-content/uploads/2025/10/debugging_1_-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2025/10/debugging_1_-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2025/10/debugging_1_-768x403.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure><p>The post <a href="https://shiftmag.dev/debugging-ai-era-6681/">Debugging in the Age of AI Isn’t About Fixing Broken Code</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Can Anyone See This Password? Probably Yes &#8211; Unless You Encrypt It</title>
		<link>https://shiftmag.dev/can-anyone-see-this-probably-yes-unless-you-encrypt-it-5028/</link>
		
		<dc:creator><![CDATA[Marko Crnjanski]]></dc:creator>
		<pubDate>Wed, 20 Aug 2025 14:03:54 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[heapcon 2024]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=5028</guid>

					<description><![CDATA[<p>Every time a password is typed or a message is sent, the internet asks: ‘Can anyone else see this?’ - and without proper encryption, the answer is usually yes.</p>
<p>The post <a href="https://shiftmag.dev/can-anyone-see-this-probably-yes-unless-you-encrypt-it-5028/">Can Anyone See This Password? Probably Yes &#8211; Unless You Encrypt It</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">The internet runs on trust, and <strong>encryption is what makes that trust possible</strong>. Every time a password is typed, a message is sent, or a payment is processed, there’s a silent question in the background: <em>Can anyone else see this?</em></p>



<p class="wp-block-paragraph">Without proper cryptography, the answer is often yes. </p>



<p class="wp-block-paragraph">It doesn’t take much for attackers &#8211; an exposed API, a weak hash, or sloppy design can open the door to stolen data, cracked passwords, or injected queries. The risks are real, and the cost of neglect is steep.</p>



<p class="wp-block-paragraph">That’s why cryptography isn’t a bonus feature. In this article, we’ll dive into the <strong>different kinds of encryption</strong> you’ll encounter, and walk through how to weave these techniques into your Node.js applications in practical, secure ways &#8211; together with <a href="https://www.linkedin.com/in/yonatan-mevorach-20808812a/?originalSubdomain=il" target="_blank" rel="noreferrer noopener">Yonatan Mevorach</a>, Developer Advocate at Wix.</p>



<h2 class="wp-block-heading"><span id="the-different-kinds-of-encryption-and-what-they-do">The different kinds of encryption and what they do</span></h2>



<p class="wp-block-paragraph">Think of cryptography as secret-keeping with math &#8211; the art of turning plain information into puzzles only the right key can solve. It’s built on a few core principles that Yonatan emphasizes:</p>



<ul class="wp-block-list">
<li><strong>Confidentiality</strong>: Ensuring that information is only accessible to authorized parties.</li>



<li><strong>Integrity</strong>: Guaranteeing that data remains unaltered during transmission or storage.</li>



<li><strong>Authentication</strong>: Verifying the identity of users or systems.</li>



<li><strong>Non-repudiation</strong>: Preventing entities from denying actions they have taken.</li>
</ul>



<p class="wp-block-paragraph">These principles shape how secure systems are built and come to life through encryption and cryptographic algorithms. At its core, encryption <strong>takes readable data and scrambles it into ciphertext</strong>, keeping it safe from prying eyes. In his lecture at the <a href="https://heapcon.io/2025" target="_blank" rel="noreferrer noopener">Heapcon conference</a>, Yonatan outlines the main approaches commonly used in modern development:</p>



<ol class="wp-block-list">
<li><strong>Symmetric Encryption</strong>: Uses a single key for both encryption and decryption. Examples include AES (Advanced Encryption Standard) and DES (Data Encryption Standard)</li>



<li><strong>Asymmetric Encryption</strong>: Uses a pair of keys (public and private) for encryption and decryption. Standard algorithms include RSA (Rivest-Shamir-Adleman) and ECC (Elliptic Curve Cryptography)</li>



<li><strong>Hashing</strong>: Converts data into a fixed-length hash value, which is irreversible. Examples: SHA-256 (Secure Hash Algorithm), Bcrypt, and Argon2 for password hashing.</li>



<li><strong>Hybrid Encryption</strong>: Combines symmetric and asymmetric encryption to balance performance and security. A common implementation is TLS (Transport Layer Security).</li>



<li><strong>Key Derivation Functions (KDFs)</strong>: Used to derive strong cryptographic keys from passwords or other input values. Examples include PBKDF2 (Password-Based Key Derivation Function 2), Argon2 (Winner of the Password Hashing Competition), and Scrypt (Designed to resist hardware-based attacks).</li>
</ol>



<p class="wp-block-paragraph">KDFs are crucial for securely storing passwords and generating encryption keys that are resistant to brute-force attacks.</p>



<h2 class="wp-block-heading"><span id="securing-your-apps-with-node-js-crypto-modules-and-modern-encryption">Securing your apps with Node.js, crypto modules, and modern encryption</span></h2>



<p class="wp-block-paragraph">As Mevorach explains, developers integrate encryption and cryptographic techniques into applications across various domains:</p>



<ul class="wp-block-list">
<li><strong>Secure Communications</strong>: Protocols like SSL/TLS secure web traffic and APIs.</li>



<li><strong>Data Protection</strong>: Encrypted databases and file systems (e.g., AES-encrypted storage in cloud environments).</li>



<li><strong>Authentication &amp; Access Control</strong>: Multi-factor authentication (MFA), digital signatures, and cryptographic tokens.</li>



<li><strong>Blockchain &amp; Cryptocurrencies</strong>: Cryptographic hashing secures transactions and smart contracts.</li>
</ul>



<p class="wp-block-paragraph"><strong>Role of the Crypto Module in Node.js</strong></p>



<p class="wp-block-paragraph">In Node.js, the crypto module provides a set of cryptographic functionalities, including hashing, encryption, and key generation, ensuring to read the official documentation for detailed API usage. </p>



<p class="wp-block-paragraph">It is widely used in web applications, authentication systems, and secure communication protocols.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Developers can leverage the crypto module to implement secure password storage, encrypt sensitive data, and integrate robust security mechanisms into Node.js applications.</p>
</blockquote>



<p class="wp-block-paragraph"><strong><a href="https://www.techtarget.com/searchsecurity/definition/Diffie-Hellman-key-exchange">Diffie-Hellman Key Exchange</a></strong>:</p>



<p class="wp-block-paragraph">This solution solves the key distribution problem by allowing two parties to establish a <strong>shared secret over a public channel</strong>.<strong> </strong></p>



<p class="wp-block-paragraph">The process? User 1 and User 2 exchange public keys derived from private keys. Each uses the other&#8217;s public and private keys to compute the shared secret. Implementation in Node.js uses &#8220;crypto. create Diffie-Hellman.&#8221;</p>



<h2 class="wp-block-heading"><span id="developers-can-protect-user-data"><span style="margin: 0px;padding: 0px">Developers can protect user data</span>!</span></h2>



<p class="wp-block-paragraph">&#8220;Security best practices are simple in principle but critical in execution. <strong>Use proven algorithms like AES-256 and RSA</strong>, derive keys securely, and avoid weak or guessable passwords. Always rely on cryptographically secure random generators.&#8221;</p>



<p class="wp-block-paragraph">That said, cryptography comes with its own challenges: key management, performance overhead, and evolving threats. Still, if you follow these best practices, you’re giving your software and your users real protection:</p>



<ul class="wp-block-list">
<li>Use well-established<strong> cryptographic libraries</strong> (e.g., OpenSSL, Bouncy Castle).</li>



<li>Regularly<strong> update algorithms</strong> to mitigate vulnerabilities.</li>



<li>Implement <strong>proper key management</strong> (e.g., Hardware Security Modules, cloud-based KMS solutions).</li>



<li><strong>Apply encryption</strong> at rest, in transit, and during processing where necessary.</li>
</ul>



<p class="wp-block-paragraph">So, as cyber threats become more sophisticated, encryption remain tools for secure software development. <span style="margin: 0px;padding: 0px">By integrating strong encryption practices and following industry standards, developers can build trustworthy systems that protect user data and maintain system integrity</span>.</p>


<figure class="wp-block-post-featured-image"><img decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2025/03/encryption_1_.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2025/03/encryption_1_.png 1200w, https://shiftmag.dev/wp-content/uploads/2025/03/encryption_1_-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2025/03/encryption_1_-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2025/03/encryption_1_-768x403.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure><p>The post <a href="https://shiftmag.dev/can-anyone-see-this-probably-yes-unless-you-encrypt-it-5028/">Can Anyone See This Password? Probably Yes &#8211; Unless You Encrypt It</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>From zero to full ownership of a legacy system in under 2 months </title>
		<link>https://shiftmag.dev/legacy-software-migration-3080/</link>
		
		<dc:creator><![CDATA[Dan Ambrosic]]></dc:creator>
		<pubDate>Tue, 02 Apr 2024 16:29:09 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[legacy software]]></category>
		<category><![CDATA[software migration]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=3080</guid>

					<description><![CDATA[<p>Fast forward one year, we have built a completely new system and are migrating customers. </p>
<p>The post <a href="https://shiftmag.dev/legacy-software-migration-3080/">From zero to full ownership of a legacy system in under 2 months </a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-post-featured-image"><img decoding="async" width="1200" height="630" src="https://shiftmag.dev/wp-content/uploads/2024/04/unknown-code.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2024/04/unknown-code.png 1200w, https://shiftmag.dev/wp-content/uploads/2024/04/unknown-code-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2024/04/unknown-code-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2024/04/unknown-code-768x403.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">One Monday afternoon, I received a call from my manager, which went along these lines: &#8220;Hi Dan, how are you?<strong> Would you like to travel to the US on Wednesday and take over some legacy services?</strong>&#8220;. I had a lot of questions and not a lot of time to discuss everything, but I still agreed. This call changed what I would be working on for a year or more.&nbsp;</p>



<p class="wp-block-paragraph">The next day, I got more context about the work and our end goal. <strong>It was to</strong> <strong>learn enough about the legacy system to keep it running</strong> until the replacement system was built and customers migrated. One caveat was that we had just 2 months to learn from the engineers working on it, so it was a tight schedule. &nbsp;</p>



<p class="wp-block-paragraph">Fast forward one year, we have built a completely new system and are migrating customers. In the meantime, the legacy system was still functioning, and we hadn&#8217;t experienced any major issues. Not that there weren&#8217;t issues or a few surprises along the way, but we must have done something right as we managed to go from zero to enough knowledge about the system and how to maintain it in less than two months.&nbsp;</p>



<h2 class="wp-block-heading"><span id="getting-the-lay-of-the-land">Getting the lay of the land&nbsp;</span></h2>



<p class="wp-block-paragraph">I knew next to nothing about the domain and workload the system was built to automatize. Luckily for me, most of it was written in Java, so I didn&#8217;t have to learn a new language as well as a new domain. &nbsp;</p>



<p class="wp-block-paragraph">We organized a few in-person days with the current engineering owners, business stakeholders, and internal users to get a good start. There, we got an overview of everything and started diving into the details of both the processes and implementations of various services. &nbsp;</p>



<p class="wp-block-paragraph">This is when we realized that we were really dealing with two subsystems. <strong>One consisted of two large monoliths over a decade old; the other was a newer microservices-oriented architecture</strong>. The latter was supposed to replace the two monoliths, but it was being done feature by feature. This meant that both subsystems were handling user&#8217;s requests, and we had to master both of them.&nbsp;</p>



<p class="wp-block-paragraph">We started by collecting the important information about each service involved in handling the user&#8217;s requests. That consisted of <a href="https://c4model.com/#ContainerDiagram" target="_blank" rel="noreferrer noopener">high-level container diagrams</a> showing most of the services, databases, and queues and how they communicated with each other. &nbsp;</p>



<p class="wp-block-paragraph">For each service, we gathered the locations of the following:&nbsp;</p>



<ul class="wp-block-list">
<li>Source code&nbsp;</li>



<li>Configuration files&nbsp;</li>



<li>Build jobs&nbsp;</li>



<li>Deployment jobs&nbsp;</li>



<li>Any other useful links or documentation&nbsp;</li>
</ul>



<p class="wp-block-paragraph">When we were done, there were 17 services and 5 databases to take over. Although it seems like you could search for that information when needed, <strong>having everything in one place proved very useful</strong>, especially later on when we needed to onboard new people. Also, knowing where everything is located meant we could check that we have permissions for the tools and access to the necessary virtual machines and databases. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2024/04/old-code-software-1024x538.png?x94846" alt="" class="wp-image-3085" srcset="https://shiftmag.dev/wp-content/uploads/2024/04/old-code-software-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2024/04/old-code-software-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2024/04/old-code-software-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2024/04/old-code-software.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="rolling-up-our-sleeves">Rolling up our sleeves&nbsp;</span></h2>



<p class="wp-block-paragraph">While waiting for all the permissions mentioned above, <strong>it was time to do what we did best: read the code</strong>. &nbsp;</p>



<p class="wp-block-paragraph">During the sessions with the business stakeholders, we gained an understanding of which functionalities were more important and which ones could be done manually if needed. That enabled us to first cover the ones that bring the most value. &nbsp;</p>



<p class="wp-block-paragraph">We focused on <a href="https://en.wikipedia.org/wiki/Happy_path" target="_blank" rel="noreferrer noopener">happy paths</a> because going through every line of the code wasn&#8217;t an option. I have to say that those monolith services were quite easy to read, as everything important was inside a single class or a single method without too many abstractions. On the other hand, we didn&#8217;t want to make any changes on the monoliths later, as we couldn&#8217;t exactly know what consequences a simple change would have. </p>



<p class="wp-block-paragraph">One thing I wish I had done from the start was bookmark those important classes and methods so I could find them faster in the future. I am sure I spent too much time locating the controller method, which handled the HTTP request, and following the method calls until I got to the actual business logic I was interested in.&nbsp;</p>



<p class="wp-block-paragraph">Still, we started understanding the main functionalities of each service and how to build and deploy them so we could get involved in the day-to-day operations and start troubleshooting real issues. It was crucial to see how the current owners handled those situations, as <strong>most issues have similar causes and need similar steps to fix them</strong>. &nbsp;</p>



<p class="wp-block-paragraph">For example, when a job failed, the procedure was to change its status to &#8220;pending&#8221;, and the service would retry that job. Another common issue was errors when storing some Unicode characters in the database that wasn&#8217;t configured to use the Unicode character set. Situations like those could fill a whole other article.&nbsp;</p>



<h2 class="wp-block-heading"><span id="the-takeover">The takeover&nbsp;</span></h2>



<p class="wp-block-paragraph">Once the time came for us to take full ownership of the system, we felt confident we could handle it because we were already troubleshooting issues and even deployed a few bug fixes. With that sorted, our focus shifted to designing and developing the replacement system to migrate the customers and shut down the legacy one.&nbsp;</p>



<p class="wp-block-paragraph">Although this wasn&#8217;t a project with all the newest bells and whistles, I did learn quite a lot from working on it. The most important lesson was that <strong>most systems will become legacy at some point</strong>, and we must keep that in mind while designing and developing them. That way, the next group of engineers that comes along to maintain it won&#8217;t need to ask a million questions.&nbsp;</p>
<p>The post <a href="https://shiftmag.dev/legacy-software-migration-3080/">From zero to full ownership of a legacy system in under 2 months </a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>You don&#8217;t need frontend developers for Backstage integration. But you do need adopters.</title>
		<link>https://shiftmag.dev/spotify-backstage-developer-platform-integration-2749/</link>
		
		<dc:creator><![CDATA[Nikola Gajski]]></dc:creator>
		<pubDate>Wed, 14 Feb 2024 17:20:32 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Developer Experience]]></category>
		<category><![CDATA[developer platform]]></category>
		<category><![CDATA[spotify backstage]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=2749</guid>

					<description><![CDATA[<p>Despite zero TypeScript and MERN experience we pulled off deploying Backstage in our platform, with much better user experience. Only 5 % of our engineers use it.</p>
<p>The post <a href="https://shiftmag.dev/spotify-backstage-developer-platform-integration-2749/">You don&#8217;t need frontend developers for Backstage integration. But you do need adopters.</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/2024/02/Developer-Platform.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2024/02/Developer-Platform.png 1200w, https://shiftmag.dev/wp-content/uploads/2024/02/Developer-Platform-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2024/02/Developer-Platform-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2024/02/Developer-Platform-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">Last year, I took the initiative to build a new internal developer portal with several other great engineers. We were all very enthusiastic, but there was one fundamental thing missing. Altogether, <strong>we had 0 to no experience</strong> with TypeScript and <a href="https://www.geeksforgeeks.org/mern-stack" target="_blank" rel="noreferrer noopener">MERN</a> stack, on top of which <strong>Spotify’s Backstage platform</strong> was built.&nbsp;</p>



<p class="wp-block-paragraph">All of us were passionate backend engineers with a few years of experience working in the infrastructure department. Our tech stack consisted of more traditional technologies like Java’s Spring and SQL databases. Naturally, the biggest concern was how we would handle technologies we weren’t familiar with and <strong>build user-friendly and intuitive interfaces</strong>. After all, we were backend developers who preferred writing command-line instructions, deprived of a sense of good user experience.&nbsp;</p>



<p class="wp-block-paragraph"> On the other hand, we had an ace up our sleeves<strong> &#8211; a deep understanding of how our platform works</strong>.&nbsp;</p>



<p class="wp-block-paragraph"> Contrary to popular belief, <strong>we pulled off deploying Backstage in our platform</strong> and integrating it with the existing tools without any major challenges. <strong>The biggest issue was (and still is) its adoption.</strong>&nbsp;</p>



<h2 class="wp-block-heading"><span id="so-where-is-the-catch">So, where is the catch?</span></h2>



<p class="wp-block-paragraph">Backstage has its set of core features, but it is also possible to extend it with your own or 3rd party plugins. &nbsp;Core features or 3rd party plugins usually work without much hassle – <strong>your custom configuration gets injected in premade modules through YAML files. &nbsp;</strong></p>



<p class="wp-block-paragraph">You can build interactive forms with multiple steps <strong>without writing any React code</strong>. This core feature is called <a href="https://backstage.io/docs/features/software-templates/" target="_blank" rel="noreferrer noopener">Software Templates</a>. We wanted to facilitate <strong>the bootstrapping of the Redis cluster.</strong> We had the define form which accepts configuration and actions that will be invoked on submission. The form was again defined through YAML. We had to write those simple actions in TypeScript, but after all, <strong>which developer doesn’t know how to write a function in any language?</strong>&nbsp;</p>



<p class="wp-block-paragraph"><strong> </strong>&nbsp;When we decided to improve <a href="https://backstage.io/docs/features/search" target="_blank" rel="noreferrer noopener">Search</a>, another core feature, the biggest effort was to <strong>optimize the PostgreSQL search engine</strong> and decide if it was worth going a step further and experimenting with Elasticsearch – in the end, it was.  &nbsp;</p>



<p class="wp-block-paragraph">While <strong>setting up authentication and SSO</strong>, the challenge was to explore all existing methods used throughout our company and unify them under one. Again, a task better suited for a platform engineer.&nbsp;</p>



<p class="wp-block-paragraph">With custom-made plugins, there was a little bit more React / TypeScript work. You have to <strong>figure out React fundamentals and start writing code.</strong> Backstage already provides out-of-the-box React components that <a href="https://backstage.io/docs/dls/contributing-to-storybook" target="_blank" rel="noreferrer noopener">follow their design principles</a>, so you won’t have to think about colors and paddings. If those components are not enough, you can use <a href="https://mui.com/" target="_blank" rel="noreferrer noopener">MUI components</a> from which the Backstage components are derived. Don’t worry, the internet is brimming with code examples.&nbsp;</p>



<p class="wp-block-paragraph">In the end, <strong>our knowledge of the platform and underlying infrastructure played a major role</strong> in our experience with developer portal integration. Lack of experience with frontend frameworks surely slowed us down a bit, but we learned along the way. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="582" src="https://shiftmag.dev/wp-content/uploads/2024/02/kazhoon-2-1024x582.jpeg?x94846" alt="" class="wp-image-2754" srcset="https://shiftmag.dev/wp-content/uploads/2024/02/kazhoon-2-1024x582.jpeg 1024w, https://shiftmag.dev/wp-content/uploads/2024/02/kazhoon-2-300x170.jpeg 300w, https://shiftmag.dev/wp-content/uploads/2024/02/kazhoon-2-768x436.jpeg 768w, https://shiftmag.dev/wp-content/uploads/2024/02/kazhoon-2.jpeg 1901w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



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



<p class="wp-block-paragraph">The biggest challenge, however, was yet ahead of us. It was (and still is) transitioning users from the old toolset they’ve been accustomed to. Despite the significant improvements in user experience and the addition of new functionalities, most users remain hesitant.&nbsp;</p>



<p class="wp-block-paragraph">To illustrate, we have a<strong> 10-year-old application management dashboard</strong> that is extensively used, but also <strong>notorious for its bad user experience</strong>. We modeled the new one after it, with a better user experience in place, but our developers still prefer the old one. When we asked them why they were not switching to the new one, their answer was simply – we don’t trust it.&nbsp;</p>



<p class="wp-block-paragraph">We also developed several nice and shiny plugins, a few features based on user requests, and resolved bugs we introduced on the way. Despite these efforts, <strong>our Backstage has yet to catch momentum.&nbsp;</strong></p>



<p class="wp-block-paragraph">We acquired most users when we organized a <a href="https://www.infobip.com/engineering/kazhoon-hackathon-creating-the-ultimate-dev-playground" target="_blank" rel="noreferrer noopener">two-day hackathon</a>, where each of the 9 teams built a plugin they needed. <strong>Only one plugin is extensively used</strong>, but it brought around 40 daily active users, which is only <strong>5% of our engineering organization</strong>. &nbsp;</p>



<p class="wp-block-paragraph">Despite the struggle, I believe that with good marketing, workshops, and constant improvements, we will bring most of the engineers to use and contribute to Backstage. When that happens, I’ll make sure to let you know how we managed to do it.&nbsp;</p>
<p>The post <a href="https://shiftmag.dev/spotify-backstage-developer-platform-integration-2749/">You don&#8217;t need frontend developers for Backstage integration. But you do need adopters.</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Database migration: Developers&#8217; open-heart surgery</title>
		<link>https://shiftmag.dev/database-migration-developers-open-heart-surgery-1926/</link>
		
		<dc:creator><![CDATA[Frane Jelavic]]></dc:creator>
		<pubDate>Mon, 06 Nov 2023 09:09:00 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[Database migration]]></category>
		<category><![CDATA[Live Database Migration experience]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=1926</guid>

					<description><![CDATA[<p>Live database migrations are developers' heart surgeries – and ours sure felt like it. Even now we have a long-lasting relationship with the patient and are keeping an eye on the surgery aftermath.</p>
<p>The post <a href="https://shiftmag.dev/database-migration-developers-open-heart-surgery-1926/">Database migration: Developers&#8217; open-heart surgery</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/2023/11/live-Database-migration.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/11/live-Database-migration.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/11/live-Database-migration-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/11/live-Database-migration-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/11/live-Database-migration-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">The task at hand was to <strong>migrate from the AWS relational PostgreSQL database to our on-prem self-hosted solution</strong>. We assembled a mission-based team comprising a Developer, DevOps, and two DBAs.</p>



<p class="wp-block-paragraph">The main driver of this migration was the <strong>steadily increasing monthly bill we got from AWS</strong>. If you don&#8217;t read all the fine print when navigating through AWS UI, you could be unpleasantly surprised by the amount of dollars you end up spending.</p>



<p class="wp-block-paragraph">But, we chose AWS for a valid reason. We had a POC (Proof Of Concept) and wanted to quickly gather customer feedback.</p>



<p class="wp-block-paragraph">We chose PostgreSQL at that time and opted for an &#8220;enhanced&#8221; Aurora version. Although we had an on-premise (in-house) solution, it was never battle-tested.</p>



<p class="wp-block-paragraph">From there, our journey&nbsp;began…</p>



<h2 class="wp-block-heading"><span id="choose-your-technologies-carefully"><strong>Choose your technologies carefully</strong></span></h2>



<p class="wp-block-paragraph">Our cluster was&nbsp;<a href="https://aws.amazon.com/rds/aurora/features/">AWS Aurora PostgreSQL RDS</a>&nbsp;with one writer and 4 standby servers. The servers were db.r5.8xlarge instances with 32 vCPU and 256 GB RAM with Aurora storage.</p>



<p class="wp-block-paragraph">The storage solution provides almost instant (approx. 20 ms) replication, with 4 out of 6 commit quorum.</p>



<p class="wp-block-paragraph">All servers use the same underlying storage, so commits from writers are propagated instantly to standbys, and asynchronous replication updates only the data in memory (shared buffers).</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="476" src="https://shiftmag.dev/wp-content/uploads/2023/10/image-1-1024x476.png?x94846" alt="" class="wp-image-1927" srcset="https://shiftmag.dev/wp-content/uploads/2023/10/image-1-1024x476.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/10/image-1-300x139.png 300w, https://shiftmag.dev/wp-content/uploads/2023/10/image-1-768x357.png 768w, https://shiftmag.dev/wp-content/uploads/2023/10/image-1.png 1252w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="560" src="https://shiftmag.dev/wp-content/uploads/2023/10/image-2-1024x560.png?x94846" alt="" class="wp-image-1928" srcset="https://shiftmag.dev/wp-content/uploads/2023/10/image-2-1024x560.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/10/image-2-300x164.png 300w, https://shiftmag.dev/wp-content/uploads/2023/10/image-2-768x420.png 768w, https://shiftmag.dev/wp-content/uploads/2023/10/image-2.png 1087w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph"><em>Reference from&nbsp;<a href="https://www.youtube.com/watch?v=--jED3W8Qy4&amp;t=1772s">AWS PostgreSQL In-Depth Training</a>.</em></p>



<p class="wp-block-paragraph">So we had help from the beginning&#8230;</p>



<p class="wp-block-paragraph">Replication was instant, so we hooked up the whole UI on our standby servers and got an immediate real-time response. Our solution was built on the assumption that changes from the writer server will be, nearly instantly, available to our standbys.</p>



<p class="wp-block-paragraph">The writer server was offloaded by efficiently using the standbys. We used Enhanced monitoring, set up Cloud Watch dashboards, analyzed and tracked every query on Performance Insight, and created alarms for every anomaly spotted in the setup.</p>



<p class="wp-block-paragraph">The level of observability and monitoring let us diagnose issues very quickly and correctly.&nbsp;Little did we know that <strong>that behavior differed widely from Vanilla Postgres</strong>. But we would find out soon enough.</p>



<h2 class="wp-block-heading"><span id="think-about-your-data-early"><strong>Think about your data early</strong></span></h2>



<p class="wp-block-paragraph">Our database DDL&nbsp;was structured&nbsp;to support the product launch and was never meant to be a long-term solution.</p>



<p class="wp-block-paragraph">Data&nbsp;was added&nbsp;but never deleted. Tables were not partitioned, and indexes have metastasized with various workloads. <strong>This resulted in tables with terabytes and indexes with hundreds of gigabytes of size.</strong></p>



<p class="wp-block-paragraph">We had to restructure. Keep the traffic data together and distinguish it from read-only and configuration data.</p>



<p class="wp-block-paragraph">Archiving was a very long and IO-intensive feature to develop, and it clashed with the migration efforts. During the product lifecycle, we had stale and test data we wanted to get rid of. <strong>We started data cleanup and removed gigabytes of data.</strong></p>



<p class="wp-block-paragraph">Again conflicting with the migration process.</p>



<h2 class="wp-block-heading"><span id="aws-charges-everything"><strong>AWS charges everything</strong></span></h2>



<p class="wp-block-paragraph">We didn&#8217;t start with a huge cluster, but with time and feature development, user adoption, and traffic increase, we had proportional demands on our underlying DB hardware.</p>



<p class="wp-block-paragraph">Fast forward to being approx. 4-5 years on the market, in production,<strong> we had huge I/O usages of our standbys. </strong>UI was sucking in two standbys, and their usage was through the roof in peak traffic hours, while the other standbys were battling the remaining read queries.</p>



<p class="wp-block-paragraph">We also hooked up some analytic reports on one of the servers to provide better statistics for our users.</p>



<p class="wp-block-paragraph">The monthly bill was rising steadily. Although we neglected costs apart from instance uptime, every I/O request had its price and so did our setup.</p>



<h2 class="wp-block-heading"><span id="on-premise-setup"><strong>On-premise setup</strong></span></h2>



<p class="wp-block-paragraph">Although our cluster was not tested with the same traffic AWS was handling at the moment, <strong>our setup was powerful.</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="462" src="https://shiftmag.dev/wp-content/uploads/2023/10/image-3-1024x462.png?x94846" alt="" class="wp-image-1929" srcset="https://shiftmag.dev/wp-content/uploads/2023/10/image-3-1024x462.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/10/image-3-300x135.png 300w, https://shiftmag.dev/wp-content/uploads/2023/10/image-3-768x347.png 768w, https://shiftmag.dev/wp-content/uploads/2023/10/image-3.png 1522w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">We had complete data center redundancy, meaning if a whole DC crashes, we could failover to the other one. Each DC had servers spread across three availability zones, so redundancy on the network level was also covered. Cluster orchestration with Patroni allowed for smooth failovers/switchovers and performing upgrades without downtime or maintenance window scheduling.</p>



<p class="wp-block-paragraph">Hardware-wise, we had Intel&#8217;s Platinum CPUs, a few generations better than we had provisioned on AWS. Storage was NVMe SSDs, so IO bottlenecks we had on AWS should be history.</p>



<h2 class="wp-block-heading"><span id="use-your-standbys-with-caution"><strong>Use your standbys with caution</strong><strong></strong></span></h2>



<p class="wp-block-paragraph">PostgreSQL allows you to use standby servers in a variety of ways:</p>



<ul class="wp-block-list">
<li><em>High availability</em>&nbsp;where the standbys&#8217; primary purpose is not to fall back from the writer and to replay WAL logs</li>



<li><em>Offloading big queries,</em>&nbsp;AKA poor men&#8217;s data warehousing</li>



<li><em>Horizontal scaling</em>, performing select queries to off-load the writer database</li>
</ul>



<p class="wp-block-paragraph">Every setup comes with its pros and cons, leading to&nbsp;streaming replication conflicts. We needed to choose whether we preferred replication changes or serving the current queries running on the standby(s).</p>



<p class="wp-block-paragraph"><strong>While the abilities of configuration are broad, they are not bulletproof.</strong> The development mindset had to change, since we were now dealing with streaming replication instead of the one provided by Aurora (which was almost completely synchronous without latency increase).</p>



<p class="wp-block-paragraph">Applications using standbys need to cope with&nbsp;<strong>eventual consistency.&nbsp;</strong>UI architecture for displaying real-time data from standbys in the new setup became an oxymoron from a logical perspective.</p>



<h2 class="wp-block-heading"><span id="limitations-of-logical-replication"><strong>Limitations of logical replication</strong></span></h2>



<p class="wp-block-paragraph"><a href="https://www.postgresql.org/docs/current/logical-replication.html" target="_blank" rel="noreferrer noopener">Logical replication</a>&nbsp;was used to transfer data from the current cluster to AWS. We had previous experience migrating data but on a completely different DDL layout (remember the portion of the text &#8220;<em>Think about your data early</em>&#8220;).</p>



<p class="wp-block-paragraph">The replication process has two phases.&nbsp;<strong>Initial data sync</strong>, where all the data currently in the table/schema is migrated, and the <strong>&#8220;catch-up&#8221; phase</strong> where the cluster syncs the subsequent changes from WAL logs.</p>



<p class="wp-block-paragraph">Since logical replication does not copy DDL changes to the target server, all changes were frozen for other developers working on the product.</p>



<p class="wp-block-paragraph">Our efforts were primarily aimed at <strong>reducing the cost</strong>, but we’ve managed to give ourselves some extra work in order to<strong> bring more value and earnings to the product.</strong></p>



<p class="wp-block-paragraph">The migration started by introducing replication slots on the source (AWS cluster) and subscribers on the target (on-premise). The first strategy, empirically, was to define one replication slot per database schema, as we did in our previous migration(s). Smaller schemas, up to 50 GB in size, were synced extremely fast and we experienced no issues.</p>



<h2 class="wp-block-heading"><span id="incidents-from-database-degradations">Incidents from database degradations</span></h2>



<p class="wp-block-paragraph">By the time we got to our main schema counting several TB of size,&nbsp;<strong>the first incident </strong><strong>happened</strong>. During the initial sync phase, WAL logs with subsequent changes are kept on the primary server. Given the way PostgreSQL provides&nbsp;<a href="https://www.postgresql.org/docs/current/transaction-iso.html">transaction isolation</a>, initial sync is thought of as a long-running transaction on the primary instance.</p>



<p class="wp-block-paragraph">The&nbsp;<a href="https://postgrespro.com/blog/pgsql/5967899">snapshot</a>&nbsp;xmin&nbsp;value is held and with it the&nbsp;event horizon. When this value is locked all queries &#8220;see&#8221; the DB state from the moment the transaction with xmin value started. In layman&#8217;s terms, every query has to start the execution from the snapshot of the DB that it was in at the moment of the ongoing transaction and go through changes (tuple versions) applied in the meantime.</p>



<p class="wp-block-paragraph"><strong>This results in prolonged query cost, inaccurate database statistics, and the most problematic one bloating of the database</strong> since&nbsp;<a href="https://www.postgresql.org/docs/current/sql-vacuum.html" target="_blank" rel="noreferrer noopener">the vacuum</a>&nbsp;is postponed. Approximately 5-6 hours in the replication we experienced complete degradation. IOPS got exhausted and we hit AWS limits, for our database instance level. <strong>We had to stop the replication, lose all the data currently migrated, and start over.</strong></p>



<p class="wp-block-paragraph">On the second attempt, armed with the experience we had from the first execution, we first divided our replication slots inside the schemas. Tables small in size were merged into a single replication slot, and every other table got its dedicated replication slot. Additional monitoring and alarms were set up to check the bloat and queries that were first impacted in the previous execution. Bigger tables were stripped from their indexes, and we decided to add them after the complete sync was done. <strong>The only index kept was the primary key one</strong>, since logical replication needs at least one unique constraint upon applying subsequent changes from WAL logs.</p>



<h2 class="wp-block-heading"><span id="the-migration-was-still-a-struggle"><strong>The migration was still a struggle.</strong> </span></h2>



<p class="wp-block-paragraph">The whole team was checking dozens of metrics and also browsing through our UI solution examining delays upon usage. We had to stop the migration and <strong>start over more than once</strong>, but this time it affected only a single, problematic table. Once we got to the biggest table inside our database, we needed to<strong> remove the primary key as well and recreate it once the initial sync was replicated.</strong></p>



<p class="wp-block-paragraph">We managed to copy all of the data to our on-premise cluster and were in the sync phase. Features such as data removal were halted until we fully migrated and we were now maintaining two separate clusters.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/11/Database-migration1-1-1024x538.png?x94846" alt="" class="wp-image-1948" srcset="https://shiftmag.dev/wp-content/uploads/2023/11/Database-migration1-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/11/Database-migration1-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/11/Database-migration1-1-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/11/Database-migration1-1.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="load-tests-with-business-specific-scenarios"><strong>Load tests with business-specific scenarios</strong></span></h2>



<p class="wp-block-paragraph">Data was replicated, clusters were up and running, DDL was synced, applications were working without issues, and the overhead of logically replicating changes didn&#8217;t affect the AWS cluster. Now what?</p>



<p class="wp-block-paragraph">We needed to put our HW to the test, and we needed a fallback if we ran into problems. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>This is the moment where we regretted not putting that extra time into having a load test.</strong> Not any kind of load test &#8211; the one that specifically mimics our production behavior, a user on our solution, and the ability to multiply it by a custom number.</p>
</blockquote>



<p class="wp-block-paragraph">Luckily, the majority of our load was SELECTs. We used our load balancers to include standby servers from the on-prem solution together with production ones. This allowed us to easily fall back, and kick out of the balancer, in case of degradation.</p>



<p class="wp-block-paragraph">The major downside of our approach was that <strong>every latency introduced in the system was immediately affecting the client.</strong> We have repeatable tests that monitor the solution and, in 99% of the cases, spot the degradation before the user does, but there is still that 1%. Apart from <strong>&#8220;testing in production&#8221;</strong>, another major downside is that there were too many unknowns inside the equation to have exact conclusions. There is always a probability something else is affecting the results when you are part of a live system.</p>



<p class="wp-block-paragraph">During these tests, we saw that our backups were disturbing our workloads and that we would need to introduce <strong>a separate server for full and incremental backups</strong>, something we didn&#8217;t even think about while we were on AWS.</p>



<p class="wp-block-paragraph">Amzon&#8217;s <a href="https://aws.amazon.com/rds/performance-insights/" target="_blank" rel="noreferrer noopener">Performance Insight</a>&nbsp;is worth every penny. Only when we stopped using it and lost the ability to check the lifecycle of every executed query and pinpoint the exact wait event causing the delay did we realize how powerful it was. </p>



<p class="wp-block-paragraph">We had to implement our solution, and we did, but again, we learned that <strong>we took some things for granted when using AWS.</strong></p>



<h2 class="wp-block-heading"><span id="the-patient-recovered-in-no-time"><strong>The </strong>patient recovered in no time</span></h2>



<p class="wp-block-paragraph">The final maintenance was scheduled for the complete migration of all services to the new on-prem solution. Here our preparation was on point. We&#8217;ve completely&nbsp;<strong>automated&nbsp;the process</strong>, we just needed to execute a few CLI commands to gracefully migrate the whole solution. Given the usage of our product, the only window we had, with minimal traffic and client impact, was from 0:00-3:00 UTC. Since we are in CET this meant a long night for us.</p>



<p class="wp-block-paragraph">We were struggling not to fall asleep before the maintenance started and would probably struggle to sleep afterward. <strong>The migration went surgically precise, and our patient recovered in no time.</strong> The window was scheduled for a full three hours, and we managed to redeploy, clean up error logs, and validate in a little more than an hour.</p>



<p class="wp-block-paragraph">Although falling asleep was hard because of the adrenaline spikes, the sense of accomplishment helped us rest our tired eyes.</p>



<h2 class="wp-block-heading"><span id="life-after-migration"><strong>Life after migration</strong></span></h2>



<p class="wp-block-paragraph">Looking back at the journey of the migration, a pragmatic observer could spot the good and the bad of each setup we had. <strong>Product maturity, access to powerful on-prem hardware, gathered know-how inside the company and cost reduction made the decision of the migration a no-brainer.</strong></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">However, there is a lot of work now on our hands that we just &#8220;threw money at&#8221; when using the cloud. Maybe the best thing to understand as an organization and as a developer is to recognize when you are ready to make this step.</p>
</blockquote>



<p class="wp-block-paragraph">Identify a step in your product lifecycle where such moves have to be taken. With increased usage of your solution, you should think about scalability and cost-efficiency not only on service level or feature bottlenecks but the ecosystem as a whole.</p>



<p class="wp-block-paragraph">Definitely choose your technologies wisely in the beginning. When you introduce new tech (platform change, &nbsp;database, framework, or even a library), build up expertise, check the knowledge inside the company, <strong>understand and take responsibility for bugs in the tech now being your bugs.</strong></p>



<p class="wp-block-paragraph">Don&#8217;t forget to think about scale.<strong> Premature optimization is the root of all evil, </strong>they say, but nevertheless, your design has to have a vision.</p>



<p class="wp-block-paragraph">These decisions are not easy, but neither is our job. We are fortunate to grow as individuals, learning by doing and owning our decisions, making us better developers but also human beings.</p>
<p>The post <a href="https://shiftmag.dev/database-migration-developers-open-heart-surgery-1926/">Database migration: Developers&#8217; open-heart surgery</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>We built a Python framework bridging the gap between AI and streaming platforms</title>
		<link>https://shiftmag.dev/fast-stream-python-framework-1646/</link>
		
		<dc:creator><![CDATA[Hajdi Cenan]]></dc:creator>
		<pubDate>Fri, 29 Sep 2023 17:04:25 +0000</pubDate>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[code generation]]></category>
		<category><![CDATA[data streaming]]></category>
		<category><![CDATA[Kafka]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[Python framework]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=1646</guid>

					<description><![CDATA[<p>We wanted to develop a framework that would make it easy to develop scalable and robust streaming microservices in Python.</p>
<p>The post <a href="https://shiftmag.dev/fast-stream-python-framework-1646/">We built a Python framework bridging the gap between AI and streaming platforms</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/2023/09/fast-stream.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">We are a small AI startup, and we&#8217;ve learned that it’s (relatively) easy to do pilot projects when you are small, as you can get away with your solutions not being on an enterprise level. But once you have to go to production, it’s a whole new ballgame. That&#8217;s how we got to create <strong>FastStream</strong>. </p>



<p class="wp-block-paragraph">It all started with our work on pilot projects with several large enterprise clients. We quickly realized that the key to a successful transition to production was <strong>seamless integration between our predictive models and existing streaming platforms.</strong></p>



<p class="wp-block-paragraph">However, we faced a challenge. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph"><strong>Java</strong> is the dominant language in the <strong>streaming ecosystem</strong>, while <strong>Python is the king of AI.</strong> This made it difficult to bridge the gap between the two worlds. </p>
</blockquote>



<p class="wp-block-paragraph">We looked for an existing tool but couldn’t find anything that fit our needs besides Faust, which is deprecated and not something we can rely on, not when working with large companies.</p>



<p class="wp-block-paragraph">That&#8217;s when we decided to create <strong><a href="https://faststream.airt.ai/0.1/#install" target="_blank" rel="noreferrer noopener">FastStream</a></strong>. We wanted to develop a framework that would make it easy to <strong>develop scalable and robust streaming microservices in Python</strong>, with the added benefit of <strong>automated code generation</strong> and predictive models.</p>



<h2 class="wp-block-heading"><span id="from-fastkafka-to-faststream">From FastKafka to FastStream</span></h2>



<p class="wp-block-paragraph">We started by calling it FastKafka, thinking we’d only use it internally and just for Kafka, but then decided to release it as an open-source, purely as a tool that might help someone else. Well, soon, we realized that it needed to be <strong>more than just a Kafka wrapper.</strong> </p>



<p class="wp-block-paragraph">The response of the community took us by surprise. We quickly crossed 500 stars on GitHub, but more importantly, we received valuable input in terms of feature requests, suggestions, and feedback from seasoned enterprise developers.</p>



<p class="wp-block-paragraph">One of our key collaborators was <strong>Nikita Pastukhov</strong>, the author of the Propan framework. Nikita contributed his expertise to merge the best features of Propan and FastKafka into a single, unified framework — FastStream.</p>



<p class="wp-block-paragraph">This collaborative approach helped us to create a robust and fully extendable API that supports not only Kafka but also other key streaming protocols.</p>



<h2 class="wp-block-heading"><span id="generate-an-application-from-a-short-textual-description">Generate an application from a short textual description</span></h2>



<p class="wp-block-paragraph">FastStream is not just about simplifying the codebase. Its architecture <strong>supports automatic code generation</strong> because we designed it with speed, scalability, and maintainability in mind. Namely, code generation is, in terms of time, a small part of the development; much more time is spent on the specification, creation of documentation, and testing. </p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="512" height="198" src="https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-code.png?x94846" alt="" class="wp-image-1655" srcset="https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-code.png 512w, https://shiftmag.dev/wp-content/uploads/2023/09/fast-stream-code-300x116.png 300w" sizes="auto, (max-width: 512px) 100vw, 512px" /></figure>



<p class="wp-block-paragraph">In our case, we have automated the whole process, whose result is a specified, documented, and tested microservice. In other words, our first prototype can <strong>generate an entire application</strong> — complete with unit and integration tests — <strong>from just a short textual description</strong> of the requirements but at the level of quality expected in large companies. </p>



<p class="wp-block-paragraph">It is absolutely mindblowing that a task that would normally take several hours, sometimes even days, for a single developer now takes about one minute.</p>



<p class="wp-block-paragraph">All this also enables seamless integration of our predictive models and future-proof microservices by allowing real-time data predictions.</p>
<p>The post <a href="https://shiftmag.dev/fast-stream-python-framework-1646/">We built a Python framework bridging the gap between AI and streaming platforms</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Here&#8217;s what to have in mind if you want to develop a collaborative app like Figma, Notion, or Canva</title>
		<link>https://shiftmag.dev/collaborative-apps-1224/</link>
		
		<dc:creator><![CDATA[Milena Radivojević]]></dc:creator>
		<pubDate>Fri, 08 Sep 2023 08:29:55 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Productivity]]></category>
		<category><![CDATA[Collaborative apps]]></category>
		<category><![CDATA[Daytona]]></category>
		<category><![CDATA[Developer Productivity]]></category>
		<category><![CDATA[Toma Puljak]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=1224</guid>

					<description><![CDATA[<p>Seamless user experience and resolving conflicts are the biggest challenges when developing collaborative apps. </p>
<p>The post <a href="https://shiftmag.dev/collaborative-apps-1224/">Here&#8217;s what to have in mind if you want to develop a collaborative app like Figma, Notion, or Canva</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/2023/08/toma_1-1.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/08/toma_1-1.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/08/toma_1-1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/08/toma_1-1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/08/toma_1-1-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph" style="font-size:0px"><a href="https://www.linkedin.com/in/toma-puljak/">Toma </a><a href="https://www.linkedin.com/in/toma-puljak/" target="_blank" rel="noreferrer noopener">Puljak</a> is a Software Developer with over 7 years of industry experience. He is fluent in Typescript, and with a strong background in C#, C++ and Python. Puljak joined Daytona as one of the core team members and he is included in almost all of the development processes in the company. </p>



<p class="wp-block-paragraph">Collaborative apps like Figma, Notion, and Google Docs foster collaboration and productivity by <strong>allowing users to interact with one another in real time</strong> but are challenging to develop. The biggest challenge is resolving conflict, and maintaining latency-free experience as more and more users join the app. <br><br>Toma Puljak, a developer and speaker at the upcoming <a href="https://belgrade.cityjsconf.org/" target="_blank" rel="noreferrer noopener">City JS Belgrade conference</a>, shared his experience with building collaborative apps with us. Toma has been working on developing IDE editor tool for almost 5 years, and has recently joined <a href="https://www.daytona.io/">Daytona</a>, a SDE (Standardized Development Environment) tool as a founding engineer. <br><br>Puljak is also a passionate speaker and loves to share his knowledge with the developer community. </p>



<p class="wp-block-paragraph"><strong>What does it mean for an app to be collaborative? </strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>A collaborative app is one that <strong>allows users to interact with one another in real-time</strong> and the use of collaboration features depends on the app itself. For example, users could write in the same document (think Google Docs), follow each other&#8217;s cursors through the app, or create different elements on a drawing board.</p>



<h2 class="wp-block-heading"><span id="collaboration-should-not-be-a-distraction">Collaboration should not be a distraction</span></h2>



<p class="wp-block-paragraph"><strong>Could you provide an example of a well-known collaborative app and discuss what aspects of its design and implementation make it successful?</strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>Some of the most popular collaborative apps (amongst developers) include<strong> Google Docs, Figma, and Notion</strong>. I’d say that what makes their collaboration features successful is the ease of use. They are collaborative by design, you don’t need to enable anything and users can just join and start working together. Collaboration should not be a distraction but a seamless way to work together and enhance your productivity and the apps that I mentioned do that very well.</p>



<p class="wp-block-paragraph"><strong>What are the benefits of collaborative apps both for users and businesses?</strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>The benefits of having collaboration features for users are mostly centered around boosting productivity. </p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Collaborative apps enable users to <strong>get their jobs done quicker and more efficiently</strong> because they eliminate the back and forth communication between colleagues. For businesses, anything that boosts productivity of their users is always a plus but collaboration can be that extra &#8220;Wow factor&#8221; that might boost engagement and customer satisfaction.</p>
</blockquote>



<p class="wp-block-paragraph"><strong>Tell us more about the collaborative features one app can have.</strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>I’ll start with the collaborative features that Daytona’s browser IDE has:</p>



<ul class="wp-block-list">
<li><strong>Collaborative text documents</strong>: Users can collaborate on the same text document in real-time and see what each user is writing and where their cursor is located.</li>



<li><strong>Collaborative terminals:</strong> Users can work together in the same terminal process and see the same output</li>



<li><strong>Chat</strong>: There is a dedicated chat window where users can write messages without leaving the IDE</li>



<li><strong>Screen sharing</strong>: Users can share their screen directly in the IDE which is an awesome feature to have when users need to collaborate on more than what the IDE offers.</li>
</ul>



<p class="wp-block-paragraph"><strong>What other collaborative features apps could implement?</strong></p>



<p class="wp-block-paragraph"><strong>Toma:</strong> Yes! There are<strong> collaborative drawing boards</strong> (similar to Figma, users can create different drawings or elements to create designs, charts, etc.), <strong>voice and video chats,</strong> and <strong>tracking cursors</strong>. This feature allows users to see exactly where other users are moving their cursor which gives them context on what their colleagues are focused on.</p>



<p class="wp-block-paragraph">The awesome thing about these features is that they can be expanded upon to include anything that their app offers to boost productivity and give that &#8220;Wow factor&#8221;.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/09/collaborative-apps-1024x538.png?x94846" alt="" class="wp-image-1374" srcset="https://shiftmag.dev/wp-content/uploads/2023/09/collaborative-apps-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/09/collaborative-apps-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/09/collaborative-apps-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/09/collaborative-apps.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="challenges-resolving-conflicts-and-scaling-collaboration">Challenges: Resolving conflicts and scaling collaboration</span></h2>



<p class="wp-block-paragraph"><strong>What challenges do developers face when they want to make apps more collaborative?&nbsp;</strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>One of the biggest challenges when implementing collaboration features is <strong>how to resolve conflicts</strong>. This is very important when working on collaborative text because users can edit, for example, the same line of text, and the collaboration implementation is responsible for <strong>resolving any conflicts</strong> that may arise. That’s why I mostly choose to work with <a href="https://github.com/yjs/yjs">Yjs</a> when implementing collaboration features. Yjs is based on Conflict-free replicated data types which automatically resolve any conflicts and ensure that users end up in the same state.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Another challenge might be <strong>scaling collaboration features</strong>. As more users connect to the same collaboration session, it’s important to maintain a latency-free experience and that’s something that a lot of implementations struggle with. That’s why it’s important to choose the right communication protocol. </p>
</blockquote>



<p class="wp-block-paragraph">For example, WebSockets or peer-to-peer communication. Yjs is here another life-saver because it comes with support for different protocols that developers can choose to ensure a smooth experience no matter how many users are working together.</p>



<p class="wp-block-paragraph"><strong>How can you ensure that the collaborative features of the app enhance the overall user experience rather than making it more complex?</strong></p>



<p class="wp-block-paragraph"><strong>Toma: </strong>The most important thing to think about when implementing collaboration features is to <strong>make it as seamless as possible</strong>. Don’t create hurdles, just allow users to jump into collaboration sessions and start working together without worrying about any of the setup.</p>



<p class="wp-block-paragraph">This could be achieved by sharing links or room identifiers or so on. Just make sure that the collaboration does not get in the way of the users&#8217; regular workflow but enhances it.</p>
<p>The post <a href="https://shiftmag.dev/collaborative-apps-1224/">Here&#8217;s what to have in mind if you want to develop a collaborative app like Figma, Notion, or Canva</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>API Bakery: Building APIs that build APIs</title>
		<link>https://shiftmag.dev/api-bakery-code-generator-1091/</link>
		
		<dc:creator><![CDATA[Senko Rasic]]></dc:creator>
		<pubDate>Fri, 18 Aug 2023 11:27:02 +0000</pubDate>
				<category><![CDATA[API]]></category>
		<category><![CDATA[Backend]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[AI code generator]]></category>
		<category><![CDATA[API Bakery]]></category>
		<category><![CDATA[API development]]></category>
		<category><![CDATA[code generator]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=1091</guid>

					<description><![CDATA[<p>Writing almost-boilerplate APIs seemed like a waste of time and clients' money. We've tried several existing code generators and ended up writing our own from scratch.</p>
<p>The post <a href="https://shiftmag.dev/api-bakery-code-generator-1091/">API Bakery: Building APIs that build APIs</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/2023/08/API-bakery.jpg?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/08/API-bakery.jpg 1200w, https://shiftmag.dev/wp-content/uploads/2023/08/API-bakery-300x158.jpg 300w, https://shiftmag.dev/wp-content/uploads/2023/08/API-bakery-1024x538.jpg 1024w, https://shiftmag.dev/wp-content/uploads/2023/08/API-bakery-768x403.jpg 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">API Bakery is a project generator SaaS. More specifically, it generates API services that can be used for web or mobile app backends or exposed to the public. In a way, it&#8217;s an API for generating APIs &#8211; with a twist. Based on a recipe that describes the project and data on a high level, API Bakery generates the complete ready-to-use project in a way that makes it easy to modify and build upon.</p>



<h2 class="wp-block-heading"><span id="code-generation-pros-and-cons">Code generation pros and cons</span></h2>



<p class="wp-block-paragraph">Generative AI helping programmers be more productive is all the rage now, but using programs to generate new programs is nothing new. As an industry, we&#8217;ve been doing that for decades. This is especially true for APIs. In the broadest strokes, an API can be understood as a specification of how to call (interface with) some program or service. <strong>And we programmers are lazy: if we have the spec, why not generate code for it?</strong></p>



<p class="wp-block-paragraph">The problem is two-fold: we can rarely <strong>automagically create <em>all</em> the functionality that we need</strong>; and auto-generated code is usually an ugly, unmaintainable mess.</p>



<p class="wp-block-paragraph">The many code-generator tools that exist can&#8217;t handle all imaginable cases and situations. Because of this, they focus on covering the most common functionality, or what&#8217;s the easiest to automate. For APIs, that&#8217;s usually the client SDKs that wrap the HTTP calls and parse the responses. This works, but the resulting code isn&#8217;t as nice to use as something crafted by hand. On the server side, the generated code usually consists of empty wrapper methods that need to be filled in by the user to actually provide the working code.</p>



<p class="wp-block-paragraph">This brings us to the second problem: <strong>having to update and maintain that code manually</strong>. Often, the generated code <strong>doesn&#8217;t conform to the coding style, best practices, or patterns of the framework or platform being used</strong>. Because it doesn&#8217;t have a wider context of the entire application, it can also be sub-optimal or have potential security issues. Nobody likes having to go in and deswamp that.</p>



<h2 class="wp-block-heading"><span id="trying-existing-code-and-api-generators">Trying existing code and API generators</span></h2>



<p class="wp-block-paragraph">On the other hand, <strong>code generators <em>can</em> save you a lot of time</strong>. In our web development agency work, we&#8217;ve worked on a lot of projects where the API was mostly standard CRUD (Create, Read, Update, Delete) methods, plus a few things like payments and project-specific flows. <strong>Writing this almost-boilerplate API seemed like a waste of time and clients&#8217; money</strong>, so we started using existing project generators and building an internal tool to automate as much of it as possible.</p>



<p class="wp-block-paragraph">Most modern web frameworks have one (or a few) project generators. We work with Django (a web framework for Python) a lot, and there are at least a dozen Django project generators, with the most popular being <code>cookiecutter</code>. However, we found that those generators can only provide a barebones skeleton for a new empty project. <strong>All those CRUD APIs we still had to write ourselves.</strong></p>



<p class="wp-block-paragraph">The more we tried to customize the generators to help us generate more code, the more we had to maintain those customizations, in effect creating our own framework on top of Django. This was definitely not the way we wanted to go.</p>



<p class="wp-block-paragraph">We also tried using Swagger (an open API specification that can be used to generate documentation or client or server code) and found out that <strong>writing a complete OpenAPI spec was almost the same amount of work as writing the Django code for it!</strong></p>



<h2 class="wp-block-heading"><span id="how-we-built-api-bakery">How we built API Bakery</span></h2>



<p class="wp-block-paragraph">What we ended up doing was <strong>writing our own code generator from scratch</strong>, focusing on two things: making it take a description of a project only to generate what&#8217;s needed and making sure the generated code looks and works great, <strong>like it was written by an actual person on the team.</strong></p>



<p class="wp-block-paragraph">This means, for example, that the code passes code-style and quality checks (linters), has unit tests (we aim for 90%+ coverage out of the box), and that when you open any file in the editor, the layout, variable naming, etc. all feels &#8220;normal&#8221;. On the flip side, we wanted to make sure we didn&#8217;t generate any generic code that would do more than asked: we aimed for the simplest, straightforward solution like a human programmer would.</p>



<p class="wp-block-paragraph"><strong>We sorely underestimated how hard it would be!</strong> It took us a few rewrites of the generator itself to make it to a point where we&#8217;re satisfied with the output and with the complexity of the generator.</p>



<p class="wp-block-paragraph">Realizing how useful it could be to other developers beyond our agency, we decided to spin it off into a separate standalone software as a service &#8211; <a href="https://apibakery.com/" target="_blank" rel="noreferrer noopener">API Bakery</a>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-2-1024x538.png?x94846" alt="" class="wp-image-1093" srcset="https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-2-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-2-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-2-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-2.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="how-api-bakery-works">How API Bakery works</span></h2>



<p class="wp-block-paragraph">API Bakery combines project scaffolding (creating a structure for a new empty project), database model generation, CRUD API generation, and tests (and other features, but these are the main areas). Of those, the project scaffolding part is straightforward and doesn&#8217;t need to be customized much &#8211; it&#8217;s the most like other generator tools like <code>cookiecutter</code>. For a new project, we just create a couple dozen files with (mostly) boilerplate code.</p>



<p class="wp-block-paragraph">The database model generation needs to know the structure of your data. This structure is an input to API Bakery in a form of a JSON recipe. The recipe describes the database models and their relationships. For example, a webshop might have Products that are grouped into Categories. Each Product might have a few Variants (SKUs), and so on. API Bakery users configure this through a web-based UI, and it is passed as a JSON recipe to the project generator. Based on this, the actual code to create and manage the data is created.</p>



<p class="wp-block-paragraph">The API generation builds on this. <strong>API Bakery generates the standard CRUD methods for accessing and managing the data through a REST API.</strong> The code for this is generated in such a way that it&#8217;s easy to add custom API (like payments or more involved data flows) later. We realize that no generator can generate all the functionality, so we take care to make it easy to expand it with custom code.</p>



<p class="wp-block-paragraph">Finally, we generate automated tests. This has proven the most tricky part because tests must be tailored to the API for the custom data models. Things like default or required fields, allowed values, and permissions all must be handled here; there are tons of edge cases that we have to handle.</p>



<p class="wp-block-paragraph">Finally, we have a Docker-based isolated environment in which we run the linters and tests to make sure the generated code does what it&#8217;s supposed to do. Automated tests with high coverage make this easier &#8211; we just run the tests we generated in the previous steps.</p>



<p class="wp-block-paragraph">For the user, this all takes a few seconds, and the project is baked and ready!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-3-1024x538.png?x94846" alt="" class="wp-image-1094" srcset="https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-3-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-3-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-3-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/08/api-bakery-3.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="the-ai-future">The AI future?</span></h2>



<p class="wp-block-paragraph">Will AI replace us all? The jury is still out, but in the meantime, we&#8217;ve started exploring how it can make our projects better. For API Bakery, we&#8217;re very happy with the code generator and don&#8217;t think GPT or other coder AIs are there yet when it comes to creating a full non-trivial project. Where we see the value is in combining AI&#8217;s ability to understand imprecise, implicit, and context-dependent human instructions.</p>



<p class="wp-block-paragraph">Our current integration takes advantage of this &#8211; users can describe their project in as much detail as they like<strong> in normal human language. We then use GPT4 to turn these instructions into a recipe, which then feeds into our existing code generator. The results have been striking. You can literally type one sentence and get a fully working and tested project for what you describe.</strong></p>



<p class="wp-block-paragraph">Where AI can be of great use is also in side-coding or co-piloting, i.e., helping the programmer write code faster and better. This is an area that API Bakery doesn&#8217;t currently cover &#8211; once you have the initial project generated, you&#8217;re on your own. Using AI to add custom code to an existing project and to go beyond CRUD API is an exciting proposition and within the realm of feasibility already.</p>



<p class="wp-block-paragraph"><strong>With continuing AI progress, the life of API developers will just get easier!</strong></p>
<p>The post <a href="https://shiftmag.dev/api-bakery-code-generator-1091/">API Bakery: Building APIs that build APIs</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>From file frustration to streamlined data exchange: Rethinking the approach</title>
		<link>https://shiftmag.dev/from-file-frustration-to-streamlined-data-exchange-999/</link>
		
		<dc:creator><![CDATA[Alen Kosanovic]]></dc:creator>
		<pubDate>Tue, 25 Jul 2023 17:29:06 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[anti-pattern]]></category>
		<category><![CDATA[CSV]]></category>
		<category><![CDATA[data exchange]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=999</guid>

					<description><![CDATA[<p>Each time some data is exchanged using files, a red flag should pop up, and you should ask yourself – what is a better way to do this? There probably is one.</p>
<p>The post <a href="https://shiftmag.dev/from-file-frustration-to-streamlined-data-exchange-999/">From file frustration to streamlined data exchange: Rethinking the approach</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/2023/07/data_exchange.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/07/data_exchange.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/07/data_exchange-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/07/data_exchange-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/07/data_exchange-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">Occasionally, everyone needs to handle data stored in files. CSV files seem like the way to go and are often the first choice &#8211; but I&#8217;d rather call them an anti-pattern.</p>



<p class="wp-block-paragraph">Let&#8217;s say a customer requests an Excel report containing specific data. If this is a one-time thing, we can conveniently send it via email. In most cases, however, the data needs to be sent regularly.&nbsp;Not all clients use sophisticated software like Kafka; even when they do, we don&#8217;t always have access to it. So we need a solution that is both universally available and easily understood. SFTP and CSV files seemingly fit the bill.</p>



<p class="wp-block-paragraph">This solution seems optimal for sending data to an external client. The problem arises when an internal application needs to integrate with ours, requires some data, and we decide to solve it by exporting CSVs. At first glance, this seems a low-hanging fruit.</p>



<p class="wp-block-paragraph">Everyone can download a file.</p>



<p class="wp-block-paragraph">Everyone can read a CSV.</p>



<p class="wp-block-paragraph">It&#8217;s already developed.</p>



<p class="wp-block-paragraph"><strong>While it may appear&nbsp;<em>that</em>&nbsp;simple, ultimately, it proves to be more costly than using a dedicated component for data exchange. </strong>I learned my lesson the hard way. I&#8217;ve worked on both applications that sent and received data via files. Here are some of the issues I discovered along the way.</p>



<h2 class="wp-block-heading"><span id="data-storage">&nbsp;<strong>Data storage</strong></span></h2>



<p class="wp-block-paragraph">The first thing we need is a place to store the data. Since our data is stored in files, it must be placed within a file system. The decision we face is whether to store the files on the&nbsp;<strong>producer</strong>&nbsp;machine,&nbsp;<strong>consumer</strong>&nbsp;machine, or an&nbsp;<strong>intermediary</strong>&nbsp;machine. Each option has its advantages and disadvantages.</p>



<p class="wp-block-paragraph"><strong>Using the producer</strong>&nbsp;machine results in the consumer bearing the entire networking load. The consumer will need to periodically retrieve the data through a&nbsp;<strong>PULL</strong>&nbsp;operation. In the event of a network link failure, the producer will remain unaffected.&nbsp;</p>



<p class="wp-block-paragraph">However, this solution has a drawback &#8211; when consumers are redundant, and there are multiple instances, each instance may attempt to download the same file. Consequently, the same data will be processed multiple times. To address this,&nbsp;<strong>each instance should reserve the file before initiating the download</strong>. This can be accomplished by appending a suffix to the file name or moving the file to another folder. Once the file is reserved, the consumer application can proceed with the file download.</p>



<p class="wp-block-paragraph"><strong>Using the consumer</strong>&nbsp;machine puts all the networking burden on the producer. The producer needs to&nbsp;<strong>PUSH&nbsp;</strong>the data to the consumer machine once the file is created. The consumer machine can watch the local file system for changes and react when a new file is created. As a result, the push-based approach can yield a faster response by the consumer and does not put any networking burden on the consumer. Since the file is sent directly to the consumer instance, this approach does not need&nbsp;<em>file reservation.</em>&nbsp;</p>



<p class="wp-block-paragraph">Pushing files to consumers also has a considerable downside &#8211; the producer must balance these files between the consumer instances. Implementing effective client-side balancing is a tough nut to crack. The producer would need to adapt its balancing strategy when a consumer instance gets offline or online and is added to or removed from the group.</p>



<p class="wp-block-paragraph"><strong>Using an intermediary machine</strong>&nbsp;combines elements of both previously mentioned approaches. It eliminates the need for client-side balancing, but the consumer still needs to reserve the file before downloading it. The data storage is independent of both the consumer and producer, although both parties are still required to transfer files over the network.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange1-1024x538.png?x94846" alt="" class="wp-image-1053" srcset="https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange1-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange1-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange1-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange1.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="data-retention"><strong>Data retention</strong></span></h2>



<p class="wp-block-paragraph">Regardless of the chosen method for storing data, it is crucial to ensure that the disk is not filled with files. Failing to do so will render the machines (and the services running on them) unusable. The primary line of defense is to&nbsp;<strong>store files on a separate section of the disk</strong>.&nbsp;</p>



<p class="wp-block-paragraph">Even if the partition gets filled with files, it will not impact other services. This advice applies even when files are stored on an intermediary machine, as some operating system functionalities may not work properly if the disk space is occupied.</p>



<p class="wp-block-paragraph">Accumulating files can happen quite easily. For instance, the consumer application may be down (or not deployed) while the producer application continues to generate files. It can also occur if the producer generates a high volume of data the consumer cannot keep up with.&nbsp;</p>



<p class="wp-block-paragraph">In such cases, it is necessary to prevent the files from <strong>overflowing the disk.</strong> If the data represents events and skipping a few events in the event of a failure is acceptable, a retention policy should be implemented.&nbsp;</p>



<p class="wp-block-paragraph">For example, a script that periodically deletes the oldest files can be developed. This script adds <strong>another component to the architecture that needs to be created, maintained, and monitored</strong>. If the script malfunctions or contains a bug, the data retention may not work as intended.</p>



<h2 class="wp-block-heading"><span id="data-processing"><strong>Data processing</strong></span></h2>



<p class="wp-block-paragraph">A file is removed from the disk when a consumer has read and processed the whole file content. The &#8216;whole file content&#8217; is emphasized since a file represents a batch of data. Errors or failures can happen at any point between parsing and processing the data. If you delete the file without processing all the data contained within it, the data will be lost. On the other hand, if you do not delete the file but have already processed some of the data, you will end up processing the same data twice. This poses a data integrity concern that needs to be addressed. Both discarding data and processing data twice are undesirable and potentially unacceptable. That is why&nbsp;<strong>it is necessary to process a file in its entirety before deleting it</strong>.</p>



<p class="wp-block-paragraph">This can be challenging, especially if the application involves multiple processing steps, including several database writes. Errors occurring in any of these phases can result in the entire batch being reversed. Additionally, processing a batch of data within a single transaction restricts the data processing to only one thread. File reading and data processing should be performed in separate threads to optimize performance.</p>



<p class="wp-block-paragraph">One possible solution is to relax the data integrity requirement by&nbsp;<strong>implementing a queue where all the data is stored after parsing</strong>. This approach considers a file processed once all its records are inserted into the queue. Records can then be dequeued one by one, preventing the entire batch from being reverted. The issue with this approach is that the data in the queue will be lost in the event of an abrupt application failure. Since abrupt application failures are expected to be rare, this trade-off may be acceptable. If preserving data is not acceptable, a persistent queue for the data can be introduced (but we opted out of using new components in favor of using&nbsp;<em>simple CSV reading</em>).</p>



<p class="wp-block-paragraph">It is also important to&nbsp;<strong>set a reasonable limit to the number of records in a file</strong>. A large file might present a huge load of data at once. So huge that it might crash the data if it does not have the memory to read the whole file.</p>



<h2 class="wp-block-heading"><span id="data-sharing"><strong>Data Sharing</strong></span></h2>



<p class="wp-block-paragraph">Once everything is set up and all the monitoring points are implemented (excluded from this article), we can enjoy our manually implemented file-based data exchange solution… until a new consumer is needed for the same data.&nbsp;</p>



<p class="wp-block-paragraph">Fortunately, we already have this functionality (file download+reservation, data retention, data queuing, monitoring, etc.) supported, and we can easily re-use it in any new consumer. Hopefully, the code has been written well enough to be copied and pasted into a library. Otherwise, there will be significant code duplication. Let&#8217;s not forget to create<strong> documentation for the module </strong>so that the solution can be integrated effortlessly.</p>



<p class="wp-block-paragraph">Once we move this code to a module, our file-based data exchange solution will become a reusable component that any application can utilize (provided it is written in the same programming language). The only thing left is instructing the producer to export the files to a new location. There might be some duplicated data between the two locations, but let&#8217;s hope we will not add many of these consumers to the system.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange-files-1024x538.png?x94846" alt="" class="wp-image-1052" srcset="https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange-files-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange-files-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange-files-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/07/data-exchange-files.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="data-storage-already-handles-this-%e2%80%93-and-it-does-it-better"><strong>Data storage already handles this – and it does it better</strong></span></h2>



<p class="wp-block-paragraph">These are only some of the issues that we encountered. There are more of them, some not even mentioned here, and others are yet to be discovered. To resolve them, we had to invest time in development, refactoring, and as a result, we now have a code base to maintain.&nbsp;</p>



<p class="wp-block-paragraph">But <strong>these problems were not unique to us.</strong> They were common problems that most data storage software handles out-of-the-box and does it better!</p>



<p class="wp-block-paragraph">The selection of software depends on the nature of the data. In our case, the data were events, and the producer application performed some batch processing on it. A more&nbsp;suitable storage option than the one we have been using <strong>would be a messaging system:</strong></p>



<p class="wp-block-paragraph">· Producers and consumers would write and read from a topic or a queue.</p>



<p class="wp-block-paragraph">· Data would be stored and replicated to another machine, also enabling Geo-redundancy.</p>



<p class="wp-block-paragraph">· Retention would be managed by the platform, eliminating the need for manual scripts.</p>



<p class="wp-block-paragraph">· Messaging systems have a&nbsp;<em>commit</em>&nbsp;feature to indicate that a record (or batch) has been processed.</p>



<p class="wp-block-paragraph">· Some messaging systems support consumer groups, allowing concurrent processing out-of-the-box.</p>



<p class="wp-block-paragraph">· Different consumers (applications) can be subscribed to the same topic.</p>



<p class="wp-block-paragraph">· Applications can be written in the most popular programming languages.</p>



<p class="wp-block-paragraph">· Monitoring tools for popular systems are already available.</p>



<p class="wp-block-paragraph">· Popular systems are usually well-documented.</p>



<p class="wp-block-paragraph">For other types of data, the solution might be a more suitable data store like <strong>Redis or Postgres</strong>. It all depends on what the data is about and how it can be presented.</p>



<p class="wp-block-paragraph"><strong>Exchanging data via files should be considered an anti-pattern</strong> and only be used when other approaches cannot be implemented (like when integrating with a legacy system).&nbsp;Each time some data is exchanged using files, a red flag should pop up, and you should ask yourself &#8211; what is a better way to do this? There probably is.</p>
<p>The post <a href="https://shiftmag.dev/from-file-frustration-to-streamlined-data-exchange-999/">From file frustration to streamlined data exchange: Rethinking the approach</a> appeared first on <a href="https://shiftmag.dev">ShiftMag</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>On APIs eating the world and creating TikToks for developers with Joyce Lin of Postman</title>
		<link>https://shiftmag.dev/joyce-lin-postman-api-308/</link>
		
		<dc:creator><![CDATA[Antonija Bilic Arar]]></dc:creator>
		<pubDate>Thu, 11 May 2023 15:00:14 +0000</pubDate>
				<category><![CDATA[Backend]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Joyce Lin]]></category>
		<category><![CDATA[Postman]]></category>
		<category><![CDATA[Shift Conference]]></category>
		<guid isPermaLink="false">https://shiftmag.dev/?p=308</guid>

					<description><![CDATA[<p>More than 50% of developers say that more than half of their organization's development effort is spent on APIs. </p>
<p>The post <a href="https://shiftmag.dev/joyce-lin-postman-api-308/">On APIs eating the world and creating TikToks for developers with Joyce Lin of Postman</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/2023/05/joyce_lin_postman.png?x94846" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" style="object-fit:cover;" srcset="https://shiftmag.dev/wp-content/uploads/2023/05/joyce_lin_postman.png 1200w, https://shiftmag.dev/wp-content/uploads/2023/05/joyce_lin_postman-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/05/joyce_lin_postman-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/05/joyce_lin_postman-768x403.png 768w" sizes="auto, (max-width: 1200px) 100vw, 1200px" /></figure>


<p class="wp-block-paragraph">Almost every developer works with web APIs today, and the time they spend working with APIs continues to grow year over year.&nbsp;</p>



<p class="wp-block-paragraph">No wonder Joyce Lin, Head of Developer Relations of Postman, decided that her talk at the Shift conference in Miami would be titled <strong>&#8220;APIs are eating the universe&#8221;</strong>. Postman &#8211; a platform for building and using APIs, has 20 million users. In their State of the API report, 51% of respondents said that more than half of their organization&#8217;s development effort is spent on APIs.&nbsp;And 89% say API investments would rise or remain steady in the coming year.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">You don’t have to be a developer to feel the impact of APIs in our everyday lives. They’re all around us. </p>
<cite>Joyce Lin, Postman</cite></blockquote>



<p class="wp-block-paragraph"><em>Even developers who haven’t traditionally worked with web APIs are starting to get involved as the world becomes more interconnected, for example with data integrations and third-party services.</em></p>



<h2 class="wp-block-heading"><span id="apis-live-and-die-by-developer-experience">APIs live and die by developer experience</span></h2>



<p class="wp-block-paragraph">Asked to provide some words of wisdom for both API providers and API consumers, Lin has only two words to say: <strong>developer experience</strong>.</p>



<p class="wp-block-paragraph"><em>API providers that offer a smooth onboarding process have a developer mindset, and frequently this corresponds to the API itself in terms of design and support. <strong>You may think you have the best API on the market</strong>, but if it’s poorly documented and unpredictable, that’s a disservice to your consumers. Create onboarding guides to help reduce the time to value for your consumers. Watch new developers read through the docs and make their first call, and ask new team members to record their first experiences while they have fresh perspectives.</em></p>



<p class="wp-block-paragraph">When it comes to API consumers, Lin says that sometimes the simple criterion of &#8220;it just works&#8221; can be enough when evaluating different API options:</p>



<p class="wp-block-paragraph"><em>Of course, you’ll want to make sure that the API is affordable, scalable, and can grow with your business. But don’t discount the value of an API that just works when evaluating different choices for APIs.</em></p>



<p class="wp-block-paragraph">In her talk at the <strong><a href="https://shift.infobip.com/us/">Shift Miami conference</a></strong>, Joyce reflected on the popularity of API protocols and patterns over time but also talked about <strong>what&#8217;s next in API development and how </strong>she sees it evolving. At <strong><a href="https://shift.infobip.com/#hero" target="_blank" rel="noreferrer noopener">Shift Zadar</a></strong> Joyce will show <strong>how to reverse engineer a private web API</strong>. </p>



<h2 class="wp-block-heading"><span id="the-developer-community-is-a-collaborative-space"><strong>The developer community is a collaborative space</strong></span></h2>



<p class="wp-block-paragraph">As a Head of Developer Relations, Joyce&#8217;s job is to share her knowledge through speaking, blog posts, or videos with the developers&#8217; community. She got into developer advocacy when she was trying to find a job as a software engineer after attending a coding boot camp. She had previously worked as a product manager:&nbsp;</p>



<p class="wp-block-paragraph"><em>Even though I had never heard of this type of role, I got a job as a developer advocate, which allowed me to be technical and share what I learned with the community.</em></p>



<p class="wp-block-paragraph"><em>Something about the developer community that I admire is that a lot of people do this on their own time, even if they don’t officially work in developer relations. <strong>It is a very collaborative space where people build open-source tools and projects and share their wisdom freely.</strong>&nbsp;</em></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="538" src="https://shiftmag.dev/wp-content/uploads/2023/05/Joyce-Lin-1024x538.png?x94846" alt="" class="wp-image-542" srcset="https://shiftmag.dev/wp-content/uploads/2023/05/Joyce-Lin-1024x538.png 1024w, https://shiftmag.dev/wp-content/uploads/2023/05/Joyce-Lin-300x158.png 300w, https://shiftmag.dev/wp-content/uploads/2023/05/Joyce-Lin-768x403.png 768w, https://shiftmag.dev/wp-content/uploads/2023/05/Joyce-Lin.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading"><span id="reaching-more-developers-on-tiktok-than-on-twitter">Reaching more developers on TikTok than on Twitter</span></h2>



<p class="wp-block-paragraph">The space is becoming more and more crowded, with tonnes of content being created almost daily. At the same time, the average attention span is getting shorter. Joyce is one of the rare tech content creators <strong><a href="https://www.tiktok.com/@joycejetson?lang=en">exploring TikTok</a> as a channel to reach developers</strong>.</p>



<p class="wp-block-paragraph"><em>I like to watch cat and dog videos and don’t personally use TikTok to learn about technology, so I am still surprised when people watch my TikToks about anything that I come across in my daily tech career, from web scraping to continuous integration.</em></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">I am able to reach way more people on TikTok compared to other platforms like Twitter or YouTube. </p>



<p class="wp-block-paragraph">Even better, people are not just listening to what I have to say; they’re leaving comments and sharing their own ideas. So I get to learn as much from my viewers as they learn from me. &nbsp;</p>



<p class="wp-block-paragraph">It’s an easy and quick way for me to see what’s on everyone’s minds.</p>
<cite>Joyce Lin, Postman</cite></blockquote>



<p class="wp-block-paragraph"><em>Sharing your ideas like this increases the discourse in the developer community and also helps independent developers who may not have access to the diversity of thoughts and trends available on the broader interwebs.</em></p>
<p>The post <a href="https://shiftmag.dev/joyce-lin-postman-api-308/">On APIs eating the world and creating TikToks for developers with Joyce Lin of Postman</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-06-19 14:24:36 by W3 Total Cache
-->