<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Saif Ullah Usmani</title>
    <description>The latest articles on DEV Community by Saif Ullah Usmani (@saifullahusmani).</description>
    <link>https://dev.to/saifullahusmani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F638356%2F93bafbeb-a1fd-4030-a77a-c158fe0a13ab.png</url>
      <title>DEV Community: Saif Ullah Usmani</title>
      <link>https://dev.to/saifullahusmani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/saifullahusmani"/>
    <language>en</language>
    <item>
      <title>Top 10 PDF Tools Everyone Needs</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Thu, 23 Apr 2026 20:56:00 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/top-10-pdf-tools-everyone-needs-1kn5</link>
      <guid>https://dev.to/saifullahusmani/top-10-pdf-tools-everyone-needs-1kn5</guid>
      <description>&lt;p&gt;PDFs are everywhere, resumes, contracts, reports, ebooks. But working with them can be frustrating without the right tools.&lt;/p&gt;

&lt;p&gt;Instead of installing heavy software, you can handle everything directly in your browser using &lt;strong&gt;keynou.com&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are the &lt;strong&gt;top 10 PDF tools you should be using&lt;/strong&gt; to save time and simplify your workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  📄 1. PDF to Word Converter
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:0]{index=0}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Turn static PDFs into editable documents.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/pdf/pdf-to-word" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf/pdf-to-word&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Editing contracts
&lt;/li&gt;
&lt;li&gt;Updating resumes
&lt;/li&gt;
&lt;li&gt;Extracting content
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📑 2. Word to PDF Converter
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:1]{index=1}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Convert documents into a universal, shareable format.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/pdf/word-to-pdf" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf/word-to-pdf&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Professional sharing
&lt;/li&gt;
&lt;li&gt;Finalizing documents
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🗜️ 3. PDF Compressor
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:2]{index=2}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Reduce file size without losing quality.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/compressor/pdf-compressor" rel="noopener noreferrer"&gt;https://keynou.com/tools/compressor/pdf-compressor&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Email attachments
&lt;/li&gt;
&lt;li&gt;Upload limits
&lt;/li&gt;
&lt;li&gt;Faster sharing
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 4. PDF Merger
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:3]{index=3}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Combine multiple PDFs into one file.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/merger/pdf-merger" rel="noopener noreferrer"&gt;https://keynou.com/tools/merger/pdf-merger&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reports
&lt;/li&gt;
&lt;li&gt;Documents bundles
&lt;/li&gt;
&lt;li&gt;Client deliverables
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✂️ 5. PDF Splitter
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:4]{index=4}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Extract specific pages from a PDF.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/pdf-splitter" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf-splitter&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sharing selected pages
&lt;/li&gt;
&lt;li&gt;Removing unnecessary sections
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 6. PDF to Excel Converter
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:5]{index=5}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Turn tables into editable spreadsheets.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/pdf/pdf-to-excel" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf/pdf-to-excel&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Data analysis
&lt;/li&gt;
&lt;li&gt;Financial reports
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🖼️ 7. Image to PDF Converter
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:6]{index=6}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Convert images into organized PDF documents.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/image/image-to-pdf" rel="noopener noreferrer"&gt;https://keynou.com/tools/image/image-to-pdf&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Scanned documents
&lt;/li&gt;
&lt;li&gt;Portfolios
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📝 8. Text to PDF
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:7]{index=7}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Quickly create PDFs from raw text.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/pdf/text-to-pdf" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf/text-to-pdf&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Notes
&lt;/li&gt;
&lt;li&gt;Documentation
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔒 9. PDF Security / Encryption
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:8]{index=8}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Protect sensitive documents.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/file-encryptor" rel="noopener noreferrer"&gt;https://keynou.com/tools/file-encryptor&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Confidential files
&lt;/li&gt;
&lt;li&gt;Client data
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧾 10. PDF Editor
&lt;/h2&gt;

&lt;p&gt;::contentReference[oaicite:9]{index=9}&lt;/p&gt;

&lt;h3&gt;
  
  
  Why you need it:
&lt;/h3&gt;

&lt;p&gt;Make quick edits without converting.&lt;/p&gt;

&lt;p&gt;👉 Use: &lt;a href="https://keynou.com/tools/file/document-editor" rel="noopener noreferrer"&gt;https://keynou.com/tools/file/document-editor&lt;/a&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  Best for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minor corrections
&lt;/li&gt;
&lt;li&gt;Quick updates
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  ⚡ Pro Workflow for PDFs
&lt;/h1&gt;

&lt;p&gt;Instead of using tools randomly, follow this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convert (if needed)
&lt;/li&gt;
&lt;li&gt;Edit or extract content
&lt;/li&gt;
&lt;li&gt;Compress file
&lt;/li&gt;
&lt;li&gt;Merge or split
&lt;/li&gt;
&lt;li&gt;Secure before sharing
&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  🚫 Common Mistakes to Avoid
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Converting PDFs multiple times (quality loss)
&lt;/li&gt;
&lt;li&gt;Sending large files without compression
&lt;/li&gt;
&lt;li&gt;Editing without backup
&lt;/li&gt;
&lt;li&gt;Ignoring formatting issues after conversion
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🧠 Final Thoughts
&lt;/h1&gt;

&lt;p&gt;PDFs don’t have to be difficult.&lt;/p&gt;

&lt;p&gt;With the right tools from &lt;strong&gt;keynou.com&lt;/strong&gt;, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;edit faster
&lt;/li&gt;
&lt;li&gt;share easier
&lt;/li&gt;
&lt;li&gt;work smarter
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All without installing anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Start Using These Tools
&lt;/h2&gt;

&lt;p&gt;Explore all PDF tools here:&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://keynou.com/tools" rel="noopener noreferrer"&gt;https://keynou.com/tools&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;Everything is free, fast, and ready to use.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>react</category>
      <category>startup</category>
    </item>
    <item>
      <title>Getting Started with Online Tools</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Tue, 21 Apr 2026 20:55:08 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/getting-started-with-online-tools-1jdh</link>
      <guid>https://dev.to/saifullahusmani/getting-started-with-online-tools-1jdh</guid>
      <description>&lt;p&gt;In today’s fast-paced digital world, productivity isn’t about working more, it’s about working &lt;strong&gt;smarter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Online tools have completely changed how we handle everyday tasks, from converting files to editing media and managing data. Instead of installing heavy software or wasting time on complex workflows, you can now get things done instantly in your browser using &lt;strong&gt;keynou.com&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What Are Online Tools?
&lt;/h2&gt;

&lt;p&gt;Online tools are &lt;strong&gt;browser-based utilities&lt;/strong&gt; that help you perform specific tasks quickly without installing any software.&lt;/p&gt;

&lt;p&gt;You simply:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the tool
&lt;/li&gt;
&lt;li&gt;Upload or input your data
&lt;/li&gt;
&lt;li&gt;Get instant results
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 Explore all tools: &lt;a href="https://keynou.com/tools" rel="noopener noreferrer"&gt;https://keynou.com/tools&lt;/a&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ Why Use Online Tools?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. No Installation Required
&lt;/h3&gt;

&lt;p&gt;Forget downloading large applications. Everything runs directly in your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Instant Results
&lt;/h3&gt;

&lt;p&gt;Most tasks take seconds, whether it's compressing an image or converting a file.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Free and Accessible
&lt;/h3&gt;

&lt;p&gt;With &lt;strong&gt;keynou.com&lt;/strong&gt;, you get access to powerful tools without subscriptions or hidden costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Work Anywhere
&lt;/h3&gt;

