<?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: Khyati Tiwari</title>
    <description>The latest articles on DEV Community by Khyati Tiwari (@khyahahati).</description>
    <link>https://dev.to/khyahahati</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%2F3897870%2Fc6170410-7a9f-45de-adf6-02eb4d7dae7f.jpeg</url>
      <title>DEV Community: Khyati Tiwari</title>
      <link>https://dev.to/khyahahati</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/khyahahati"/>
    <language>en</language>
    <item>
      <title>When Seconds Matter: A Real-Time Go Application for Secure Ledger Transactions</title>
      <dc:creator>Khyati Tiwari</dc:creator>
      <pubDate>Fri, 19 Jun 2026 08:38:13 +0000</pubDate>
      <link>https://dev.to/khyahahati/when-seconds-matter-a-real-time-go-application-for-secure-ledger-transactions-13mb</link>
      <guid>https://dev.to/khyahahati/when-seconds-matter-a-real-time-go-application-for-secure-ledger-transactions-13mb</guid>
      <description>&lt;p&gt;One of my biggest lessons in building secure applications was when I decided I wanted to build a fintech application. An overly complex fintech app would require access to sensitive data which had its legal complications so I stuck with a simple wallet application with a payment feature. &lt;/p&gt;

&lt;p&gt;When building a financial application, data consistency isn't just a feature; it's a hard requirement. If a user transfers $50 from Account A to Account B, two distinct actions must happen simultaneously: Account A must be debited, and Account B must be credited. If the user double-clicks the "Send" button, or if two separate transactions hit the database at the exact same millisecond, the system can suffer from race conditions. If your backend executes these queries independently under default database isolation levels, high concurrency introduces severe vulnerabilities. &lt;/p&gt;

&lt;p&gt;To ensure absolute financial accuracy, I implemented a strict double-entry ledger system. Every time a transfer occurs, the application must:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Debit the amount from Account A.&lt;/li&gt;
&lt;li&gt;Credit the amount to Account B.&lt;/li&gt;
&lt;li&gt;Update the running balances for both accounts.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To execute this safely under heavy concurrent traffic, I chose PostgreSQL's &lt;strong&gt;Serializable Isolation&lt;/strong&gt; which guarantees that if transactions execute concurrently, the end result will be exactly the same as if they had run one after the other in a serialized line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Concurrency Roadblock: Handling SQLSTATE 40001&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To enforce this, Postgres monitors the data reads and writes. If it detects that two concurrent transactions are modifying overlapping data sets in a way that would break this linear guarantee, it steps in aggressively to protect data integrity. Instead of allowing a race condition, Postgres intentionally terminates one of the transactions and throws a specific serialization failure error: SQLSTATE 40001.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftwelzh92nrxdqq7r76y0.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftwelzh92nrxdqq7r76y0.jpg" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Go Solution: 10-Step Exponential Backoff&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since the database kills the transaction to safeguard the ledger, the responsibility shifts entirely to the Go backend to heal the operation. &lt;/p&gt;

&lt;p&gt;If it catches 40001, it treats it as a temporary concurrency conflict rather than a terminal failure. The application then automatically retries the entire database transaction using an exponential backoff strategy. &lt;/p&gt;

&lt;p&gt;The Go server attempts this loop up to 10 times. If the data clears up during any of these attempts, the transaction commits successfully, and the user experiences a seamless transfer without ever knowing a backend collision occurred. However, if the database is under catastrophic conflict and all 10 attempts are completely exhausted, the error is wrapped, and the application layer safely falls back to a generic HTTP 500 internal server error to ensure the system fails closed rather than corrupting data.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx8q64wjz7cdkmcwywbx.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx8q64wjz7cdkmcwywbx.jpg" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aside from this, I enhanced the security of my application by employing several security standards : &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication Layers&lt;/strong&gt;&lt;br&gt;
The application enforces granular security by splitting user interactions into specialized operational layers:&lt;br&gt;
&lt;strong&gt;Web Banking Password:&lt;/strong&gt; A robust alphanumeric password for primary account login.&lt;br&gt;
&lt;strong&gt;4-Digit View PIN:&lt;/strong&gt; A low-friction PIN for safely viewing account balances.&lt;br&gt;
&lt;strong&gt;6-Digit Payment PIN:&lt;/strong&gt; A high-security PIN required specifically for authorizing outbound ledger transfers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hashing&lt;/strong&gt;&lt;br&gt;
To ensure data privacy, the Go backend implements Bcrypt hashing with a secure work factor for all credentials. The database stores only non-reversible cryptographic strings, rendering stored credentials useless in the event of a database compromise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Multi-Factor Authentication (MFA)&lt;/strong&gt;&lt;br&gt;
To protect against credential stuffing, the application mandates MFA via TOTP (Time-based One-Time Password) algorithms. Users link their profiles to authenticator apps, and the backend verifies 6-digit tokens for sensitive sessions, preventing unauthorized access even if primary passwords are leaked.&lt;/p&gt;

