<?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: Victor Ajadi</title>
    <description>The latest articles on DEV Community by Victor Ajadi (@victor_ajadi_21b5913f79f6).</description>
    <link>https://dev.to/victor_ajadi_21b5913f79f6</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%2F1668214%2F6d803e51-d5ba-41ff-941f-806adbcc80b5.jpeg</url>
      <title>DEV Community: Victor Ajadi</title>
      <link>https://dev.to/victor_ajadi_21b5913f79f6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/victor_ajadi_21b5913f79f6"/>
    <language>en</language>
    <item>
      <title>Smart Query-Aware Cache Invalidation: Solving Mongoose Performance at Scale</title>
      <dc:creator>Victor Ajadi</dc:creator>
      <pubDate>Sun, 14 Jun 2026 04:19:56 +0000</pubDate>
      <link>https://dev.to/victor_ajadi_21b5913f79f6/smart-query-aware-cache-invalidation-solving-mongoose-performance-at-scale-59ic</link>
      <guid>https://dev.to/victor_ajadi_21b5913f79f6/smart-query-aware-cache-invalidation-solving-mongoose-performance-at-scale-59ic</guid>
      <description>&lt;h1&gt;
  
  
  The Mongoose Caching Problem (And How We Solved It)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  From 300 RPS to 700+ RPS: A 2.2x Performance Breakthrough
&lt;/h2&gt;

&lt;p&gt;When you're building a Node.js application with MongoDB, you quickly hit a wall: &lt;strong&gt;your database can't handle the query volume&lt;/strong&gt;. You add caching. But caching is fraught with pitfalls-cache stampedes, stale data, invalidation nightmares.&lt;/p&gt;

&lt;p&gt;We built &lt;code&gt;@mongoose-performance-cache&lt;/code&gt; to solve this once and for all. Here's what we learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Why Your Mongoose App Feels Slow
&lt;/h2&gt;

&lt;p&gt;Let me paint a scenario. You have a typical SaaS API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User authentication - runs thousands of times&lt;/span&gt;
&lt;span class="nx"&gt;app&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Popular reports - same query, different users&lt;/span&gt;
&lt;span class="nx"&gt;app&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/reports/active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reports&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;p&gt;Each request hits MongoDB. At 100 concurrent users:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;500+ database queries per second&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MongoDB CPU at 85%+&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;P99 latency: 500ms+&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Users complaining: "Why is this so slow?"&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need caching. But here's where it gets tricky.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching is Hard (For Good Reason)
&lt;/h2&gt;

&lt;p&gt;Traditional caching with Redis is deceptively simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Naive caching approach&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getActiveReports&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active_reports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active_reports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EX&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reports&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;p&gt;Looks clean. But in production, it breaks in three catastrophic ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 1: The Cache Stampede
&lt;/h3&gt;

&lt;p&gt;It's 2:59:55 PM. Your cache expires in 5 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2:59:55 - 100 concurrent requests arrive
2:59:59 - Cache expires
3:00:00 - All 100 requests query MongoDB
         (not 100 queries in sequence, but 100 in parallel)
         ↓
         MongoDB CPU: 95%+, P99 Latency: 2000ms+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called a &lt;strong&gt;cache stampede&lt;/strong&gt; or &lt;strong&gt;thundering herd&lt;/strong&gt;. Your database crashes right when it matters most.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Invalidation Hell
&lt;/h3&gt;

&lt;p&gt;You need to update a report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Update the report&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Now what? The cache says it's still 'active'&lt;/span&gt;
&lt;span class="c1"&gt;// Do you clear the entire 'active_reports' cache?&lt;/span&gt;
&lt;span class="c1"&gt;// Do you clear all report caches?&lt;/span&gt;
&lt;span class="c1"&gt;// Do you manually track which queries are affected?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most teams pick &lt;strong&gt;option 2: clear everything&lt;/strong&gt;. Your hit rate plummets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: Concurrent Writes
&lt;/h3&gt;

&lt;p&gt;Multiple requests update the same document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request A: Update report status → Queue update → Cache in 50ms
Request B: Update report name  → Queue update → Cache in 100ms

What gets cached? The result of B (name change), but A's status change is lost.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Solution: Intelligent Caching
&lt;/h2&gt;

&lt;p&gt;We built &lt;code&gt;@mongoose-performance-cache&lt;/code&gt; to solve all three problems automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cache Stampede Protection
&lt;/h3&gt;