&lt;p&gt;All you need is an internet connection, your tools are always available.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Key Categories to Get Started With
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📄 File &amp;amp; Document Tools
&lt;/h3&gt;

&lt;p&gt;::contentReference[oaicite:0]{index=0}&lt;/p&gt;

&lt;p&gt;Handle everyday document tasks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Converting PDFs to Word
&lt;/li&gt;
&lt;li&gt;Compressing large files
&lt;/li&gt;
&lt;li&gt;Merging or editing documents
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/pdf/pdf-to-word" rel="noopener noreferrer"&gt;https://keynou.com/tools/pdf/pdf-to-word&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/compressor/pdf-compressor" rel="noopener noreferrer"&gt;https://keynou.com/tools/compressor/pdf-compressor&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🖼️ Image Tools
&lt;/h3&gt;

&lt;p&gt;::contentReference[oaicite:1]{index=1}&lt;/p&gt;

&lt;p&gt;Perfect for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reducing image size
&lt;/li&gt;
&lt;li&gt;Resizing for social media
&lt;/li&gt;
&lt;li&gt;Converting formats
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/image/image-compressor" rel="noopener noreferrer"&gt;https://keynou.com/tools/image/image-compressor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/image/image-resizer" rel="noopener noreferrer"&gt;https://keynou.com/tools/image/image-resizer&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🎬 Video &amp;amp; Audio Tools
&lt;/h3&gt;

&lt;p&gt;::contentReference[oaicite:2]{index=2}&lt;/p&gt;

&lt;p&gt;Great for content creators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert video formats
&lt;/li&gt;
&lt;li&gt;Compress large files
&lt;/li&gt;
&lt;li&gt;Extract or edit media
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/video/videoConverter" rel="noopener noreferrer"&gt;https://keynou.com/tools/video/videoConverter&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/audio/audio-convertor" rel="noopener noreferrer"&gt;https://keynou.com/tools/audio/audio-convertor&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💻 Developer &amp;amp; Data Tools
&lt;/h3&gt;

&lt;p&gt;::contentReference[oaicite:3]{index=3}&lt;/p&gt;

&lt;p&gt;Useful for developers and analysts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Format JSON
&lt;/li&gt;
&lt;li&gt;Convert CSV to JSON
&lt;/li&gt;
&lt;li&gt;Encode/decode data
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/json/json-convertor" rel="noopener noreferrer"&gt;https://keynou.com/tools/json/json-convertor&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/data/csv-to-json" rel="noopener noreferrer"&gt;https://keynou.com/tools/data/csv-to-json&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚡ Everyday Productivity Tools
&lt;/h3&gt;

&lt;p&gt;::contentReference[oaicite:4]{index=4}&lt;/p&gt;

&lt;p&gt;For quick daily tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate secure passwords
&lt;/li&gt;
&lt;li&gt;Create QR codes
&lt;/li&gt;
&lt;li&gt;Count words or format text
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/security/password-generator" rel="noopener noreferrer"&gt;https://keynou.com/tools/security/password-generator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://keynou.com/tools/misc/word-counter" rel="noopener noreferrer"&gt;https://keynou.com/tools/misc/word-counter&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧠 How to Use Online Tools Effectively
&lt;/h2&gt;

&lt;p&gt;To get the most out of tools on &lt;strong&gt;keynou.com&lt;/strong&gt;, follow this simple workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Identify your task&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
(e.g., convert, compress, edit)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Choose the right tool&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Go directly to the relevant page&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Upload or input data&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Keep files clean and organized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Download results instantly&lt;/strong&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚠️ Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always check output quality after processing
&lt;/li&gt;
&lt;li&gt;Compress large files before sharing
&lt;/li&gt;
&lt;li&gt;Use the correct format for your use case
&lt;/li&gt;
&lt;li&gt;Avoid unnecessary repeated conversions
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔐 Is It Safe?
&lt;/h2&gt;

&lt;p&gt;Yes, online tools on &lt;strong&gt;keynou.com&lt;/strong&gt; are designed with privacy in mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Files are processed quickly
&lt;/li&gt;
&lt;li&gt;No registration required
&lt;/li&gt;
&lt;li&gt;No unnecessary data storage
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚀 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Online tools are no longer just a convenience, they are essential for modern workflows.&lt;/p&gt;

&lt;p&gt;Whether you're a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;student
&lt;/li&gt;
&lt;li&gt;developer
&lt;/li&gt;
&lt;li&gt;content creator
&lt;/li&gt;
&lt;li&gt;professional
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the right tools can save you &lt;strong&gt;hours of time every week&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  👉 Get Started Now
&lt;/h2&gt;

&lt;p&gt;Explore all tools and start simplifying your workflow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://keynou.com/tools" rel="noopener noreferrer"&gt;https://keynou.com/tools&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;No setup. No friction. Just results.&lt;/p&gt;

</description>
      <category>sass</category>
      <category>ai</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Hostinger 20% off</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Wed, 11 Mar 2026 15:10:43 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/hostinger-20-off-1mij</link>
      <guid>https://dev.to/saifullahusmani/hostinger-20-off-1mij</guid>
      <description>&lt;p&gt;Launching a website or SaaS? Get &lt;strong&gt;20% off hosting&lt;/strong&gt; with &lt;strong&gt;Hostinger&lt;/strong&gt; using my link: &lt;a href="https://www.hostinger.com?REFERRALCODE=1SAIF931" rel="noopener noreferrer"&gt;https://www.hostinger.com?REFERRALCODE=1SAIF931&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fast, affordable hosting with free SSL and easy setup. Perfect for startups, developers, and online businesses.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Django Microservices, A Practical Guide</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Sat, 24 Jan 2026 19:46:56 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/django-microservices-a-practical-guide-1b88</link>
      <guid>https://dev.to/saifullahusmani/django-microservices-a-practical-guide-1b88</guid>
      <description>&lt;p&gt;A Django app is monolith, not a microservice, by default.&lt;br&gt;
A microservice is a &lt;strong&gt;separately deployed Django project&lt;/strong&gt; with its own auth boundary.&lt;/p&gt;

&lt;p&gt;Below is the simplest, correct way to do this using &lt;strong&gt;JWT shared between two Django services&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Service 1, Auth Service
&lt;/h2&gt;

&lt;p&gt;This is a standalone Django project whose only job is to issue JWTs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;settings.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DJANGO_SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;same-secret-between-all-microservices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;auth_service/auth.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;

&lt;span class="n"&gt;JWT_ALGORITHM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HS256&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;JWT_EXP_SECONDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;issue_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;iat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;exp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;JWT_EXP_SECONDS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DJANGO_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;algorithm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;JWT_ALGORITHM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;views.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;.auth&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;issue_token&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# assume validated user
&lt;/span&gt;    &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;issue_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This service &lt;strong&gt;only issues jwt tokens&lt;/strong&gt;. When a user sends email and password to login the correct user.&lt;/p&gt;




&lt;h2&gt;
  
  
  Service 2, Business Service
&lt;/h2&gt;

