<?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: Nilotpal Baishya</title>
    <description>The latest articles on DEV Community by Nilotpal Baishya (@bynilotpal).</description>
    <link>https://dev.to/bynilotpal</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3965951%2Faaea1422-1fc3-4134-bde7-a7b0d5c9bb33.jpg</url>
      <title>DEV Community: Nilotpal Baishya</title>
      <link>https://dev.to/bynilotpal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bynilotpal"/>
    <language>en</language>
    <item>
      <title>Building a Distributed Rate Limiter from Scratch</title>
      <dc:creator>Nilotpal Baishya</dc:creator>
      <pubDate>Sat, 11 Jul 2026 11:48:30 +0000</pubDate>
      <link>https://dev.to/bynilotpal/building-a-distributed-rate-limiter-from-scratch-44gi</link>
      <guid>https://dev.to/bynilotpal/building-a-distributed-rate-limiter-from-scratch-44gi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;There comes a point while learning software engineering where using a technology isn't enough anymore.&lt;/p&gt;

&lt;p&gt;For me, that technology was &lt;strong&gt;Redis&lt;/strong&gt;. I had used Redis before in small projects. I knew it was fast, great for caching, and commonly used in backend systems. But there was one thing I couldn't confidently explain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do distributed applications actually implement rate limiting?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I understood the concept of rate limiting, but not the engineering behind it. Instead of watching another tutorial, I decided to build one from scratch.&lt;/p&gt;

&lt;p&gt;That project eventually became &lt;strong&gt;Aegis&lt;/strong&gt;—my first open-source Python package.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build Another Rate Limiter?
&lt;/h2&gt;

&lt;p&gt;Honestly, I wasn't trying to build a better rate limiter. There are already plenty of mature libraries that solve this problem far better than something I could build alone.&lt;/p&gt;

&lt;p&gt;My goal was much simpler. I wanted to understand how these systems actually work under the hood.&lt;/p&gt;

&lt;p&gt;That meant asking questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do different rate limiting algorithms behave?&lt;/li&gt;
&lt;li&gt;Why is Redis commonly used?&lt;/li&gt;
&lt;li&gt;What causes race conditions?&lt;/li&gt;
&lt;li&gt;Why do people use Lua scripts with Redis?&lt;/li&gt;
&lt;li&gt;How would I design a library that other developers could actually use?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only way I knew how to answer those questions was by building everything myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Small
&lt;/h2&gt;

&lt;p&gt;Like most projects, Aegis didn't start with Redis or distributed systems. It started with a simple in-memory implementation.&lt;/p&gt;

&lt;p&gt;I first implemented four common rate limiting algorithms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed Window&lt;/li&gt;
&lt;li&gt;Sliding Window&lt;/li&gt;
&lt;li&gt;Token Bucket&lt;/li&gt;
&lt;li&gt;Leaky Bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Getting each algorithm working taught me that they all solve the same problem in different ways.&lt;/p&gt;

&lt;p&gt;Some are simple. Some are more accurate. Some allow bursts of traffic. Some smooth traffic over time.&lt;/p&gt;

&lt;p&gt;Understanding those trade-offs was one of the most interesting parts of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making It Distributed
&lt;/h2&gt;

&lt;p&gt;Once the in-memory implementation was working, I started thinking about a more realistic scenario.&lt;/p&gt;

&lt;p&gt;What happens when your application runs on multiple servers? An in-memory counter only exists inside a single process. If two servers each keep their own counters, the rate limiter isn't really shared anymore.&lt;/p&gt;

&lt;p&gt;That's where Redis came in. Redis became the shared source of truth, allowing every application instance to work with the same state.&lt;/p&gt;

&lt;p&gt;But moving the logic to Redis introduced another challenge-Race conditions.&lt;/p&gt;

&lt;p&gt;Two requests arriving at almost the same time could both read the same value before either one updated it. &lt;/p&gt;

&lt;p&gt;To solve that problem, I implemented the Redis algorithms using &lt;strong&gt;Lua scripts&lt;/strong&gt;, allowing the entire operation to execute atomically on the Redis server. It was one of the biggest learning moments during this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Beyond the Algorithms
&lt;/h2&gt;

&lt;p&gt;At some point, I realized Aegis was becoming more than just a collection of algorithms. So I spent time improving the architecture.&lt;/p&gt;