&lt;p&gt;When multiple concurrent requests hit the same uncached query, &lt;strong&gt;only one database query executes&lt;/strong&gt;. The rest share the result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mongoose-performance-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyCacheToQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReportSchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 100 concurrent requests&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Result: 1 MongoDB query, 100 shared responses&lt;/span&gt;
&lt;span class="c1"&gt;// Not 100 queries. Not throttled. Just smart.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Eliminated cache stampedes entirely. No more thundering herd.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Smart Query-Aware Invalidation
&lt;/h3&gt;

&lt;p&gt;Here's where it gets clever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This query is cached&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeReports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Update report - change the name&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Q4 Report&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// What happens to the cache?&lt;/span&gt;
&lt;span class="c1"&gt;// The system automatically determines:&lt;/span&gt;
&lt;span class="c1"&gt;// "Does 'name' appear in the query filter?"&lt;/span&gt;
&lt;span class="c1"&gt;// "No. So don't invalidate."&lt;/span&gt;
&lt;span class="c1"&gt;// ✅ Cache remains valid&lt;/span&gt;

&lt;span class="c1"&gt;// Now update the status&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByIdAndUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// The system determines:&lt;/span&gt;
&lt;span class="c1"&gt;// "Does 'status' appear in the query filter?"&lt;/span&gt;
&lt;span class="c1"&gt;// "Yes. Invalidate this specific query."&lt;/span&gt;
&lt;span class="c1"&gt;// ✅ Only relevant queries cleared&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't guessing. It's pattern matching on your actual query filters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; 70% higher hit rates in write-heavy workloads. The cache stays valid longer.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Batch Write Optimization
&lt;/h3&gt;

&lt;p&gt;Instead of flushing each cache write individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Traditional: 1000 writes → 1000 Redis operations → Network overhead
v1.2:        1000 writes → Batch queue → 40 Redis operations (deduped)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The library groups cache writes into 50ms batches, automatically deduplicating them. If the same key is written twice, only the latest write persists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; 60% fewer Redis operations. Smoother latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Results: Benchmarks That Matter
&lt;/h2&gt;

&lt;p&gt;We stress-tested this on real hardware (Lenovo 14 Ada: 2-core @ 1.2GHz, 5.88GB RAM) with a realistic workload:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;v1.1 Performance (Before)
├─ Throughput: 300-350 RPS
├─ P50 Latency: ~120ms
├─ P95 Latency: ~250ms
└─ P99 Latency: ~500ms

v1.2 Performance (After)
├─ Throughput: 705-708 RPS ⬆️ 2.2x
├─ P50 Latency: ~70ms ⬆️ 42% faster
├─ P95 Latency: ~95ms ⬆️ 62% faster
└─ P99 Latency: ~150ms ⬆️ 70% faster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test details:&lt;/strong&gt; 50 concurrent clients, 60-second duration, 70% read / 15% write / 15% aggregate operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Grade: The Audit Story
&lt;/h2&gt;

&lt;p&gt;Before shipping this, we ran a comprehensive audit across 45,534 real-world operations:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What we verified:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Zero data corruption (100% success rate)&lt;/li&gt;
&lt;li&gt;✅ Proper invalidation semantics (every edge case tested)&lt;/li&gt;
&lt;li&gt;✅ Memory safety under load (no OOM crashes)&lt;/li&gt;
&lt;li&gt;✅ Serialization accuracy (BSON types handled correctly)&lt;/li&gt;
&lt;li&gt;✅ Distributed cache consistency (Redis pub/sub working)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Integrity Score: 9.6/10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We found (and fixed) three minor issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Size estimation was ±80% off (now ±20%)&lt;/li&gt;
&lt;li&gt;$pull operator missing type safety (now validated)&lt;/li&gt;
&lt;li&gt;Geospatial queries weren't cache-safe (now rejected)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All fixes were straightforward. &lt;strong&gt;No architectural flaws. No data corruption vectors.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works: Just Three Lines
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;initCache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mongoose-performance-cache&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// 1. Initialize once&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;initCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                    &lt;span class="c1"&gt;// 10 minutes&lt;/span&gt;
  &lt;span class="na"&gt;enableSmartInvalidation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// Smart invalidation&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// 2. Apply to your schemas&lt;/span&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyCacheToQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserSchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyCacheToQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReportSchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;applyCacheToQueries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ProjectSchema&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 3. Use Mongoose normally&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;published&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// That's it. Caching works automatically.&lt;/span&gt;