&lt;p&gt;This is a &lt;strong&gt;separate Django project&lt;/strong&gt;, deployed independently.&lt;br&gt;
Its database doesn't have users or auth related stuff.&lt;br&gt;
It only knows how to &lt;strong&gt;read the content of auth service JWT token&lt;/strong&gt; because of same django_secret_key.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;settings.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;DJANGO_SECRET_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;same-secret-between-all-microservices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Custom JWT Middleware
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;middleware.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.conf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JWTAuthMiddleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_response&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;auth_header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;detail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unauthorized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DJANGO_SECRET_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;algorithms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HS256&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExpiredSignatureError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;detail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Token expired&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvalidTokenError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;detail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Register Middleware
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;settings.py&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MIDDLEWARE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;django.middleware.security.SecurityMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;your_app.middleware.JWTAuthMiddleware&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Protected View in Service 2
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;JsonResponse&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;JsonResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Access granted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How the services talk
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Client calls &lt;strong&gt;Auth Service&lt;/strong&gt; → receives JWT&lt;/li&gt;
&lt;li&gt;Client calls &lt;strong&gt;Business Service&lt;/strong&gt; with
&lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Business Service validates token locally&lt;/li&gt;
&lt;li&gt;No shared DB, no shared sessions, no Django apps crossing boundaries&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That separation is what makes it a microservice. Separate apps, separate databases, linked together based on good old keys.&lt;/p&gt;




&lt;h2&gt;
  
  
  The important clarification
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multiple Django apps in one project is &lt;strong&gt;not&lt;/strong&gt; microservices&lt;/li&gt;
&lt;li&gt;One Django project per service is the minimum bar&lt;/li&gt;
&lt;li&gt;Auth must be explicit and stateless&lt;/li&gt;
&lt;li&gt;Token validation happens in every service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the real line between a Django app and a Django microservice.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>React Vs Next</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Mon, 19 Jan 2026 06:06:45 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/choosing-the-right-react-stack-dashboards-with-react-seo-and-e-commerce-with-nextjs-and-da2</link>
      <guid>https://dev.to/saifullahusmani/choosing-the-right-react-stack-dashboards-with-react-seo-and-e-commerce-with-nextjs-and-da2</guid>
      <description>&lt;p&gt;For a long time, I treated React as a hammer.&lt;br&gt;
Every problem looked like a nail.&lt;br&gt;
Dashboards, landing pages, blogs, SEO pages, e-commerce.&lt;br&gt;
Same stack, same patterns, same assumptions.&lt;/p&gt;

&lt;p&gt;That worked, until it didn’t.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 The early mistake
&lt;/h3&gt;

&lt;p&gt;In my early production systems, I built everything as a single React SPA. It felt clean and modern. One codebase, one mental model, fast iteration.&lt;/p&gt;

&lt;p&gt;Then real traffic showed up.&lt;/p&gt;

&lt;p&gt;Marketing pages loaded slowly on mobile.&lt;br&gt;
SEO performance was unpredictable.&lt;br&gt;
Dashboards felt heavy despite being internal tools.&lt;br&gt;
E-commerce pages struggled with crawlability and first paint.&lt;/p&gt;

&lt;p&gt;Nothing was “broken” in isolation. The problem was architectural laziness.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚙️ What production taught me
&lt;/h3&gt;

&lt;p&gt;Dashboards and SEO-sensitive surfaces solve fundamentally different problems.&lt;/p&gt;

&lt;p&gt;For dashboards, I care about interaction density, state complexity, and perceived responsiveness after login. React shines here. Client-side state, aggressive caching, optimistic updates, complex charts. SEO is irrelevant, speed after auth is everything.&lt;/p&gt;

&lt;p&gt;For landing pages, blogs, and e-commerce, the priorities flip. First contentful paint matters. Crawlability matters. Predictable rendering matters. This is where Next.js earned its place in my stack, not because it is trendy, but because it lets me choose rendering intentionally.&lt;/p&gt;

&lt;p&gt;Static generation for programmatic SEO pages.&lt;br&gt;
Server rendering for product and category pages.&lt;br&gt;
Incremental regeneration where content changes slowly but traffic is high.&lt;/p&gt;

&lt;p&gt;Same React mental model, different execution strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚖️ The tradeoffs nobody talks about
&lt;/h3&gt;

&lt;p&gt;This split is not free.&lt;/p&gt;

&lt;p&gt;Two deployment pipelines instead of one.&lt;br&gt;
More opinions in the team about where code should live.&lt;br&gt;
Shared components need discipline or they rot fast.&lt;br&gt;
Developers must understand rendering, not just write JSX.&lt;/p&gt;

&lt;p&gt;But the alternative is worse.&lt;br&gt;
A single stack that optimizes for everything usually optimizes for nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔍 Programmatic SEO at scale
&lt;/h3&gt;

&lt;p&gt;The hardest lessons came from programmatic content.&lt;/p&gt;

&lt;p&gt;Generating thousands of pages is easy. Making them fast, indexable, and maintainable is not.&lt;/p&gt;

&lt;p&gt;I learned to treat content like data. Validate it, cache it, version it. Build guardrails so bad data cannot ship broken pages. Accept that not every page deserves hydration. Sometimes HTML is enough.&lt;/p&gt;

&lt;p&gt;That mindset shift mattered more than any framework choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  📌 What I’d do again, and what I wouldn’t
&lt;/h3&gt;

&lt;p&gt;I would still use React everywhere.&lt;br&gt;
I would not render it the same way everywhere.&lt;/p&gt;

&lt;p&gt;I would design around user intent, not developer convenience.&lt;br&gt;
I would explain these tradeoffs early to non-technical stakeholders, especially marketing and leadership, because performance and SEO are business risks, not frontend details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing thought
&lt;/h3&gt;

&lt;p&gt;Senior engineering, to me, is not about knowing more tools. It is about knowing when not to use the same one twice.&lt;/p&gt;

&lt;p&gt;When your architecture starts matching user behavior instead of developer preference, everything gets calmer. Teams move faster. Metrics improve. Conversations with leadership become simpler.&lt;/p&gt;

&lt;p&gt;That is usually how I know the system is finally growing up.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>It works on my localhost 🔥</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Thu, 15 Jan 2026 19:52:35 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/why-your-code-failed-in-production-1jda</link>
      <guid>https://dev.to/saifullahusmani/why-your-code-failed-in-production-1jda</guid>
      <description>&lt;p&gt;(Difference between code that works and code that scales)&lt;/p&gt;

&lt;p&gt;The most expensive bugs I have shipped were not syntax errors.&lt;br&gt;
They were design decisions that worked perfectly… until they didn’t.&lt;br&gt;
Nothing fails faster than code that was only tested against success.&lt;/p&gt;

&lt;p&gt;I learned this the hard way, not from blogs or courses, but from production incidents at 3 a.m. when dashboards went red and users noticed before we did.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚧 Code that works is easy to celebrate
&lt;/h3&gt;

&lt;p&gt;Early in my career, I was proud of how fast I could ship.&lt;/p&gt;

&lt;p&gt;The feature passed tests.&lt;br&gt;
The API responded quickly on my machine.&lt;br&gt;
The demo impressed stakeholders.&lt;/p&gt;

&lt;p&gt;And for a while, everything looked fine.&lt;/p&gt;

&lt;p&gt;But that code assumed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Low traffic&lt;/li&gt;
&lt;li&gt;Friendly users&lt;/li&gt;
&lt;li&gt;Predictable data&lt;/li&gt;
&lt;li&gt;One happy path&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reality never respects those assumptions.&lt;/p&gt;




&lt;h3&gt;
  
  
  📈 Code that scales is built around failure
&lt;/h3&gt;

&lt;p&gt;The first real scaling incident taught me something uncomfortable.&lt;/p&gt;

