<?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: Karuppasamy Pandian</title>
    <description>The latest articles on DEV Community by Karuppasamy Pandian (@kphere).</description>
    <link>https://dev.to/kphere</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%2F3751598%2F008af2dc-a88c-4f2c-a3f2-641ef4a89687.png</url>
      <title>DEV Community: Karuppasamy Pandian</title>
      <link>https://dev.to/kphere</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kphere"/>
    <language>en</language>
    <item>
      <title>AutoMapper &amp; MediatR Going License-Based: A Practical Take from a .NET Developer</title>
      <dc:creator>Karuppasamy Pandian</dc:creator>
      <pubDate>Tue, 31 Mar 2026 00:48:47 +0000</pubDate>
      <link>https://dev.to/kphere/automapper-mediatr-going-license-based-a-practical-take-from-a-net-developer-2b0n</link>
      <guid>https://dev.to/kphere/automapper-mediatr-going-license-based-a-practical-take-from-a-net-developer-2b0n</guid>
      <description>&lt;p&gt;If you’ve been working in the .NET ecosystem for a while, chances are you’ve used AutoMapper and MediatR in at least one project.&lt;/p&gt;

&lt;p&gt;They’re not just libraries anymore—they’ve become habits.&lt;/p&gt;

&lt;p&gt;So when discussions around licensing started surfacing, it caught a lot of developers off guard. Not because of the cost alone, but because of how deeply these tools are embedded in modern .NET architecture.&lt;/p&gt;

&lt;p&gt;This isn’t just about paying for a library. It’s about rethinking some of the assumptions we’ve been making for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Got Comfortable with These Libraries
&lt;/h2&gt;

&lt;p&gt;Let’s be honest—AutoMapper and MediatR made our lives easier.&lt;/p&gt;

&lt;p&gt;With AutoMapper, we stopped writing repetitive mapping code. No more manually copying properties between models. Just define a profile and move on.&lt;/p&gt;

&lt;p&gt;With MediatR, we started writing cleaner, decoupled code. Controllers became thin. Business logic moved into handlers. Cross-cutting concerns like logging and validation became neatly pluggable.&lt;/p&gt;

&lt;p&gt;At some point, these tools stopped feeling like “third-party libraries” and started feeling like part of .NET itself.&lt;/p&gt;

&lt;p&gt;That’s where the risk begins.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Moment Licensing Enters the Conversation
&lt;/h2&gt;

&lt;p&gt;When a library shifts toward a license-based model, the first reaction is usually:&lt;/p&gt;

&lt;p&gt;“Wait… do we now have to pay for this?”&lt;/p&gt;

&lt;p&gt;But the more important question is:&lt;/p&gt;

&lt;p&gt;“How dependent are we on this?”&lt;/p&gt;

&lt;p&gt;Because for many teams, the answer is: very.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s Not Just About Cost
&lt;/h2&gt;

&lt;p&gt;Yes, there’s a financial angle. But in most enterprise setups, the actual licensing cost is not the biggest issue.&lt;/p&gt;

&lt;p&gt;The real impact shows up elsewhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Procurement approvals&lt;/li&gt;
&lt;li&gt;Legal reviews&lt;/li&gt;
&lt;li&gt;Compliance tracking&lt;/li&gt;
&lt;li&gt;Budget planning across multiple services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a single project, it’s manageable. For an organization with 20+ microservices? It adds up—both in cost and operational overhead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bigger Concern: Architectural Lock-In
&lt;/h2&gt;

&lt;p&gt;This is where things get interesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;With AutoMapper&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your application heavily relies on mapping profiles:&lt;/p&gt;

&lt;p&gt;Your DTO transformations are centralized&lt;br&gt;
Your services assume mappings exist&lt;br&gt;
Your tests indirectly depend on those configurations&lt;/p&gt;

&lt;p&gt;Removing AutoMapper isn’t impossible—but it’s not trivial either.&lt;/p&gt;

