<?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: Popoola Temilorun</title>
    <description>The latest articles on DEV Community by Popoola Temilorun (@popthemy).</description>
    <link>https://dev.to/popthemy</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%2F2521880%2F98fc7bc0-43f7-4049-b6af-e60bfdbad04e.jpg</url>
      <title>DEV Community: Popoola Temilorun</title>
      <link>https://dev.to/popthemy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/popthemy"/>
    <language>en</language>
    <item>
      <title>How I Safely Added New Fields to My Django API Without Breaking Existing Users (Inboxit Case Study)</title>
      <dc:creator>Popoola Temilorun</dc:creator>
      <pubDate>Sun, 05 Apr 2026 17:36:25 +0000</pubDate>
      <link>https://dev.to/popthemy/how-i-safely-added-new-fields-to-my-django-api-without-breaking-existing-users-inboxit-case-study-5489</link>
      <guid>https://dev.to/popthemy/how-i-safely-added-new-fields-to-my-django-api-without-breaking-existing-users-inboxit-case-study-5489</guid>
      <description>&lt;p&gt;While building &lt;strong&gt;Inboxit&lt;/strong&gt; a plug-and-play tool that forwards website form submissions to email, Slack, or WhatsApp, I needed to add new fields and change serializers to support more features.&lt;/p&gt;

&lt;p&gt;The API was already live in production with real users. Changing models and serializers risked breaking existing integrations.&lt;/p&gt;

&lt;p&gt;Here’s exactly how I handled it using the &lt;strong&gt;Expand-Contract&lt;/strong&gt; pattern and API versioning.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Situation
&lt;/h3&gt;

&lt;p&gt;I had to add new fields to the main model. At the same time, I wanted to improve the response structure.&lt;/p&gt;

&lt;p&gt;If I just updated the existing serializer, all current integrations would break.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Approach: API Versioning + Expand-Contract
&lt;/h3&gt;

&lt;p&gt;I decided to introduce &lt;strong&gt;v2&lt;/strong&gt; while keeping &lt;strong&gt;v1&lt;/strong&gt; fully functional.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 1: Expand
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Added the new fields to the Django model (kept the old fields intact).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what the model looked like after adding the new fields:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgkxrpiqze873nmgpcuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgkxrpiqze873nmgpcuq.png" alt="Model with additional fields" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Versioning in URLs
&lt;/h4&gt;

&lt;p&gt;I set up URL versioning so both versions could coexist:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# urls.py
&lt;/span&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v1/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inboxit.api.v1.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;   &lt;span class="c1"&gt;# Old version (still active)
&lt;/span&gt;    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;api/v2/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inboxit.api.v2.urls&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;   &lt;span class="c1"&gt;# New version
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Old clients continue using &lt;code&gt;/api/v1/&lt;/code&gt; without any change.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 3: Migration &amp;amp; Contract Phase
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Updated code to support both versions where needed.&lt;/li&gt;
&lt;li&gt;Added logging to track which version clients were using.&lt;/li&gt;
&lt;li&gt;Once most traffic moved to v2, I’ll fully deprecate v1 with proper notice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Lessons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Never modify a live API in place if users depend on it.&lt;/li&gt;
&lt;li&gt;Use versioning early (&lt;code&gt;/api/v1/&lt;/code&gt;, &lt;code&gt;/api/v2/&lt;/code&gt;) to give yourself room to evolve without affecting integrations.&lt;/li&gt;
&lt;li&gt;The Expand-Contract pattern (add new → migrate → remove old) prevents painful rollbacks.&lt;/li&gt;
&lt;li&gt;Always communicate deprecation timelines to users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach let me add new features to Inboxit without disrupting existing integrations.&lt;/p&gt;

&lt;p&gt;Have you had to version an API in production?&lt;br&gt;&lt;br&gt;
What strategy worked best for you — URL versioning, header-based, or something else?&lt;/p&gt;

&lt;p&gt;I’d love to hear your experiences in the comments 😎😎.&lt;/p&gt;

</description>
      <category>apiversioning</category>
      <category>backend</category>
      <category>djangorestframework</category>
      <category>python</category>
    </item>
    <item>
      <title>🔐 Managing Multiple GitHub Accounts with SSH: Personal &amp; Work Setup Guide</title>
      <dc:creator>Popoola Temilorun</dc:creator>
      <pubDate>Fri, 06 Jun 2025 20:16:27 +0000</pubDate>
      <link>https://dev.to/popthemy/managing-multiple-github-accounts-with-ssh-personal-work-setup-guide-4nje</link>
      <guid>https://dev.to/popthemy/managing-multiple-github-accounts-with-ssh-personal-work-setup-guide-4nje</guid>
      <description>&lt;p&gt;If you've ever struggled to juggle your personal and work GitHub accounts on the same machine, this guide is for you.&lt;/p&gt;