&lt;p&gt;The system didn’t crash because of traffic.&lt;br&gt;
It crashed because of contention, retries, locks, timeouts, and cascading failures I had never designed for.&lt;/p&gt;

&lt;p&gt;At scale:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Databases become bottlenecks, not just storage&lt;/li&gt;
&lt;li&gt;Network calls fail silently, then loudly&lt;/li&gt;
&lt;li&gt;Caches lie&lt;/li&gt;
&lt;li&gt;Background jobs pile up&lt;/li&gt;
&lt;li&gt;Small inefficiencies compound into outages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing was “wrong” with the code.&lt;br&gt;
It just wasn’t honest about reality.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚖️ Tradeoffs you only learn in production
&lt;/h3&gt;

&lt;p&gt;Scaling is rarely about perfect architecture. It is about choosing which problems you want to live with.&lt;/p&gt;

&lt;p&gt;I have learned to ask different questions now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this synchronous call worth blocking a request?&lt;/li&gt;
&lt;li&gt;Is strong consistency actually required here?&lt;/li&gt;
&lt;li&gt;What happens if this dependency is slow, not down?&lt;/li&gt;
&lt;li&gt;Can we degrade gracefully instead of failing hard?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the right answer is slower code with fewer surprises.&lt;br&gt;
Sometimes it is duplication over abstraction.&lt;br&gt;
Sometimes it is accepting eventual consistency to protect availability.&lt;/p&gt;

&lt;p&gt;None of those decisions look elegant in isolation.&lt;br&gt;
All of them matter at scale.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 The mindset shift that changed everything
&lt;/h3&gt;

&lt;p&gt;The biggest difference is not technical, it is mental.&lt;/p&gt;

&lt;p&gt;Code that works asks:&lt;br&gt;
“Does this solve the problem?”&lt;/p&gt;

&lt;p&gt;Code that scales asks:&lt;br&gt;
“What happens when this is stressed, misused, partially broken, or operated by someone new at 2 a.m.?”&lt;/p&gt;

&lt;p&gt;That question changes how you log, how you name things, how you design interfaces, and how much you care about operability.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔚 What I optimize for today
&lt;/h3&gt;

&lt;p&gt;I no longer optimize for cleverness or speed of delivery alone.&lt;/p&gt;

&lt;p&gt;I optimize for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictability under load&lt;/li&gt;
&lt;li&gt;Clear failure modes&lt;/li&gt;
&lt;li&gt;Boring reliability&lt;/li&gt;
&lt;li&gt;Systems that are easy to reason about six months later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Scaling is not about writing more complex code.&lt;br&gt;
It is about writing code that tells the truth about the environment it runs in.&lt;/p&gt;

&lt;p&gt;That is the difference I wish I understood earlier.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Make one CRM and sell forever 🤑</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Tue, 13 Jan 2026 13:01:41 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/sell-crm-make-crm-for-every-client-make-crm-core-one-time-and-sell-every-client-with-1525</link>
      <guid>https://dev.to/saifullahusmani/sell-crm-make-crm-for-every-client-make-crm-core-one-time-and-sell-every-client-with-1525</guid>
      <description>&lt;p&gt;For years, I did the “right” thing, or so I thought.&lt;br&gt;
Every new client, a new CRM. New repo. New schema tweaks. New logic.&lt;br&gt;
It felt productive. It looked busy. It was a trap.&lt;/p&gt;

&lt;p&gt;I didn’t learn this from a blog post.&lt;br&gt;
I learned it from production pain, support calls, and my own burnout.&lt;/p&gt;




&lt;h3&gt;
  
  
  🚧 The early mistake: building &lt;em&gt;for&lt;/em&gt; clients, not &lt;em&gt;for scale&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;When a client asked for a CRM, I’d build &lt;em&gt;their&lt;/em&gt; CRM.&lt;/p&gt;

&lt;p&gt;Different flows.&lt;br&gt;
Different permissions.&lt;br&gt;
Different custom fields hard-coded because “this client is special.”&lt;/p&gt;

&lt;p&gt;On paper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast initial delivery&lt;/li&gt;
&lt;li&gt;Happy client&lt;/li&gt;
&lt;li&gt;Clean codebase (for now)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In reality:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5 CRMs → 5 slightly different bugs&lt;/li&gt;
&lt;li&gt;Fixing the same issue 5 times&lt;/li&gt;
&lt;li&gt;Feature requests that couldn’t be shared&lt;/li&gt;
&lt;li&gt;Onboarding a new dev became archaeology&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The worst part?&lt;br&gt;
Every “small change” had a multiplied cost.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 The uncomfortable realization
&lt;/h3&gt;

&lt;p&gt;The problem wasn’t programming speed.&lt;br&gt;
It was &lt;strong&gt;decision duplication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;No-code tools get praised for “speed,” but what they really optimize is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;One core system, many tenants, infinite configurations.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I was doing the opposite:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Infinite systems, tiny differences, zero leverage.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s when it clicked:&lt;br&gt;
&lt;strong&gt;Programming isn’t slow. Rebuilding the same product over and over is.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔄 The pivot: one CRM core, many identities (like inheritance in OOP)
&lt;/h3&gt;

&lt;p&gt;Instead of asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I build this CRM for this client?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I started asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What must &lt;em&gt;never&lt;/em&gt; change across CRMs?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That became the &lt;strong&gt;CRM Core&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users, roles, permissions (policy-driven, not hard-coded)&lt;/li&gt;
&lt;li&gt;Pipelines, stages, activities&lt;/li&gt;
&lt;li&gt;Contacts, companies, deals&lt;/li&gt;
&lt;li&gt;Audit logs, notifications, access rules&lt;/li&gt;
&lt;li&gt;Extensible metadata instead of schema forks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Client-specific needs moved to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Config&lt;/li&gt;
&lt;li&gt;Feature flags&lt;/li&gt;
&lt;li&gt;Branding&lt;/li&gt;
&lt;li&gt;Workflow rules&lt;/li&gt;
&lt;li&gt;Tenant-level permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same engine.&lt;br&gt;
Different paint.&lt;br&gt;
Different defaults.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚖️ Real tradeoffs (not talked about enough)
&lt;/h3&gt;

&lt;p&gt;This wasn’t a magic win.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What got harder:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial architecture took longer&lt;/li&gt;
&lt;li&gt;Over-engineering temptation was real&lt;/li&gt;
&lt;li&gt;“Just for this client” requests needed discipline&lt;/li&gt;
&lt;li&gt;Some clients wanted bad ideas — and now I had to say no&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What got easier (and compound):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bug fixes once, everywhere&lt;/li&gt;
&lt;li&gt;New features became revenue, not cost&lt;/li&gt;
&lt;li&gt;Onboarding a client dropped from weeks to days&lt;/li&gt;
&lt;li&gt;Support became pattern-based, not detective work&lt;/li&gt;
&lt;li&gt;Rebranding was a config change, not a rewrite&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🔧 Lessons I learned the hard way
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;❌ Custom code feels fast until version 3&lt;/li&gt;
&lt;li&gt;❌ DRY across repos is still duplication&lt;/li&gt;
&lt;li&gt;✅ Multi-tenancy is a business decision, not just a technical one&lt;/li&gt;
&lt;li&gt;✅ Config &amp;gt; conditionals&lt;/li&gt;
&lt;li&gt;✅ Saying “no” to one client can say “yes” to ten future ones&lt;/li&gt;
&lt;li&gt;✅ No-code tools don’t beat engineers — &lt;strong&gt;systems thinking does&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧩 The maturity shift
&lt;/h3&gt;