&lt;p&gt;You’re looking at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rewriting mappings&lt;/li&gt;
&lt;li&gt;Refactoring services&lt;/li&gt;
&lt;li&gt;Potential regressions
&lt;strong&gt;With MediatR&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MediatR goes even deeper.&lt;/p&gt;

&lt;p&gt;If you’ve built your system around it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every request flows through IMediator&lt;/li&gt;
&lt;li&gt;Business logic lives in handlers&lt;/li&gt;
&lt;li&gt;Pipeline behaviors handle cross-cutting concerns
Now imagine removing it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’re not just replacing a library—you’re reshaping your application flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Subtle Reality Check
&lt;/h2&gt;

&lt;p&gt;This situation exposes something important:&lt;/p&gt;

&lt;p&gt;We didn’t just adopt these tools—&lt;strong&gt;we designed around them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that’s a key distinction.&lt;/p&gt;

&lt;p&gt;There’s nothing wrong with using libraries. But when your architecture starts depending on them, you’re no longer just “using”—you’re committing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So What Are the Options?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most teams will end up choosing one of these paths:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Continue and Pay&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For many teams, this is the simplest option.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No refactoring&lt;/li&gt;
&lt;li&gt;No disruption&lt;/li&gt;
&lt;li&gt;Keep existing patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your system is stable and heavily invested, this is a perfectly reasonable decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Gradually Move Away&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some teams will take this as an opportunity to reduce dependency.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Replace AutoMapper in performance-critical paths&lt;/li&gt;
&lt;li&gt;Use explicit mapping where clarity matters&lt;/li&gt;
&lt;li&gt;Limit MediatR usage to specific layers
This approach isn’t about abandoning the tools—it’s about using them more intentionally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Replace Completely&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the most aggressive approach.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manual mapping instead of AutoMapper&lt;/li&gt;
&lt;li&gt;Direct service calls or custom mediator instead of MediatR&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Full control&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zero licensing concerns&lt;br&gt;
But you also take on:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More responsibility&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Less abstraction&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An Unexpected Side Effect: Better Engineering Conversations
&lt;/h2&gt;

&lt;p&gt;Interestingly, this shift is forcing teams to ask better questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do we really need AutoMapper here?&lt;/li&gt;
&lt;li&gt;Is MediatR adding value—or just structure?&lt;/li&gt;
&lt;li&gt;Are we optimizing for clarity, or just following patterns?
These are conversations that often get skipped when everything is “free and working.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Performance (The Thing We Often Ignore)
&lt;/h2&gt;

&lt;p&gt;Let’s not forget—these tools do add overhead.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AutoMapper uses reflection (though optimized over time)&lt;/li&gt;
&lt;li&gt;MediatR introduces an extra hop for every request
In most applications, this is negligible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But in high-throughput systems, it becomes noticeable.&lt;/p&gt;

&lt;p&gt;Licensing discussions are pushing teams to revisit these trade-offs, which is actually a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for Clean Architecture &amp;amp; CQRS
&lt;/h2&gt;

&lt;p&gt;A lot of people associate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AutoMapper → Clean Architecture&lt;/li&gt;
&lt;li&gt;MediatR → CQRS
But that’s not entirely accurate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These libraries *&lt;em&gt;support *&lt;/em&gt; those patterns—they don’t define them.&lt;/p&gt;

&lt;p&gt;You can implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clean Architecture without AutoMapper&lt;/li&gt;
&lt;li&gt;CQRS without MediatR
It just takes a bit more effort.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And maybe that’s the real takeaway.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Take
&lt;/h2&gt;

&lt;p&gt;This shift isn’t a bad thing. It’s uncomfortable—but useful.&lt;/p&gt;