&lt;p&gt;In this step-by-step tutorial, you'll learn how to:&lt;/p&gt;

&lt;p&gt;✅ Generate SSH keys for different GitHub accounts&lt;br&gt;
✅ Configure SSH with aliases for each identity&lt;br&gt;
✅ Clone repositories using SSH without constant authentication issues&lt;/p&gt;

&lt;p&gt;Let’s dive in 👇&lt;/p&gt;


&lt;h2&gt;
  
  
  1. Generate SSH Keys for Personal and Work GitHub Accounts
&lt;/h2&gt;

&lt;p&gt;Start by creating two separate SSH keys—one for each GitHub account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Personal GitHub account&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_personal_email@example.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ed25519 

&lt;span class="c"&gt;# Work GitHub account&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your_work_email@example.com"&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_rsa_work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;📝 &lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;-f&lt;/code&gt; flag specifies the filename.&lt;/li&gt;
&lt;li&gt;Use meaningful filenames like &lt;code&gt;id_ed25519&lt;/code&gt; and &lt;code&gt;id_rsa_work&lt;/code&gt; for clarity.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Add Your Public Keys to GitHub
&lt;/h2&gt;

&lt;p&gt;Copy the contents of each public key and add them to their respective GitHub accounts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Display the public key&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519.pub      &lt;span class="c"&gt;# Personal&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa_work.pub     &lt;span class="c"&gt;# Work&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your &lt;strong&gt;GitHub Settings &amp;gt; SSH and GPG keys&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"New SSH Key"&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Paste the key content and save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzkpt11uhrd7e4fo0qz0t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzkpt11uhrd7e4fo0qz0t.jpg" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;br&gt;
Repeat this process for both personal and work accounts.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Configure the SSH Config File for Multiple Identities
&lt;/h2&gt;

&lt;p&gt;Create or update your &lt;code&gt;~/.ssh/config&lt;/code&gt; file to define aliases for each account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Personal GitHub&lt;/span&gt;
Host github-personal
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519

&lt;span class="c"&gt;# Work GitHub&lt;/span&gt;
Host github-work
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_rsa_work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🛠️ You can edit this file using your favorite text editor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code ~/.ssh/config    &lt;span class="c"&gt;# VS Code&lt;/span&gt;
nano ~/.ssh/config    &lt;span class="c"&gt;# Terminal editor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2zxlgazpzfzf72zvw7kq.jpg" alt="Image description" width="800" height="384"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  4. Test Your SSH Connections
&lt;/h2&gt;

&lt;p&gt;Verify your setup with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github-personal
ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github-work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hi your-username! You've successfully authenticated, but GitHub does not provide shell access.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzwmhst3w4ayrmifca2d.jpg" alt="Image description" width="800" height="164"&gt;
&lt;/h2&gt;

&lt;h2&gt;
  
  
  5. Clone Repositories Using SSH Aliases
&lt;/h2&gt;

&lt;p&gt;Now you can clone repos with the correct identity by using the aliases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Personal repo&lt;/span&gt;
git clone git@github-personal:your_personal_username/repo.git

&lt;span class="c"&gt;# Work repo&lt;/span&gt;
git clone git@github-work:your_work_org/repo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more switching keys or editing global settings!&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Set Local Git User Info for Work Repositories
&lt;/h2&gt;

&lt;p&gt;To ensure your work commits use the correct email and name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;path/to/work-repo

git config user.name &lt;span class="s2"&gt;"Your Work Name"&lt;/span&gt;
git config user.email &lt;span class="s2"&gt;"your_work_email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This updates the local &lt;code&gt;.git/config&lt;/code&gt; file and overrides the global config.&lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;Check your Git identity:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config user.name
git config user.email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎉 You're All Set!
&lt;/h2&gt;

&lt;p&gt;With this setup, you can seamlessly manage multiple GitHub accounts on one machine using SSH. It's a clean and secure way to avoid authentication conflicts and commit with the correct identity every time.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use different SSH keys for personal and work accounts&lt;/li&gt;
&lt;li&gt;Define aliases in &lt;code&gt;~/.ssh/config&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Clone repos using the correct alias&lt;/li&gt;
&lt;li&gt;Set local Git user info per project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💬 Got questions or a better SSH setup? Connect on &lt;a href="https://www.linkedin.com/in/popoola-oluwatemilorun/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>ssh</category>
      <category>developer</category>
    </item>
  </channel>
</rss>