&lt;p&gt;Junior me optimized for &lt;em&gt;delivery&lt;/em&gt;.&lt;br&gt;
Mid-level me optimized for &lt;em&gt;code quality&lt;/em&gt;.&lt;br&gt;
Senior me optimizes for &lt;strong&gt;leverage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Leverage in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;Maintenance cost&lt;/li&gt;
&lt;li&gt;Team sanity&lt;/li&gt;
&lt;li&gt;Business scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you feel the difference, you can’t unsee it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Closing thought
&lt;/h3&gt;

&lt;p&gt;If you’re rebuilding the same product again and again, you’re not moving fast, you’re running in circles.&lt;/p&gt;

&lt;p&gt;Build a core.&lt;br&gt;
Protect it.&lt;br&gt;
Let everything else be replaceable.&lt;/p&gt;

&lt;p&gt;That’s not over-engineering.&lt;br&gt;
That’s respect for your future self.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>EC2 (single instance with db and redis and all) vs EC2 + RDS + MemoryDB, ECS/EKS (docker-based approach): when and why</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Sun, 11 Jan 2026 22:42:16 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/ec2-single-instance-with-db-and-redis-and-all-vs-ec2-rds-memorydb-ecseks-docker-based-78b</link>
      <guid>https://dev.to/saifullahusmani/ec2-single-instance-with-db-and-redis-and-all-vs-ec2-rds-memorydb-ecseks-docker-based-78b</guid>
      <description>&lt;p&gt;Early in my career, I thought architecture was about picking the &lt;em&gt;right&lt;/em&gt; stack.&lt;br&gt;
Years later, after a few outages, 3 a.m. rollbacks, and uncomfortable postmortems, I learned it’s really about picking the &lt;em&gt;right compromise&lt;/em&gt; for where you are &lt;strong&gt;right now&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ve run production systems on a single EC2 box with everything installed.&lt;br&gt;
I’ve also migrated those same systems, sometimes painfully, into RDS, MemoryDB, ECS, and later EKS.&lt;/p&gt;

&lt;p&gt;Both worked.&lt;br&gt;
Both failed.&lt;br&gt;
Here’s what experience taught me.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧱 Phase 1: The “Everything on One EC2” Reality
&lt;/h3&gt;

&lt;p&gt;Yes, I’ve done it.&lt;br&gt;
App server, PostgreSQL/MySQL, Redis, background workers, all on one EC2 instance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it made sense at the time:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One bill, one server, one mental model&lt;/li&gt;
&lt;li&gt;No network latency between app, DB, and cache&lt;/li&gt;
&lt;li&gt;Fastest way to ship when the team is small&lt;/li&gt;
&lt;li&gt;Debugging was… oddly comforting (SSH into one box)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What broke first in production:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disk I/O contention during peak writes&lt;/li&gt;
&lt;li&gt;Memory pressure: Redis vs DB vs app fighting silently&lt;/li&gt;
&lt;li&gt;“Just restart the instance” becoming a risky decision&lt;/li&gt;
&lt;li&gt;Backups and upgrades turning into manual rituals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The biggest issue wasn’t uptime.&lt;br&gt;
It was &lt;strong&gt;blast radius&lt;/strong&gt;.&lt;br&gt;
Every change felt dangerous because everything shared the same failure domain.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔁 Phase 2: EC2 + RDS + MemoryDB (Decoupling Painfully, But Intentionally)
&lt;/h3&gt;

&lt;p&gt;Moving the database and cache out felt expensive at first.&lt;br&gt;
It &lt;em&gt;was&lt;/em&gt; more expensive. But it was also the turning point.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What improved immediately:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predictable performance (especially under load)&lt;/li&gt;
&lt;li&gt;Clear ownership of resources&lt;/li&gt;
&lt;li&gt;Backups and failover stopped being “someone’s script”&lt;/li&gt;
&lt;li&gt;App deploys no longer risked data integrity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The tradeoffs people don’t talk about:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network latency is real and measurable&lt;/li&gt;
&lt;li&gt;Misconfigured security groups can take you down faster than bad code&lt;/li&gt;
&lt;li&gt;You lose the illusion of simplicity, now you need observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here’s the thing:&lt;br&gt;
Once traffic, data, or business expectations grow, &lt;strong&gt;managed services buy you time and safety&lt;/strong&gt;, not just convenience.&lt;/p&gt;

&lt;p&gt;This is usually where teams &lt;em&gt;should&lt;/em&gt; be, even if they resist it.&lt;/p&gt;




&lt;h3&gt;
  
  
  📦 Phase 3: ECS / EKS (Containers Don’t Fix Architecture)
&lt;/h3&gt;

&lt;p&gt;Containers didn’t solve my scaling problems.&lt;br&gt;
They solved my &lt;strong&gt;operational discipline problems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Docker + ECS/EKS started making sense:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple environments stopped drifting&lt;/li&gt;
&lt;li&gt;Rollbacks became boring (a good thing)&lt;/li&gt;
&lt;li&gt;Horizontal scaling stopped being theoretical&lt;/li&gt;
&lt;li&gt;Teams could work in parallel without stepping on each other&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I underestimated early on:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes adds cognitive load before it adds value&lt;/li&gt;
&lt;li&gt;Bad architecture in containers is still bad architecture&lt;/li&gt;
&lt;li&gt;You need maturity in monitoring, logging, and alerts first&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ECS worked well when the team wanted guardrails.&lt;br&gt;
EKS made sense only when the organization had &lt;strong&gt;strong platform ownership&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Containers are a multiplier.&lt;br&gt;
They multiply clarity or chaos.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚖️ What Experience Taught Me (The Non-Obvious Lessons)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single EC2 is not “wrong”&lt;/strong&gt;, it’s often the most honest starting point&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Managed services trade money for sleep&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decoupling is about failure isolation, not fashion&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Orchestration should follow discipline, not precede it&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The costliest system is the one your team can’t reason about at 2 a.m.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Architecture maturity is less about scale and more about &lt;strong&gt;operational confidence&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 The Real Question I Ask Now
&lt;/h3&gt;

&lt;p&gt;Not “Is this scalable?”&lt;br&gt;
But:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“What will break first, and how hard will it be to recover?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That answer not hype, not trends should drive your choice.&lt;/p&gt;




&lt;p&gt;If there’s one thing years in production taught me, it’s this:&lt;br&gt;
&lt;strong&gt;Good architecture grows with the team, not ahead of it.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>ReactJs can kill you in production</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Sun, 11 Jan 2026 13:05:00 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/how-poor-reactjs-code-quietly-burns-you-in-production-1n76</link>
      <guid>https://dev.to/saifullahusmani/how-poor-reactjs-code-quietly-burns-you-in-production-1n76</guid>
      <description>&lt;p&gt;Latency creeps in, bugs multiply, teams lose confidence, and “small changes” start taking days instead of hours.&lt;/p&gt;

&lt;p&gt;This isn’t about React being bad.&lt;br&gt;
It’s about how poor React decisions compound over time.&lt;/p&gt;

&lt;p&gt;🚧 What actually went wrong in production&lt;br&gt;
Early on, the app felt fast. Features shipped quickly. Everyone was happy.&lt;br&gt;
Then scale arrived.&lt;br&gt;
User count grew&lt;br&gt;
API traffic spiked&lt;br&gt;
UI complexity increased&lt;br&gt;
Multiple engineers touched the same code paths&lt;br&gt;
That’s when cracks turned into outages.&lt;br&gt;
Not because of one big mistake, but because of many small, ignored ones.&lt;/p&gt;