&lt;p&gt;Building this app taught me the role of databases in ensuring security in high stakes applications and I am certain that I can upgrade it with more features in the future. &lt;br&gt;
You can test the Digital Wallet at : &lt;a href="https://github.com/khyahahati/digital-wallet" rel="noopener noreferrer"&gt;https://github.com/khyahahati/digital-wallet&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>postgres</category>
      <category>backend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Is FastAPI the best choice to build a Backend Entry Point?</title>
      <dc:creator>Khyati Tiwari</dc:creator>
      <pubDate>Thu, 11 Jun 2026 16:50:25 +0000</pubDate>
      <link>https://dev.to/khyahahati/is-fastapi-the-best-choice-to-build-a-backend-entry-point-1kon</link>
      <guid>https://dev.to/khyahahati/is-fastapi-the-best-choice-to-build-a-backend-entry-point-1kon</guid>
      <description>&lt;p&gt;Starting with placements around last year, the first project I built was a FastAPI-based API gateway. Essentially, what the gateway ensures is that only authenticated traffic reaches backend services alongside enforcing traffic control and observability standards. &lt;br&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%2F0q7x0hbhh99ns1dvl94y.webp" 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%2F0q7x0hbhh99ns1dvl94y.webp" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It handles &lt;em&gt;authentication&lt;/em&gt;, &lt;em&gt;rate limiting&lt;/em&gt;, &lt;em&gt;logging&lt;/em&gt;, and &lt;em&gt;request routing&lt;/em&gt; before forwarding traffic to internal services and I'm not just naming features, they help solve some major pain-points while building a reliable backend. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Mobile and web apps have to keep track of multiple URLs and if you move a service to a new server, you have to update the client-side code and force a redeploy.&lt;br&gt;
Now, because of the routing and proxying feature, there is only one URL. Moreover, the Gateway acts as the traffic controller, mapping requests to the right place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each microservice has the same authentication logic and if a security vulnerability is found in how you verify tokens, you have to patch and redeploy every service in your ecosystem.&lt;br&gt;
The Gateway verifies the JWT once. If it’s valid, it passes the request to the backend with a header. As a result, the backend services can focus purely on business logic instead of security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A single user/script bug can send 10,000 requests per second — crashing the database and causing DOS for all other users.&lt;br&gt;
The Gateway counts requests in real-time and as soon as a user crosses their limit the gateway returns an HTTP Status 429.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Digging through five different sets of server logs across five different machines to piece together what went wrong with an error.&lt;br&gt;
Every request sent is logged in a consistent format at the entry point including the full path, the response time, and the status codes improving debugging speed by 10x.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You don’t know your system is slow until support tickets are raised, no data on peak traffic hours or which services are struggling.&lt;br&gt;
A real-time dashboard. You can see the heartbeat of your system. For example, if your average response time climbs from 50ms to 500ms, an automated alert can notify you before the system crashes.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I chose FastAPI because of concurrency. Since the gateway waits for the backend to respond, FastAPI’s asynchronous capabilities allow it to handle these waiting states without the consumption of any extra memory.&lt;/p&gt;

&lt;p&gt;What my concern is whether this API Gateway is &lt;strong&gt;truly&lt;/strong&gt; good enough to be used in production-grade applications. Am I missing some features or issues that arise with handling backend systems? I would love some opinions. &lt;/p&gt;

&lt;p&gt;You can test the API Gateway here : &lt;a href="https://github.com/khyahahati/api-gateway" rel="noopener noreferrer"&gt;https://github.com/khyahahati/api-gateway&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to hear your thoughts!&lt;/p&gt;

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