&lt;p&gt;It reminds us that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No library is guaranteed to stay free forever&lt;/li&gt;
&lt;li&gt;Convenience always comes with a trade-off&lt;/li&gt;
&lt;li&gt;Good architecture should survive tool changes
If replacing a library feels impossible, that’s usually a signal—not about the library, but about the design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Final Thought&lt;/p&gt;

&lt;p&gt;AutoMapper and MediatR are still great tools. That hasn’t changed.&lt;/p&gt;

&lt;p&gt;What’s changing is how we think about them.&lt;/p&gt;

&lt;p&gt;Not as default choices—&lt;strong&gt;but as deliberate ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that’s a healthier place to be as engineers.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>LiveAuth - a nuget pkg to liberate your JWT authentication</title>
      <dc:creator>Karuppasamy Pandian</dc:creator>
      <pubDate>Thu, 19 Mar 2026 21:49:34 +0000</pubDate>
      <link>https://dev.to/kphere/liveauth-a-nuget-pkg-to-liberate-your-jwt-authentication-5ab5</link>
      <guid>https://dev.to/kphere/liveauth-a-nuget-pkg-to-liberate-your-jwt-authentication-5ab5</guid>
      <description>&lt;p&gt;I’m excited to announce the release of "LiveAuth" — an extension for ASP.NET Core that solves one of the most common limitations of JWT authentication: lack of real-time control over active sessions.&lt;/p&gt;

&lt;p&gt;JWT is widely used because it is stateless and scalable. However, this design also introduces several practical challenges in real systems.&lt;br&gt;
Once a JWT is issued, it cannot easily:&lt;br&gt;
• be revoked immediately&lt;br&gt;
• reflect role changes in real time&lt;br&gt;
• support forced logout&lt;br&gt;
• enforce true session control&lt;/p&gt;

&lt;p&gt;In many production environments, this leads to difficult trade-offs between security and simplicity.&lt;/p&gt;

&lt;p&gt;"LiveAuth" addresses this problem by introducing dynamic session validation on top of existing JWT authentication, without replacing the authentication pipeline.&lt;/p&gt;

&lt;p&gt;Instead of modifying the authentication scheme, LiveAuth integrates with the OnTokenValidated hook of JwtBearer authentication. Every request is validated against a central session store, allowing the application to enforce real-time session state.&lt;/p&gt;

&lt;p&gt;Key capabilities include:&lt;br&gt;
• Immediate session revocation&lt;br&gt;
• Version-based token invalidation&lt;br&gt;
• Optional real-time role override&lt;br&gt;
• Compatibility with standard ASP.NET Core JWT authentication&lt;br&gt;
• No custom authentication handler required&lt;br&gt;
• Works with Redis, SQL, or any session store&lt;/p&gt;

&lt;p&gt;With this approach, applications can maintain the scalability of JWT while gaining centralized control over active sessions.&lt;/p&gt;

&lt;p&gt;To demonstrate this concept, I also built a sample implementation that enforces a Role revocation in a Web API. &lt;/p&gt;

&lt;p&gt;Without server-side validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User logs in → JWT issued&lt;/li&gt;
&lt;li&gt;User becomes idle&lt;/li&gt;
&lt;li&gt;JWT remains valid&lt;/li&gt;
&lt;li&gt;Access still granted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With LiveAuth + server session validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User logs in&lt;/li&gt;
&lt;li&gt;User becomes idle&lt;/li&gt;
&lt;li&gt;Session expires&lt;/li&gt;
&lt;li&gt;Next request → Unauthorized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This shows how LiveAuth enables real-time session enforcement while still using JWT.&lt;/p&gt;

&lt;p&gt;This example highlights the real-world limitation of stateless JWT tokens and shows how LiveAuth can be used to enforce dynamic session policies.&lt;br&gt;
Architecture:&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%2Fzx3x8cowppyoa0ixr9wx.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%2Fzx3x8cowppyoa0ixr9wx.png" alt=" " width="467" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repository&lt;br&gt;
&lt;a href="https://github.com/ksamhere/LiveAuth" rel="noopener noreferrer"&gt;https://github.com/ksamhere/LiveAuth&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;NuGet Package&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/LiveAuth" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/LiveAuth&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is open source and released under the MIT license.&lt;/p&gt;