&lt;p&gt;🔁 Re-rendering without discipline&lt;br&gt;
Components re-rendering on every keystroke&lt;br&gt;
Props changing shape every render&lt;br&gt;
On lower-end devices and real networks? Painful.&lt;/p&gt;

&lt;p&gt;Lesson: Rendering is not free. React makes it easy to re-render, not cheap.&lt;/p&gt;

&lt;p&gt;⏱️ No debouncing, no throttling, no mercy&lt;br&gt;
Search inputs hitting APIs on every keypress.&lt;br&gt;
Scroll events firing dozens of times per second.&lt;br&gt;
The backend started looking like the problem.&lt;br&gt;
It wasn’t.&lt;/p&gt;

&lt;p&gt;Lesson: Frontend inefficiency scales faster than backend cost.&lt;/p&gt;

&lt;p&gt;🧠 State management without a strategy&lt;br&gt;
No single mental model.&lt;/p&gt;

&lt;p&gt;Bug fixes required tracing state across five layers of components.&lt;br&gt;
Lesson: State chaos doesn’t show up in demos — it shows up during incidents.&lt;/p&gt;

&lt;p&gt;🌗 No theming, no single source of truth&lt;br&gt;
Hardcoded colors. Inline styles. Repeated constants.&lt;br&gt;
When branding changes came in, it turned into a multi-day refactor.&lt;/p&gt;

&lt;p&gt;Lesson: If a value appears in more than one place, it’s already a liability.&lt;/p&gt;

&lt;p&gt;🔌 API calls scattered everywhere&lt;br&gt;
Every component knew how to talk to the backend.&lt;br&gt;
Different error handling. Different retries. Different headers.&lt;br&gt;
When auth logic changed, the blast radius was massive.&lt;/p&gt;

&lt;p&gt;Lesson: No single point of change means every change is risky.&lt;/p&gt;

&lt;p&gt;🧱 File structure that doesn’t scale&lt;br&gt;
Flat folders. No boundaries. No ownership.&lt;br&gt;
New engineers took weeks to become productive.&lt;br&gt;
Senior engineers became bottlenecks.&lt;br&gt;
Lesson: File structure is an architecture decision, not a formatting preference.&lt;/p&gt;

&lt;p&gt;📦 No code splitting, no lazy loading&lt;br&gt;
The initial bundle kept growing.&lt;br&gt;
Users felt it before metrics did.&lt;br&gt;
Lesson: Performance debt compounds invisibly, until users leave.&lt;/p&gt;

&lt;p&gt;🧩 The real mistake&lt;br&gt;
Lack of planning for scale, assuming React would “handle it” later.&lt;br&gt;
React gives you enough rope to hang your product if you’re careless.&lt;/p&gt;

&lt;p&gt;🧠 What I do differently now&lt;br&gt;
Treat rendering cost as a first-class concern&lt;br&gt;
Design state flow before writing components&lt;br&gt;
Centralize API interaction aggressively&lt;br&gt;
Plan file structure for future teams, not current comfort&lt;br&gt;
Optimize for change, not just delivery speed&lt;br&gt;
This isn’t over-engineering.&lt;br&gt;
It’s respect for production.&lt;/p&gt;

&lt;p&gt;Final thought&lt;br&gt;
Most frontend failures are labeled as “performance issues” or “React problems.”&lt;br&gt;
In reality, they’re engineering maturity problems.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Elasticsearch - How I failed when I needed fast searching</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Sat, 10 Jan 2026 11:26:00 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/why-using-elasticsearch-was-bad-because-i-needed-real-time-data-retrieval-not-just-fast-searching-1cn8</link>
      <guid>https://dev.to/saifullahusmani/why-using-elasticsearch-was-bad-because-i-needed-real-time-data-retrieval-not-just-fast-searching-1cn8</guid>
      <description>&lt;p&gt;For a long time, I thought Elasticsearch was the obvious answer.&lt;br&gt;
It was fast. It scaled. Everyone I respected was using it.&lt;br&gt;
So when our system started to feel slow, I added Elasticsearch without hesitation.&lt;/p&gt;

&lt;p&gt;That decision worked… until it didn’t.&lt;br&gt;
🚧 The problem I was actually solving&lt;br&gt;
In production, our pain wasn’t search speed.&lt;br&gt;
It was real-time correctness.&lt;/p&gt;

&lt;p&gt;We had workflows where:&lt;br&gt;
A user action needed to be reflected immediately&lt;br&gt;
State changes had to be visible within milliseconds&lt;br&gt;
“Eventually consistent” was not good enough to explain to customers or support teams&lt;/p&gt;

&lt;p&gt;But at the time, I framed the problem incorrectly:&lt;br&gt;
“Queries are slow → add Elasticsearch”&lt;/p&gt;

&lt;p&gt;That framing cost us months.&lt;/p&gt;

&lt;p&gt;🔍 What went wrong at scale&lt;br&gt;
Elasticsearch did exactly what it promises:&lt;br&gt;
fast, distributed search over indexed data.&lt;/p&gt;

&lt;p&gt;What it does not promise:&lt;br&gt;
Strong real-time guarantees&lt;br&gt;
Immediate consistency after writes&lt;br&gt;
Acting as a primary data source for transactional flows&lt;/p&gt;

&lt;p&gt;In real production traffic, we started seeing:&lt;br&gt;
Recently updated records missing from results&lt;br&gt;
Edge cases where writes succeeded but reads lagged&lt;br&gt;
Complex retry and refresh logic creeping into application code&lt;/p&gt;

&lt;p&gt;Every bug was “rare”.&lt;br&gt;
Together, they were constant.&lt;/p&gt;

&lt;p&gt;Non-technical stakeholders didn’t care why it happened.&lt;br&gt;
They just saw data that felt unreliable.&lt;/p&gt;

&lt;p&gt;⚖️ The tradeoff I underestimated&lt;br&gt;
Elasticsearch trades correctness now for performance at scale.&lt;/p&gt;

&lt;p&gt;We needed:&lt;br&gt;
Predictable reads after writes&lt;/p&gt;

&lt;p&gt;🧠 The lesson that stuck with me&lt;br&gt;
The mistake wasn’t using Elasticsearch.&lt;br&gt;
The mistake was using it to compensate for a poorly defined problem.&lt;br&gt;
Fast search ≠ real-time data retrieval&lt;br&gt;
Indexing ≠ state management&lt;br&gt;
Scalability ≠ correctness&lt;br&gt;
Once we re-centered the architecture around:&lt;br&gt;
A primary, strongly consistent data store&lt;br&gt;
Clear read/write paths&lt;br&gt;
Search used only where search made sense&lt;br&gt;
The system became calmer.&lt;br&gt;
Incidents dropped.&lt;br&gt;
Engineers slept better.&lt;br&gt;
🌱 How this changed how I design systems&lt;br&gt;
Today, I’m much slower to introduce “powerful” infrastructure.&lt;br&gt;
Before adding anything new, I ask:&lt;br&gt;
What guarantee does this system give me?&lt;br&gt;
What guarantee does it explicitly not give?&lt;br&gt;
What failure will I be debugging six months from now?&lt;br&gt;
Most production pain doesn’t come from lack of tools.&lt;br&gt;
It comes from misaligned guarantees.&lt;br&gt;
Closing thought&lt;br&gt;
Elasticsearch is an excellent tool.&lt;br&gt;
It just wasn’t the right one for a problem that required trust, not speed.&lt;br&gt;
Experience has taught me this:&lt;br&gt;
Architectural maturity isn’t about knowing more technologies — it’s about knowing when not to use them.&lt;br&gt;
That lesson only comes from shipping, breaking things, and owning the consequences.&lt;/p&gt;