&lt;p&gt;Some of the things I added were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A shared Redis Lua base class&lt;/li&gt;
&lt;li&gt;Separate Redis and in-memory backends&lt;/li&gt;
&lt;li&gt;A simple SDK API&lt;/li&gt;
&lt;li&gt;Unit and integration tests&lt;/li&gt;
&lt;li&gt;GitHub Actions for automated testing&lt;/li&gt;
&lt;li&gt;Black and Ruff for formatting and linting&lt;/li&gt;
&lt;li&gt;Packaging and publishing to PyPI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These weren't the most exciting features to build, but they made the project feel much more complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Looking back, Aegis taught me much more than rate limiting.&lt;/p&gt;

&lt;p&gt;It taught me how to think about distributed systems, software design, testing, packaging, and maintaining an open-source project. More importantly, it reminded me that the best way to understand a complex topic is often to build it yourself.&lt;/p&gt;

&lt;p&gt;There are still plenty of things I want to improve, and Aegis is far from finished. But I'm happy with where it has taken me so far.&lt;/p&gt;

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

&lt;p&gt;This project started with a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"How does distributed rate limiting actually work?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Trying to answer that question led me through Redis, Lua, multiple algorithms, software architecture, testing, CI/CD, and eventually publishing my first open-source Python package.&lt;/p&gt;

&lt;p&gt;If you're learning backend engineering, I'd definitely recommend picking a problem that interests you and building it from scratch.&lt;/p&gt;

&lt;p&gt;You'll probably learn much more than any tutorial could teach.&lt;/p&gt;

&lt;p&gt;If you'd like to check out the project:&lt;/p&gt;

&lt;p&gt;⭐ GitHub: &lt;a href="https://github.com/Nilotpal04/aegis" rel="noopener noreferrer"&gt;https://github.com/Nilotpal04/aegis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📦 PyPI: &lt;a href="https://pypi.org/project/aegis-rl/0.1.1/" rel="noopener noreferrer"&gt;https://pypi.org/project/aegis-rl/0.1.1/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;aegis-rl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feedback and suggestions are always welcome!&lt;/p&gt;

</description>
      <category>backend</category>
      <category>distributedsystems</category>
      <category>opensource</category>
    </item>
    <item>
      <title>7 Backend Concepts That Separate a Real Backend from a Simple CRUD Application</title>
      <dc:creator>Nilotpal Baishya</dc:creator>
      <pubDate>Fri, 19 Jun 2026 15:59:07 +0000</pubDate>
      <link>https://dev.to/bynilotpal/7-backend-concepts-that-separate-a-real-backend-from-a-simple-crud-application-44oj</link>
      <guid>https://dev.to/bynilotpal/7-backend-concepts-that-separate-a-real-backend-from-a-simple-crud-application-44oj</guid>
      <description>&lt;p&gt;The moment I first started learning backend development, I already knew that real applications involved much more than CRUD operations. What I didn't fully understand was how these things are actually built behind the scenes.&lt;/p&gt;

&lt;p&gt;While building backend projects and reviewing a larger FastAPI codebase, I came across several concepts that repeatedly appear in real-world systems. The interesting part wasn't discovering these concepts—it was understanding why they exist and what problems they solve.&lt;/p&gt;

&lt;p&gt;Here are 7 backend concepts that changed how I think about backend engineering.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Authentication (JWT)
&lt;/h3&gt;

&lt;p&gt;The first question every backend needs to answer is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Who is making this request?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Without authentication, anyone can access your endpoints and perform actions they shouldn't be able to. While building projects, authentication was one of the first concepts that made my backend feel more like a real application. Instead of allowing every request, users now had to log in, receive a token, and include that token when accessing protected routes.&lt;/p&gt;

&lt;p&gt;This is where JWT (JSON Web Tokens) came in.&lt;/p&gt;

&lt;p&gt;Implementing login, protected routes, and a &lt;code&gt;/me&lt;/code&gt; endpoint helped me understand how applications keep track of users and verify their identity. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Authorization (RBAC)
&lt;/h3&gt;

&lt;p&gt;Authentication tells us who the user is and "Authorization" tells us what they are allowed to do.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A normal user can upload documents.&lt;/li&gt;
&lt;li&gt;An admin can verify documents.&lt;/li&gt;
&lt;li&gt;Another role might manage users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As applications grow, managing permissions becomes increasingly important. Initially, it may seem easy to add a few checks wherever needed, but that approach quickly becomes difficult to maintain.&lt;/p&gt;

&lt;p&gt;This is where RBAC (Role-Based Access Control) comes in.&lt;/p&gt;