&lt;p&gt;I built this as part of exploring practical solutions to real authentication challenges in distributed systems, and I hope it helps developers who face similar issues when working with JWT.&lt;/p&gt;

&lt;p&gt;Feedback, suggestions, and contributions are welcome.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jwt</category>
      <category>dotnetcore</category>
      <category>authentication</category>
    </item>
    <item>
      <title>JWT Is Stateless — But Real Apps Aren’t</title>
      <dc:creator>Karuppasamy Pandian</dc:creator>
      <pubDate>Thu, 05 Feb 2026 01:55:44 +0000</pubDate>
      <link>https://dev.to/kphere/jwt-is-stateless-but-real-apps-arent-2egl</link>
      <guid>https://dev.to/kphere/jwt-is-stateless-but-real-apps-arent-2egl</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why Modern Systems Use Hybrid Stateful Authentication (Like Facebook)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For years, JSON Web Tokens (JWT) have been promoted as the silver bullet for authentication. They’re fast, scalable, and eliminate server-side sessions.&lt;/p&gt;

&lt;p&gt;But then you look at how real-world platforms like Facebook, Google, Netflix, or banking apps actually work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Users stay logged in for months&lt;/li&gt;
&lt;li&gt;Tokens can be revoked instantly&lt;/li&gt;
&lt;li&gt;Compromised devices can be logged out&lt;/li&gt;
&lt;li&gt;Offline access still works&lt;/li&gt;
&lt;li&gt;Suspicious sessions are terminated immediately&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pure JWT cannot safely do all of this.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That’s why modern systems use a &lt;strong&gt;Hybrid Stateful Authentication Model.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s break it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Stateless JWT: What It Really Means
&lt;/h2&gt;

&lt;p&gt;A standard JWT contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User ID&lt;/li&gt;
&lt;li&gt;Roles / claims&lt;/li&gt;
&lt;li&gt;Expiration time&lt;/li&gt;
&lt;li&gt;Digital signature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once issued, the server &lt;strong&gt;does not store it&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → sends JWT  
Server → verifies signature + expiration  
→ grants access 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No session storage&lt;/li&gt;
&lt;li&gt;Horizontally scalable&lt;/li&gt;
&lt;li&gt;Very low latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But here’s the problem:&lt;/strong&gt;&lt;br&gt;
The server cannot revoke a JWT once issued. If stolen, it remains valid until it expires.&lt;/p&gt;

&lt;p&gt;That’s a &lt;strong&gt;huge security gap.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Why Stateless JWT Alone Fails in Real Apps
&lt;/h2&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%2Fb0vpwevdprai6w623bvh.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%2Fb0vpwevdprai6w623bvh.png" alt=" " width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stateless tokens are blind.&lt;br&gt;
They don’t know whether a session still exists.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Enter: Hybrid Stateful Authentication
&lt;/h2&gt;

&lt;p&gt;This model combines:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;JWT for fast authorization&lt;br&gt;
Server session for control&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s how Facebook, Google, and most identity providers work.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Hybrid JWT Flow (How Facebook-Style Auth Works)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Login&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Server creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A JWT (short lived, signed)&lt;/li&gt;
&lt;li&gt;A Session Record in DB / Redis:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SessionId
UserId
DeviceId
Status = Active
LastSeen

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The JWT contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sub = userId
sid = sessionId
exp = 15 minutes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2 — API Request&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → sends JWT
Server →
  1. Verify signature
  2. Check expiration
  3. Lookup sessionId (sid) in session store
  4. Ensure session is Active
→ Grant access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the server controls the token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Logout or Revoke&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Server updates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Session.Status = Revoked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any request using that JWT is now rejected — even if it’s not expired.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Why This Is Still Fast
&lt;/h2&gt;