&lt;h1&gt;
  
  
  SeniorSoftwareEngineer
&lt;/h1&gt;

&lt;h1&gt;
  
  
  StaffEngineer
&lt;/h1&gt;

&lt;h1&gt;
  
  
  EngineeringLeadership
&lt;/h1&gt;

&lt;h1&gt;
  
  
  TechnicalDecisionMaking
&lt;/h1&gt;

&lt;h1&gt;
  
  
  SystemOwnership
&lt;/h1&gt;

&lt;h1&gt;
  
  
  BackendEngineering
&lt;/h1&gt;

&lt;h1&gt;
  
  
  SystemDesign
&lt;/h1&gt;

&lt;h1&gt;
  
  
  ScalableSystems
&lt;/h1&gt;

&lt;h1&gt;
  
  
  DistributedSystems
&lt;/h1&gt;

&lt;h1&gt;
  
  
  ProductionExperience
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>beginners</category>
      <category>career</category>
    </item>
    <item>
      <title>Redis overdose</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Fri, 09 Jan 2026 11:25:49 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/how-overusing-redis-almost-killed-our-project-at-scale-5h2d</link>
      <guid>https://dev.to/saifullahusmani/how-overusing-redis-almost-killed-our-project-at-scale-5h2d</guid>
      <description>&lt;p&gt;For a long time, Redis felt like a silver bullet.&lt;br&gt;
 Need speed? Redis.&lt;br&gt;
 Need caching? Redis.&lt;br&gt;
 Need queues, rate-limiting, sessions, feature flags? Redis everywhere.&lt;/p&gt;

&lt;p&gt;I’ve personally made that mistake and paid for it later at scale.&lt;/p&gt;

&lt;p&gt;In the beginning, Redis is amazing:&lt;br&gt;
Sub-millisecond reads&lt;br&gt;
Simple data structures&lt;br&gt;
Easy to deploy&lt;br&gt;
Easy to justify&lt;/p&gt;

&lt;p&gt;We started caching everything:&lt;br&gt;
Auth sessions&lt;br&gt;
API responses&lt;br&gt;
Database query results&lt;br&gt;
Counters&lt;br&gt;
Background job states&lt;br&gt;
Even business logic flags&lt;br&gt;
Performance skyrocketed.&lt;br&gt;
The mistake wasn’t using Redis.&lt;/p&gt;

&lt;p&gt;The mistake was making Redis a core dependency for everything.&lt;/p&gt;

&lt;p&gt;💥 What Broke at Scale&lt;br&gt;
As traffic grew, Redis slowly turned from a helper into a single point of failure.&lt;/p&gt;

&lt;p&gt;Here’s what started happening:&lt;br&gt;
1️⃣ Redis Became Our “Second Database”&lt;br&gt;
Instead of being a cache, Redis became stateful infrastructure:&lt;br&gt;
Critical data existed only in Redis&lt;br&gt;
Expiration bugs caused silent data loss&lt;br&gt;
Cold restarts created cascading failures&lt;br&gt;
At that point, Redis outages weren’t “performance issues” they were production incidents.&lt;/p&gt;

&lt;p&gt;2️⃣ Latency Looked Great, Until Throughput Collapsed&lt;br&gt;
This is something many teams miss:&lt;br&gt;
Low latency ≠ High throughput&lt;br&gt;
Redis can respond in microseconds, but:&lt;br&gt;
Single-threaded command execution&lt;br&gt;
Blocking commands (KEYS, large LRANGE, big Lua scripts)&lt;br&gt;
Huge keyspaces with poor eviction policies&lt;/p&gt;

&lt;p&gt;At scale:&lt;br&gt;
P99 latency exploded&lt;br&gt;
CPU maxed out&lt;br&gt;
Network bandwidth became the bottleneck&lt;br&gt;
Timeouts started propagating to APIs&lt;br&gt;
Redis didn’t slow down — everything around it did.&lt;/p&gt;

&lt;p&gt;3️⃣ We Used Redis Where the Database Was Better&lt;br&gt;
Some data:&lt;br&gt;
Needed strong consistency&lt;br&gt;
Needed transactions&lt;br&gt;
Needed relational integrity&lt;/p&gt;

&lt;p&gt;But Redis was faster, so we used it anyway.&lt;br&gt;
That led to:&lt;br&gt;
Data mismatch between DB and cache&lt;br&gt;
Complex cache invalidation logic&lt;br&gt;
Hard-to-debug race conditions&lt;/p&gt;

&lt;p&gt;At some point, the “performance optimization” was costing more engineering time than it saved.&lt;/p&gt;

&lt;p&gt;🧯 The Turning Point: Redis Is a Tool, Not a Crutch&lt;br&gt;
The real lesson wasn’t “Redis is bad”.&lt;br&gt;
The lesson was:&lt;br&gt;
Redis must be intentionally limited in responsibility.&lt;/p&gt;

&lt;p&gt;We redefined Redis as:&lt;br&gt;
A performance layer&lt;br&gt;
Not a source of truth&lt;br&gt;
Not a workflow engine&lt;br&gt;
Not a business logic store&lt;br&gt;
That mindset shift changed everything.&lt;/p&gt;

&lt;p&gt;☁️ Hosting Redis Properly on AWS: MemoryDB vs Self-Managed&lt;br&gt;
After multiple painful incidents, we moved away from self-managed Redis.&lt;/p&gt;

&lt;p&gt;Why AWS MemoryDB?&lt;br&gt;
Key reasons:&lt;br&gt;
Multi-AZ with transactional durability&lt;br&gt;
Redis-compatible but designed for high availability&lt;br&gt;
Faster failover&lt;br&gt;
No manual replication hell&lt;/p&gt;

&lt;p&gt;Yes, it costs more.&lt;br&gt;
But outages cost far more.&lt;/p&gt;

&lt;p&gt;⚖️ Latency vs Throughput: The Tradeoff That Matters&lt;br&gt;
This is the part most blogs skip.&lt;br&gt;
Latency&lt;br&gt;
Redis excels at single-key reads&lt;br&gt;
Network placement matters more than instance size&lt;/p&gt;

&lt;p&gt;Throughput&lt;br&gt;
Sharding is mandatory at scale&lt;br&gt;
Bigger instances ≠ linear throughput&lt;br&gt;
Avoid large payloads&lt;/p&gt;

&lt;p&gt;Rule I live by now:&lt;br&gt;
If Redis needs vertical scaling, the design is already wrong.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>softwareengineering</category>
      <category>beginners</category>
    </item>
    <item>
      <title>EC2 and Django - Restart kills the server</title>
      <dc:creator>Saif Ullah Usmani</dc:creator>
      <pubDate>Fri, 09 Jan 2026 11:10:04 +0000</pubDate>
      <link>https://dev.to/saifullahusmani/how-running-a-single-ec2-with-just-gunicorn-silently-capped-my-app-and-what-it-taught-me-about-1m17</link>
      <guid>https://dev.to/saifullahusmani/how-running-a-single-ec2-with-just-gunicorn-silently-capped-my-app-and-what-it-taught-me-about-1m17</guid>
      <description>&lt;p&gt;For a long time, my backend looked healthy.&lt;/p&gt;