&lt;p&gt;Instead of scattering permission checks throughout the codebase, roles can be centralized and enforced through reusable dependencies and helper functions.&lt;/p&gt;

&lt;p&gt;Learning RBAC helped me understand how larger applications manage permissions cleanly, while keeping the code organized and easier to maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Dependency Injection
&lt;/h3&gt;

&lt;p&gt;This was probably the concept that confused me the most when I started learning FastAPI.&lt;/p&gt;

&lt;p&gt;I kept seeing things like:&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="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and&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="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CurrentUser&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without fully understanding what was happening behind the scenes.&lt;/p&gt;

&lt;p&gt;Eventually, I realized that dependency injection is simply a way of providing things like database sessions, authenticated users, and permissions to endpoints automatically.&lt;/p&gt;

&lt;p&gt;Once it clicked, a lot of FastAPI's design started making sense. It also helped me understand how the same database session, current user, or permission checks could be reused across multiple endpoints without repeating the same code everywhere.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Global Exception Handling
&lt;/h3&gt;

&lt;p&gt;In smaller projects, it's common to see:&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="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;everywhere.&lt;/p&gt;

&lt;p&gt;That works at first, but as the application grows, error handling can quickly become repetitive and harder to maintain.&lt;/p&gt;

&lt;p&gt;While building projects, I learned how custom exceptions and global exception handlers can make this much cleaner.&lt;/p&gt;

&lt;p&gt;Instead of repeating the same response logic in every route, the backend can define reusable exceptions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UnauthorizedError&lt;/li&gt;
&lt;li&gt;ForbiddenError&lt;/li&gt;
&lt;li&gt;ConflictError&lt;/li&gt;
&lt;li&gt;NotFoundError&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The framework then handles these exceptions consistently across the entire application.&lt;/p&gt;

&lt;p&gt;Besides reducing repetition, this approach also makes the code easier to read and helps keep API responses standardized.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Audit Logs
&lt;/h3&gt;

&lt;p&gt;This was one concept I hadn't paid much attention to when I started learning backend development.&lt;/p&gt;

&lt;p&gt;Imagine an admin verifies a document.&lt;/p&gt;

&lt;p&gt;A few days later someone asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who verified it?&lt;/li&gt;
&lt;li&gt;When was it verified?&lt;/li&gt;
&lt;li&gt;What action was taken?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without audit logs, there is no answer.&lt;/p&gt;

&lt;p&gt;Audit logs create a history of important actions inside the system. They don't directly add new features for users, but they make systems much more reliable and traceable.&lt;/p&gt;

&lt;p&gt;After implementing and reviewing them in real projects, I started noticing how important they are in applications where accountability and record-keeping matter.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Database Migrations (Alembic)
&lt;/h3&gt;

&lt;p&gt;One thing I quickly realized while working with databases is that changing a model is easy, but safely updating an existing database is not.&lt;/p&gt;

&lt;p&gt;What happens when a new column is added? Or a table structure changes after the application is already being used?&lt;/p&gt;

&lt;p&gt;This is where Alembic comes in. A simple way to think about it is: &lt;strong&gt;Alembic is like Git for your database schema.&lt;/strong&gt; It keeps track of changes and allows those changes to be applied in a controlled and repeatable way.&lt;/p&gt;

&lt;p&gt;Instead of manually modifying the database, migrations provide a structured and controlled way to evolve the schema over time.&lt;/p&gt;

&lt;p&gt;Learning Alembic helped me understand that managing a database isn't just about creating tables. It's also about safely handling change as an application grows and new requirements emerge.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Asynchronous Programming
&lt;/h3&gt;

&lt;p&gt;One of the most intimidating concepts I encountered was &lt;strong&gt;Async&lt;/strong&gt;. At first, I understood the syntax, but I didn't fully understand when asynchronous programming was useful or what problem it was trying to solve.&lt;/p&gt;

&lt;p&gt;What I learned is that asynchronous programming allows a server to handle other work while waiting for certain operations to complete.&lt;/p&gt;

&lt;p&gt;This becomes especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Database operations&lt;/li&gt;
&lt;li&gt;Network requests&lt;/li&gt;
&lt;li&gt;File handling&lt;/li&gt;
&lt;li&gt;External APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One lesson that really stuck with me was that simply writing:&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="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_function&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;some_async_operation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not automatically make a function asynchronous. The code inside the function also needs to perform asynchronous operations for async to provide any real benefit. Understanding that distinction helped me appreciate why async exists and where it actually provides value in backend applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Before learning these concepts, I mostly focused on getting features to work. If an endpoint returned the correct response, I was happy.&lt;/p&gt;