&lt;p&gt;Session lookups are done in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Memory cache&lt;/li&gt;
&lt;li&gt;Distributed cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Latency is typically &amp;lt; 2ms.&lt;/p&gt;

&lt;p&gt;This is negligible compared to database calls and network overhead.&lt;/p&gt;

&lt;p&gt;Security &amp;gt; micro-optimizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Offline &amp;amp; Long-Term Login
&lt;/h2&gt;

&lt;p&gt;Apps use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short-lived access token (JWT)&lt;/li&gt;
&lt;li&gt;Long-lived refresh token (stateful)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When access expires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client → sends refresh token
Server → validates session
→ issues new JWT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how Facebook keeps you logged in for months.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Stateless vs Hybrid Stateful
&lt;/h2&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%2Fjlfs5zill9jf8evuc4fq.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%2Fjlfs5zill9jf8evuc4fq.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Final Thought
&lt;/h2&gt;

&lt;p&gt;JWT is an &lt;strong&gt;authorization format&lt;/strong&gt;, not a complete authentication strategy.&lt;/p&gt;

&lt;p&gt;Real-world systems must answer:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Is this session still valid?”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Only a &lt;strong&gt;hybrid stateful model&lt;/strong&gt; can do that safely.&lt;/p&gt;

&lt;p&gt;That’s why Facebook, Google, and most enterprise systems &lt;strong&gt;do not rely on stateless JWT alone&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you’re designing authentication for a serious application,&lt;br&gt;
&lt;strong&gt;stateless is not enough&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Security requires state.&lt;/p&gt;

</description>
      <category>authorization</category>
      <category>jwt</category>
      <category>security</category>
      <category>modernapp</category>
    </item>
    <item>
      <title>FluentValidation in ASP.NET Core: Why One Validator per Request Is the Real Best Practice</title>
      <dc:creator>Karuppasamy Pandian</dc:creator>
      <pubDate>Wed, 04 Feb 2026 01:02:09 +0000</pubDate>
      <link>https://dev.to/kphere/fluentvalidation-in-aspnet-core-why-one-validator-per-request-is-the-real-best-practice-18m4</link>
      <guid>https://dev.to/kphere/fluentvalidation-in-aspnet-core-why-one-validator-per-request-is-the-real-best-practice-18m4</guid>
      <description>&lt;p&gt;In modern .NET Web APIs, validation is not just about checking nulls or ranges. It is part of your API contract and one of the most critical layers that protects your system from bad data.&lt;/p&gt;

&lt;p&gt;FluentValidation has become the industry standard for handling validation in a clean, testable, and maintainable way.&lt;/p&gt;

&lt;p&gt;In this article, let's see below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What FluentValidation is&lt;/li&gt;
&lt;li&gt;How to implement it in ASP.NET Core&lt;/li&gt;
&lt;li&gt;Why a “generic validator” is a bad idea&lt;/li&gt;
&lt;li&gt;Why one request = one validator is the correct pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is FluentValidation?&lt;/strong&gt;&lt;br&gt;
FluentValidation is a popular .NET library that allows you to define validation rules using a &lt;strong&gt;fluent, strongly typed syntax&lt;/strong&gt; instead of attributes or controller logic.&lt;/p&gt;

&lt;p&gt;Instead of this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Required]
[EmailAddress]
public string Email { get; set; } 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You define rules in a separate validator class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RuleFor(x =&amp;gt; x.Email)
    .NotEmpty()
    .EmailAddress(); 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps your API models clean and moves validation into a dedicated validation layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Validation Should NOT Be in Controllers&lt;/strong&gt;&lt;br&gt;