&lt;p&gt;CPU wasn’t maxed. Memory wasn’t fully used.&lt;/p&gt;

&lt;p&gt;Yet users were getting slow responses… and deployments felt risky.&lt;/p&gt;

&lt;p&gt;That was my first real lesson:&lt;/p&gt;

&lt;p&gt;Infrastructure can fail you quietly before it fails loudly.&lt;/p&gt;

&lt;p&gt;🚧 The setup that worked… until it didn’t&lt;/p&gt;

&lt;p&gt;I was hosting a production Django app on a single EC2 instance, running behind Gunicorn.&lt;/p&gt;

&lt;p&gt;On paper, the instance had enough RAM and decent specs.&lt;/p&gt;

&lt;p&gt;In reality, the application never came close to using what I was paying for.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because Gunicorn doesn’t automatically scale with your instance.&lt;/p&gt;

&lt;p&gt;It only uses what you explicitly allow it to use.&lt;/p&gt;

&lt;p&gt;I had:&lt;/p&gt;

&lt;p&gt;One Gunicorn service&lt;/p&gt;

&lt;p&gt;A small number of workers&lt;/p&gt;

&lt;p&gt;One port&lt;/p&gt;

&lt;p&gt;No real load balancing&lt;/p&gt;

&lt;p&gt;Restart-based deployments&lt;/p&gt;

&lt;p&gt;It worked fine for early traffic.&lt;/p&gt;

&lt;p&gt;At scale, it became a bottleneck disguised as stability.&lt;/p&gt;

&lt;p&gt;🧠 The hidden constraint: workers and memory&lt;/p&gt;

&lt;p&gt;Here’s the part many teams learn the hard way:&lt;/p&gt;

&lt;p&gt;Each Gunicorn worker is a separate process&lt;/p&gt;

&lt;p&gt;Each process has its own memory ceiling&lt;/p&gt;

&lt;p&gt;If you under-provision workers, your app can’t consume available RAM&lt;/p&gt;

&lt;p&gt;If you over-provision blindly, you’ll trigger OOM kills&lt;/p&gt;

&lt;p&gt;So even though EC2 showed free memory, my app couldn’t use it.&lt;/p&gt;

&lt;p&gt;The fix wasn’t “bigger EC2”.&lt;/p&gt;

&lt;p&gt;The fix was intentional worker strategy.&lt;/p&gt;

&lt;p&gt;I learned to:&lt;/p&gt;

&lt;p&gt;Size workers based on RAM, not guesses&lt;/p&gt;

&lt;p&gt;Understand sync vs async workers&lt;/p&gt;

&lt;p&gt;Treat Gunicorn config as capacity planning, not boilerplate&lt;/p&gt;

&lt;p&gt;⚙️ Why gevent changed the game for I/O-heavy traffic&lt;/p&gt;

&lt;p&gt;A big part of our load wasn’t CPU-heavy.&lt;/p&gt;

&lt;p&gt;It was:&lt;/p&gt;

&lt;p&gt;API calls&lt;/p&gt;

&lt;p&gt;DB waits&lt;/p&gt;

&lt;p&gt;Network I/O&lt;/p&gt;

&lt;p&gt;External services&lt;/p&gt;

&lt;p&gt;Classic sync workers were wasting time waiting.&lt;/p&gt;

&lt;p&gt;Switching to gevent wasn’t about “multithreading hype”.&lt;/p&gt;

&lt;p&gt;It was about concurrency efficiency.&lt;/p&gt;

&lt;p&gt;With gevent:&lt;/p&gt;

&lt;p&gt;One worker could handle many concurrent requests&lt;/p&gt;

&lt;p&gt;Memory usage became more predictable&lt;/p&gt;

&lt;p&gt;Latency improved without throwing more hardware at the problem&lt;/p&gt;

&lt;p&gt;Not a silver bullet, but the right tool for the workload.&lt;/p&gt;

&lt;p&gt;🔁 Zero-downtime updates: ports &amp;gt; restarts&lt;/p&gt;

&lt;p&gt;The moment traffic grows, this becomes non-negotiable.&lt;/p&gt;

&lt;p&gt;Restarting Gunicorn to deploy meant:&lt;/p&gt;

&lt;p&gt;Dropped connections&lt;/p&gt;

&lt;p&gt;Failed requests&lt;/p&gt;

&lt;p&gt;Nervous releases&lt;/p&gt;

&lt;p&gt;So I moved to:&lt;/p&gt;

&lt;p&gt;Running multiple Gunicorn instances on different ports&lt;/p&gt;

&lt;p&gt;Using Nginx as a reverse proxy&lt;/p&gt;

&lt;p&gt;Gradually shifting traffic between ports during deploys&lt;/p&gt;

&lt;p&gt;This gave me:&lt;/p&gt;

&lt;p&gt;Zero-downtime updates&lt;/p&gt;

&lt;p&gt;Rollbacks without panic&lt;/p&gt;

&lt;p&gt;Confidence during releases&lt;/p&gt;

&lt;p&gt;It wasn’t fancy.&lt;/p&gt;

&lt;p&gt;It was operational maturity.&lt;/p&gt;

&lt;p&gt;⚖️ Tradeoffs I had to accept&lt;/p&gt;

&lt;p&gt;This setup isn’t “free”:&lt;/p&gt;

&lt;p&gt;More ports = more ops discipline&lt;/p&gt;

&lt;p&gt;Worker tuning requires monitoring, not guesses&lt;/p&gt;

&lt;p&gt;gevent needs code that plays nicely with async I/O&lt;/p&gt;

&lt;p&gt;You must understand your traffic patterns&lt;/p&gt;

&lt;p&gt;But the upside?&lt;/p&gt;

&lt;p&gt;Full utilization of EC2 specs&lt;/p&gt;

&lt;p&gt;Predictable scaling&lt;/p&gt;

&lt;p&gt;Fewer production surprises&lt;/p&gt;

&lt;p&gt;Cleaner upgrade paths later (ECS, Kubernetes, etc.)&lt;/p&gt;

&lt;p&gt;📌 What this experience taught me&lt;/p&gt;

&lt;p&gt;Scaling is not about adding resources, it’s about unlocking the ones you already have&lt;/p&gt;

&lt;p&gt;Defaults are for demos, not production&lt;/p&gt;

&lt;p&gt;Memory, workers, and concurrency are architectural decisions&lt;/p&gt;

&lt;p&gt;Stability comes from understanding, not tooling&lt;/p&gt;

&lt;p&gt;Most importantly:&lt;/p&gt;

&lt;p&gt;Senior engineering isn’t about knowing more tools.&lt;/p&gt;

&lt;p&gt;It’s about knowing why things break quietly.&lt;/p&gt;

&lt;p&gt;If you’re running production workloads and things feel “fine but fragile”,&lt;/p&gt;

&lt;p&gt;look closely the ceiling might already be there.&lt;/p&gt;

&lt;p&gt;#SeniorSoftwareEngineer #BackendEngineering #Django #PythonEngineering&lt;/p&gt;

&lt;p&gt;#CloudArchitecture #AWS #ProductionSystems #ScalableSystems&lt;/p&gt;

&lt;p&gt;#EngineeringLeadership #HiringEngineers&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>devops</category>
      <category>python</category>
    </item>
  </channel>
</rss>