&lt;p&gt;But while building project and reviewing a larger backend, I started realizing that backend development is about much more than making things work.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who is making this request?&lt;/li&gt;
&lt;li&gt;Are they allowed to do this?&lt;/li&gt;
&lt;li&gt;What happens if something goes wrong?&lt;/li&gt;
&lt;li&gt;How do we track important actions?&lt;/li&gt;
&lt;li&gt;How do we safely change the database later?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;started becoming just as important as the endpoints themselves.&lt;/p&gt;

&lt;p&gt;I'm still learning, and I have a lot more to explore. But understanding concepts like JWT authentication, RBAC, dependency injection, audit logs, Alembic, and async programming has given me a much better picture of how real backend applications are built.&lt;/p&gt;

&lt;p&gt;For me, these concepts were the first step from simply building APIs to thinking more like a backend engineer.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>fastapi</category>
      <category>beginners</category>
      <category>python</category>
    </item>
    <item>
      <title>My First CORS Error in FastAPI</title>
      <dc:creator>Nilotpal Baishya</dc:creator>
      <pubDate>Wed, 03 Jun 2026 10:57:54 +0000</pubDate>
      <link>https://dev.to/bynilotpal/my-first-cors-error-in-fastapi-45jo</link>
      <guid>https://dev.to/bynilotpal/my-first-cors-error-in-fastapi-45jo</guid>
      <description>&lt;p&gt;I'm learning FastAPI. And I am not a person who can learn by watching tutorials.&lt;/p&gt;

&lt;p&gt;So I decided to learn while building. So I built something small just to start with FastAPI. A basic expense tracker.&lt;/p&gt;

&lt;p&gt;Nothing fancy. Just a FastAPI backend with a few endpoints and a simple HTML page with JavaScript. There are three buttons in it: Load Expenses, Add Expense, Calculate Total. I just wanted to see how frontend talks to backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Everything seemed fine
&lt;/h3&gt;

&lt;p&gt;I started the server. No errors. Tested my API in Swagger UI. Worked perfectly. Then I opened my HTML file. Clicked "Load Expenses."&lt;/p&gt;

&lt;p&gt;But there was nothing. like no expenses, no error, just nothing.&lt;/p&gt;

&lt;p&gt;I stared at the screen thinking &lt;em&gt;What did I do wrong?&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  I blamed my backend first
&lt;/h3&gt;

&lt;p&gt;I thought I messed up my Python code. I checked everything but there was nothing wrong. Then tested Swagger UI again. The endpoint was fine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then I blamed my frontend
&lt;/h3&gt;

&lt;p&gt;So I went to check my fetch request. It looked fine to me. I checked the button. Worked fine. But after all this there was still nothing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then I opened the browser console
&lt;/h3&gt;

&lt;p&gt;This was the moment. I clicked F12 and saw this red error:&lt;/p&gt;

&lt;p&gt;Access to fetch at '&lt;a href="http://127.0.0.1:8000/expenses" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/expenses&lt;/a&gt;' from origin '&lt;a href="http://127.0.0.1:3000" rel="noopener noreferrer"&gt;http://127.0.0.1:3000&lt;/a&gt;' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.&lt;/p&gt;

&lt;p&gt;I had no idea what CORS meant.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I learned
&lt;/h3&gt;

&lt;p&gt;I learnt that my backend was working the whole time. I searched about CORS error and came to know about what is CORS and all. The browser was blocking it. SO my frontend was on port 3000 and my backend was on port 8000.They are different ports. The browser saw them as different "origins" and said "nope, not allowed unless the backend gives permission." &lt;br&gt;
My backend wasn't giving permission. So I added the CORS middleware, it adds special HTTP headers to my backend responses.&lt;/p&gt;
&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;I added this to my FastAPI code:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi.middleware.cors&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;CORSMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_origins&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;http://127.0.0.1:3000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;allow_methods&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;*&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;allow_headers&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;*&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;h3&gt;
  
  
  What stuck with me
&lt;/h3&gt;

&lt;p&gt;The fix was four lines. But what I actually learned was:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I should always open the browser console FIRST. At least not after checking everything else.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test my API separately before blaming it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CORS errors are browser things, not code bugs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>api</category>
      <category>fastapi</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