&lt;span class="c1"&gt;// Invalidation happens automatically.&lt;/span&gt;
&lt;span class="c1"&gt;// No manual cache busting.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Architecture: Why It's Different
&lt;/h2&gt;

&lt;p&gt;Traditional caching treats the cache as a simple key-value store. We treat it as an &lt;strong&gt;extension of Mongoose itself&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;Standard Caching:
User Logic → Cache Layer → Database
            (dumb, knows nothing about queries)

Our Approach:
User Logic → Mongoose Hooks → Smart Cache → Database
                              (knows query structure)
                              (understands invalidation)
                              (prevents stampedes)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key innovations:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Query-aware invalidation:&lt;/strong&gt; Matches update operations against cached query filters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inflight coalescing:&lt;/strong&gt; Shares database results across concurrent requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch deduplication:&lt;/strong&gt; Groups cache writes, eliminates duplicates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory circuit breakers:&lt;/strong&gt; Prevents OOM by monitoring heap pressure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Event loop protection:&lt;/strong&gt; Prevents background operations from starving requests&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  When to Use This
&lt;/h2&gt;

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

&lt;ul&gt;
&lt;li&gt;High-traffic APIs (100+ req/s)&lt;/li&gt;
&lt;li&gt;Read-heavy workloads (70%+ reads)&lt;/li&gt;
&lt;li&gt;Applications with repeating queries&lt;/li&gt;
&lt;li&gt;Teams that want caching without the complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not needed for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strongly consistent requirements (financial transactions)&lt;/li&gt;
&lt;li&gt;Very low traffic (&amp;lt;10 req/s)&lt;/li&gt;
&lt;li&gt;Queries that are always unique (no repeating patterns)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Numbers: What You Actually Save
&lt;/h2&gt;

&lt;p&gt;On a typical SaaS backend (100 concurrent users, 70% cache hit rate):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Without caching:
├─ Database queries: 3000/sec
├─ MongoDB CPU: 85%+
├─ P99 latency: 500ms
└─ Database cost: $2000/month