Putting validation in controllers leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicated logic&lt;/li&gt;
&lt;li&gt;Hard-to-test code&lt;/li&gt;
&lt;li&gt;Fat controllers&lt;/li&gt;
&lt;li&gt;Business rules leaking into API layer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FluentValidation integrates directly into the ASP.NET Core pipeline, so validation &lt;strong&gt;runs automatically before your controller executes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If validation fails, the framework returns a &lt;strong&gt;400 Bad Request&lt;/strong&gt; — no extra code required in the controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Implement FluentValidation in ASP.NET Core&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install Packages
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package FluentValidation
dotnet add package FluentValidation.AspNetCore 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Create a Request DTO
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CreateUserRequest
{
    public string FirstName { get; set; }
    public string Email { get; set; }
    public int Age { get; set; }
} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is a Request DTO — not your database entity.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the Validator
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CreateUserRequestValidator 
    : AbstractValidator&amp;lt;CreateUserRequest&amp;gt;
{
    public CreateUserRequestValidator()
    {
        RuleFor(x =&amp;gt; x.FirstName)
            .NotEmpty()
            .MinimumLength(3);

        RuleFor(x =&amp;gt; x.Email)
            .NotEmpty()
            .EmailAddress();

        RuleFor(x =&amp;gt; x.Age)
            .InclusiveBetween(18, 60);
    }
} 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Register FluentValidation
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddControllers()
    .AddFluentValidationAutoValidation();

builder.Services.AddValidatorsFromAssemblyContaining&amp;lt;CreateUserRequestValidator&amp;gt;(); 

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That’s it. Every request is now validated automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why NOT Use a Generic Validator?&lt;/strong&gt;&lt;br&gt;
Many developers ask: “Can I create one generic validator for all requests?”&lt;/p&gt;

&lt;p&gt;Short answer: No.&lt;/p&gt;

&lt;p&gt;Here’s why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every request has different business rules&lt;/li&gt;
&lt;li&gt;Generic validators become God classes&lt;/li&gt;
&lt;li&gt;Rules turn into if/else chaos&lt;/li&gt;
&lt;li&gt;You lose type safety&lt;/li&gt;
&lt;li&gt;You break single responsibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Validation is not generic — it is use-case specific.&lt;/p&gt;

&lt;p&gt;The Industry Standard Pattern&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CreateUserRequest      → CreateUserRequestValidator
UpdateUserRequest      → UpdateUserRequestValidator
CreateOrderRequest     → CreateOrderRequestValidator 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each API contract gets its own validator.&lt;/p&gt;

&lt;p&gt;This gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear rules per use case&lt;/li&gt;
&lt;li&gt;Easy unit testing&lt;/li&gt;
&lt;li&gt;Zero duplication&lt;/li&gt;
&lt;li&gt;Clean controllers&lt;/li&gt;
&lt;li&gt;Scalable architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sharing Rules Without Duplication&lt;/strong&gt;&lt;br&gt;
You can still reuse logic safely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rule Extensions&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static class ValidationExtensions
{
    public static IRuleBuilderOptions&amp;lt;T, string&amp;gt; ValidEmail&amp;lt;T&amp;gt;(
        this IRuleBuilder&amp;lt;T, string&amp;gt; rule)
    {
        return rule.NotEmpty().EmailAddress();
    }
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RuleFor(x =&amp;gt; x.Email).ValidEmail(); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps validators clean and reusable without breaking architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thought&lt;/strong&gt;&lt;br&gt;
FluentValidation is not just a validation tool — it is a design decision.&lt;/p&gt;

&lt;p&gt;By using:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request DTOs&lt;br&gt;
One validator per request&lt;br&gt;
Automatic pipeline validation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You build APIs that are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safer&lt;/li&gt;
&lt;li&gt;Cleaner&lt;/li&gt;
&lt;li&gt;Easier to test&lt;/li&gt;
&lt;li&gt;Easier to maintain
That is what real-world, production-grade .NET systems look like.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>dotnetcore</category>
      <category>dotnet</category>
      <category>validation</category>
    </item>
  </channel>
</rss>