With @mongoose-performance-cache:
├─ Database queries: 900/sec (-70%)
├─ MongoDB CPU: 25%
├─ P99 latency: 150ms (-70%)
└─ Database cost: $400/month (-80%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's &lt;strong&gt;$19,200/year&lt;/strong&gt; in saved database costs. Plus your users get &lt;strong&gt;70% faster responses&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Open Sourced This
&lt;/h2&gt;

&lt;p&gt;We built this for production use. It's battle-tested on real traffic. We open sourced it because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Caching shouldn't be hard.&lt;/strong&gt; Teams shouldn't have to solve this themselves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The problem is universal.&lt;/strong&gt; If you use Mongoose at scale, you need this.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration improves everything.&lt;/strong&gt; We want the community to find edge cases we missed.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @mongoose-performance-cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or on Bun:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun add @mongoose-performance-cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Full documentation: &lt;a href="https://github.com/VictorAjadi/mongoose-cache" rel="noopener noreferrer"&gt;https://github.com/VictorAjadi/mongoose-cache&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Questions We Know You Have
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: What about cache invalidation consistency across multiple servers?&lt;/strong&gt;&lt;br&gt;
A: We use Redis pub/sub for distributed invalidation. All instances sync automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I use this with existing caching middleware?&lt;/strong&gt;&lt;br&gt;
A: Yes. Our cache layer is independent. Works alongside other caching strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What happens if Redis goes down?&lt;/strong&gt;&lt;br&gt;
A: Automatic fallback to in-memory cache. No errors. Service continues working.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Will this work with my existing MongoDB queries?&lt;/strong&gt;&lt;br&gt;
A: Yes. Zero code changes needed. Just call &lt;code&gt;applyCacheToQueries(schema)&lt;/code&gt; once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: How do I monitor cache performance?&lt;/strong&gt;&lt;br&gt;
A: Built-in stats: &lt;code&gt;cache.getStats()&lt;/code&gt; returns hits, misses, hit rate, memory usage, etc.&lt;/p&gt;


&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;We're planning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cache analytics:&lt;/strong&gt; Deep insights into query patterns and hit rates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom invalidation strategies:&lt;/strong&gt; Plugin system for complex invalidation logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GraphQL support:&lt;/strong&gt; Automatic caching for GraphQL queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Geospatial query support:&lt;/strong&gt; Currently geo queries ($near, $geoIntersects) are rejected because exact coordinates make caching hard. We're exploring geohash-based caching (round coordinates to varying precision levels) and TTL stratification (shorter TTLs for precise queries). &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-database adaptation:&lt;/strong&gt; The same patterns (stampede protection, smart invalidation, batch optimization) work for any database. Coming next:

&lt;ol&gt;
&lt;li&gt;PostgreSQL (Beta Q1 2025)&lt;/li&gt;
&lt;li&gt;MySQL (Q2 2025)&lt;/li&gt;
&lt;li&gt;DynamoDB, Cassandra, SQLite (Community-driven)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Join Us
&lt;/h2&gt;

&lt;p&gt;This library is open source and actively maintained. Contributions welcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Report bugs or edge cases&lt;/li&gt;
&lt;li&gt;Submit feature requests&lt;/li&gt;
&lt;li&gt;Share your performance results&lt;/li&gt;
&lt;li&gt;Help with documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Caching is hard. But it doesn't have to be.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;@mongoose-performance-cache&lt;/code&gt;, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;2.2x faster responses&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;70% fewer database queries&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero cache invalidation complexity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production-grade reliability&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All with three lines of code.&lt;/p&gt;

&lt;p&gt;Try it on your next project. Or your existing one. Let us know what you think.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Ready to make your Mongoose app faster?&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;npm &lt;span class="nb"&gt;install&lt;/span&gt; @mongoose-performance-cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Happy caching! 🚀&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Questions? Found a bug? Have a feature idea?&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Open an issue on GitHub or reach out to us on LinkedIn.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Performance numbers based on stress testing with 50 concurrent clients on Lenovo 14 Ada (2-core @ 1.2GHz, 5.88GB RAM). Results may vary based on hardware, query complexity, and data size.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>node</category>
      <category>performance</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Enhance Your React Applications with cards-slider-react-lib : A Feature-Rich Card Slider Library</title>
      <dc:creator>Victor Ajadi</dc:creator>
      <pubDate>Sun, 23 Jun 2024 22:26:08 +0000</pubDate>
      <link>https://dev.to/victor_ajadi_21b5913f79f6/enhance-your-react-applications-with-cards-slider-react-lib-a-feature-rich-card-slider-library-m6m</link>
      <guid>https://dev.to/victor_ajadi_21b5913f79f6/enhance-your-react-applications-with-cards-slider-react-lib-a-feature-rich-card-slider-library-m6m</guid>
      <description>&lt;p&gt;&lt;strong&gt;cards-slider-react-lib: A Customizable and Responsive React Slider Component&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;card-slider-react-lib&lt;/code&gt; library provides a powerful and versatile React component for creating interactive and visually appealing card sliders in your web applications. This article delves into the features, usage, and customization options offered by &lt;code&gt;card-slider-react-lib&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Key Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Responsive Design&lt;/strong&gt;: &lt;code&gt;card-slider-react-lib&lt;/code&gt; automatically adapts the layout to display an optimal number of cards per view based on the user's screen size. This ensures a seamless experience across various devices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Highly Customizable&lt;/strong&gt;: The library allows you to define the content of your cards, customize the number of cards displayed per view, and configure various other properties to match your specific requirements. You can even create custom card components for a truly unique look and feel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effortless Card Management&lt;/strong&gt;: &lt;code&gt;card-slider-react-lib&lt;/code&gt; efficiently arranges your cards dynamically based on the current index, creating a smooth and continuous sliding effect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Navigation&lt;/strong&gt;: The component comes with built-in navigation buttons that enable users to easily navigate through the cards, either forward or backward. You can also customize the color of these buttons for better integration with your application's design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Properties (Props) for Customization:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;array (Required)&lt;/strong&gt;: This is a mandatory property that takes an array of objects. Each object represents the content of a single card in your slider. The properties within these objects will be available as props in your custom card component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cardNumPerView (Optional)&lt;/strong&gt;: This prop allows you to control the number of cards displayed per view. It provides manual control over the layout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;autoArrange (Optional, default: false)&lt;/strong&gt;: When enabled, this prop automatically adjusts the number of cards displayed based on the screen size, ensuring responsiveness. It overrides cardNumPerView when set to true.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buttonColor (Optional, default: '#000000')&lt;/strong&gt;: This prop lets you customize the color of the navigation buttons to match your application's color scheme.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buttonWidth (Optional, default: '54px')&lt;/strong&gt;: Set the width of the navigation buttons using CSS measurements (e.g., 'px', 'em').&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buttonHeight (Optional, default: '54px')&lt;/strong&gt;: Set the height of the navigation buttons using CSS measurements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CustomCard&lt;/strong&gt;: This is where you define your custom card component. It receives any props you pass within the &lt;code&gt;&amp;lt;CardSlider&amp;gt;&lt;/code&gt;tag. Refer to the implementation of your CustomCard component for specific prop usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LeftSvgIcon (Optional)&lt;/strong&gt;: This prop allows you to override the default left navigation button with your custom SVG icon component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RightSvgIcon (Optional)&lt;/strong&gt;: Similarly, you can override the default right navigation button with your custom SVG icon component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;slideTimeInterval (Optional, default: 3240)&lt;/strong&gt;: This prop sets the interval (in milliseconds) at which the slider auto-slides in an infinite loop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;allowSlidePerInterval (Optional)&lt;/strong&gt;: When enabled (true), this prop allows the slider to auto-slide without requiring users to click the navigation buttons. It also pauses auto-sliding when the user hovers over the slider, improving performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cardSpacing&lt;/strong&gt;: this is use to give space to each card or image-card for customized display "gap"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buttonPosition&lt;/strong&gt;: used to position the button around the slider, &lt;code&gt;middle&lt;/code&gt; or &lt;code&gt;middle-bottom&lt;/code&gt; or &lt;code&gt;middle-top&lt;/code&gt; , default positioned at the &lt;code&gt;right and left end&lt;/code&gt; of the slider container.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;buttonPositionGap&lt;/strong&gt;: when a value is passed here, it gives space to the navigation button relative to the &lt;code&gt;buttonPosition&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Card Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The provided example demonstrates the structure of a custom card component (&lt;code&gt;CustomCard&lt;/code&gt;) that you can use with &lt;code&gt;cards-slider-react-lib&lt;/code&gt;. This component renders the card content based on the props received from the &lt;code&gt;CardSlider&lt;/code&gt;component.&lt;/p&gt;

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

&lt;p&gt;The usage section showcases how to integrate the &lt;code&gt;CardSlider&lt;/code&gt; component into your React application. It demonstrates how to define card data, customize props, and create a custom card component.&lt;/p&gt;

&lt;p&gt;Installation:&lt;/p&gt;

&lt;p&gt;To install &lt;code&gt;cards-slider-react-lib&lt;/code&gt;, use npm or yarn:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Bash&lt;br&gt;
npm install cards-slider-react-lib&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Bash&lt;br&gt;
yarn add cards-slider-react-lib&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;Here's an example of integrating &lt;code&gt;CardSlider&lt;/code&gt; into your React application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { CardSlider } from 'cards-slider-react-lib';
import CustomCard from './CustomCard'; // Your custom card component

const cardData = [
  { id: 1, title: 'Card 1', content: 'Content 1' },
  { id: 2, title: 'Card 2', content: 'Content 2' },
  { id: 3, title: 'Card 3', content: 'Content 3' },
  // ... more card data
];

function App() {
  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;CardSlider
        `array={cardData}`
        `cardNumPerView={3}` // Or use autoArrange={true} for auto- 
        adjustment
        `buttonColor="#ff5733"`
        `buttonWidth="50px"`
        `buttonHeight="50px"`
        `CardComponent={(props) =&amp;gt; &amp;lt;CustomCard {...props}
        additionalProp="1" /&amp;gt;}`
        `cardSpacing={'30px'}` //this is use to give space to each card or 
        image-card for customized display "gap"
        `buttonPosition={'middle'}` or middle-bottom or middle-top, default 
        positioned at the end of the slider container 
        `buttonPositionGap={'10px'}` //when a value is passed here, it 
        gives space to the navigation button relative to the 
        buttonPosition
        // Other customization options...
      /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Comparison to Other Card Slider Libraries:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Several React libraries offer card slider functionalities. Here's a brief comparison of &lt;code&gt;cards-slider-react-lib&lt;/code&gt; with two popular alternatives:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cs = cards-slider-react-lib&lt;br&gt;
rsp=React Swiper&lt;br&gt;
rs=React Slick&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Feature             cs              rsp           rs
Responsiveness          Yes         Yes       Yes
Customization           High            High          High
Navigation Btn          Built-in    Optional      Optional
Autoplay            Optional    Yes       Yes
Touch Support           Yes         Yes       Yes
Documentation           Moderate    Good          Good
Ease of Use         Moderate    Moderate      Moderate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Additional Details:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dynamic Screen Size Handling: As mentioned earlier, &lt;code&gt;card-slider-react-lib&lt;/code&gt; employs breakpoints to automatically adjust the number of cards displayed per view based on screen size. Here's a breakdown of the default breakpoints:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extra Small&lt;/strong&gt;: 1 card&lt;br&gt;
&lt;strong&gt;Small&lt;/strong&gt;: 2 cards&lt;br&gt;
&lt;strong&gt;Medium&lt;/strong&gt;: 3 cards&lt;br&gt;
&lt;strong&gt;Large&lt;/strong&gt;: 4 cards&lt;/p&gt;

&lt;p&gt;By leveraging &lt;code&gt;card-slider-react-lib&lt;/code&gt; , you can create visually appealing and interactive card sliders that enhance the user experience in your React applications. Its flexibility and customization options allow you to tailor the component to your specific design needs and data structures.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Video Playback Made Easy: Unleash the Power of the New MVP VideoPlayer Component</title>
      <dc:creator>Victor Ajadi</dc:creator>
      <pubDate>Sun, 23 Jun 2024 00:45:28 +0000</pubDate>
      <link>https://dev.to/victor_ajadi_21b5913f79f6/react-video-playback-made-easy-unleash-the-power-of-the-videoplayer-component-3fo7</link>
      <guid>https://dev.to/victor_ajadi_21b5913f79f6/react-video-playback-made-easy-unleash-the-power-of-the-videoplayer-component-3fo7</guid>
      <description>&lt;h2&gt;
  
  
  Introducing the VideoPlayer Component: A Powerful and Customizable Video Playback Solution for React with Keyboard Navigation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Empowering Your React Applications with Enhanced Video Playback&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This project introduces the VideoPlayer component, a robust and configurable video playback solution designed specifically for React applications. It goes beyond basic video display, offering a rich set of features that elevate the user experience and cater to diverse project needs, including built-in keyboard navigation for accessibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features and Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seamless Integration&lt;/strong&gt;: Leverages the power of React for effortless incorporation into your application's UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Controls&lt;/strong&gt;: Provides a wide range of built-in controls, including play/pause, speed adjustment (if supported by the video format), full screen, theater mode, picture-in-picture, caption support, and keyboard navigation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization Flexibility&lt;/strong&gt;: Empowers developers to tailor the player's functionality by enabling or disabling specific controls as needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlined Configuration&lt;/strong&gt;: Simplifies player setup through intuitive props that control various behaviors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subtitle Support&lt;/strong&gt;: Enhances accessibility and caters to multilingual audiences by allowing subtitle file upload in popular formats like .srt and .vtt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable Icons&lt;/strong&gt;: Offers the ability to inject custom SVG icons for backward and forward seek buttons for a cohesive visual experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optional Features&lt;/strong&gt;: Provides flexibility with optional props like allowFrame for specifying iframe embedding and video preview on timeline hover.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keyboard Navigation&lt;/strong&gt;: Supports essential keyboard shortcuts for play/pause, full screen, theater mode, mute, and seeking backward/forward using arrow keys or specific letters (e.g., "j", "l").&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Comparison with Other React Video Players:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Several React video player libraries exist, each with its strengths and weaknesses. Here's a brief comparison with a few popular options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React Player&lt;/strong&gt;: Offers a wide range of features, including quality selection, autoplay, and custom controls, but might have a steeper learning curve.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video-React&lt;/strong&gt;: A lightweight and customizable library with good documentation, but may lack some advanced features like picture-in-picture.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VideoPlayer&lt;/code&gt; &lt;strong&gt;(This Library)&lt;/strong&gt;: Provides a good balance of features and ease of use, with built-in navigation, subtitle support, and optional iframe embedding. However, it currently doesn't offer functionalities like quality selection or auto-generated captions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best choice for your project depends on your specific requirements and priorities. Consider factors like feature set, ease of use, and community support when making your decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installation and Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To install the VideoPlayer library in your React project, use npm:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install lib-react-youtube-player&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Usage Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The following code snippet showcases a basic implementation of the &lt;code&gt;VideoPlayer&lt;/code&gt; component within a React application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Import VideoPlayer from the library

import { VideoPlayer } from 'lib-react-youtube-player';

// Import the video file

import videoFile from './assets/video/Learn useRef in 11 Minutes.mp4';

function App() {

  return (

    &amp;lt;div className="App"&amp;gt;

      {/* Render the VideoPlayer component */}

      &amp;lt;VideoPlayer
        speedbtnProp={true} // Enable speed control button

        fullscreenProp={true} // Enable full screen button

        theaterProp={true} // Enable theater mode button

        pipProp={true} // Enable picture-in-picture button

        captionbtnProp // Enable caption/subtitle button

        backwardBtn={false} // Disable backward seek button

        forwardBtn={false} // Disable forward seek button

        videoFile={videoFile} // Specify the video file path

        allowFrame={true} // Enable iframe embedding (optional)

        LeftBackwardSvgIcon={() =&amp;gt; { // Provide custom backward seek SVG here }}

        RightForwardSvgIcon={() =&amp;gt; { // Provide custom forward seek SVG here }}

        subtitleFile={'./assets/srt/Learn useRef in 11 Minutes.srt'} // Default subtitle file (optional)

      /&amp;gt;

    &amp;lt;/div&amp;gt;

  );

}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Faj6vbsuulno6aljc552y.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%2Faj6vbsuulno6aljc552y.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import Statements:&lt;/strong&gt; We import the VideoPlayer component from the &lt;code&gt;'lib-react-youtube-player'&lt;/code&gt; library and the video file (Learn useRef in 11 Minutes.mp4) using import statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Component:&lt;/strong&gt; The App function is the main component of our React application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rendering the VideoPlayer:&lt;/strong&gt; Inside the App component's JSX, we render the VideoPlayer component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring Props:&lt;/strong&gt; We configure the VideoPlayer component using various props to enable or disable specific controls, specify the video file, and activate optional features like iframe embedding.&lt;/p&gt;

&lt;p&gt;We encourage you to explore the &lt;code&gt;VideoPlayer&lt;/code&gt; component further and consider incorporating it into your React projects. If you have any questions or feedback, feel free to reach out to us via email at &lt;a href="https://dev.tourl"&gt;victorajadi2004@gmail.com&lt;/a&gt; or connect with us on LinkedIn &lt;a href="https://dev.tourl"&gt;www.https://www.linkedin.com/in/zemon-dev/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mimicking YouTube Functionality:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;VideoPlayer&lt;/code&gt; component aims to offer a similar user experience to YouTube in several aspects, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Play/Pause functionality with keyboard shortcuts (spacebar or "k").&lt;/li&gt;
&lt;li&gt;Full screen mode toggle with keyboard shortcut ("f").&lt;/li&gt;
&lt;li&gt;Theater mode toggle with keyboard shortcut ("t").&lt;/li&gt;
&lt;li&gt;Mute toggle with keyboard shortcut ("m").&lt;/li&gt;
&lt;li&gt;Seeking backward and forward using arrow keys or specific letters ("j" for 5 seconds backward, "l" for 5 seconds forward).&lt;/li&gt;
&lt;li&gt;Subtitle support through user-uploaded .srt and .vtt files, activated by the caption button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Iframe Preview (Optional):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;VideoPlayer&lt;/code&gt; offers the optional &lt;code&gt;allowFrame&lt;/code&gt; prop, which enables you to embed the video within an iframe. This can be useful for providing a preview image on the timeline when hovering, similar to YouTube's functionality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Currently, the library doesn't support video quality selection, unlike YouTube.&lt;/li&gt;
&lt;li&gt;It relies on user-uploaded subtitle files and doesn't offer auto-generated captions like YouTube.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're continuously improving the &lt;code&gt;VideoPlayer&lt;/code&gt; component, and these features might be added in future updates.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;VideoPlayer&lt;/code&gt; component provides a versatile and user-friendly solution for video playback in your React applications. Its intuitive design, keyboard navigation accessibility, and customizable features make it a valuable asset in your development toolkit. Explore the component further to personalize video experiences and enhance your React projects.&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
