<?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: Viacheslav Soldatov</title>
    <description>The latest articles on DEV Community by Viacheslav Soldatov (@vsoldatov).</description>
    <link>https://dev.to/vsoldatov</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%2F3408118%2Fcda62ade-dc34-4c0e-8692-da82856aa64b.jpg</url>
      <title>DEV Community: Viacheslav Soldatov</title>
      <link>https://dev.to/vsoldatov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vsoldatov"/>
    <language>en</language>
    <item>
      <title>MemMouse — Enterprise Memory Management</title>
      <dc:creator>Viacheslav Soldatov</dc:creator>
      <pubDate>Mon, 11 Aug 2025 06:39:18 +0000</pubDate>
      <link>https://dev.to/vsoldatov/memmouse-enterprise-memory-management-m9o</link>
      <guid>https://dev.to/vsoldatov/memmouse-enterprise-memory-management-m9o</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/redis-2025-07-23"&gt;Redis AI Challenge&lt;/a&gt;: Beyond the Cache&lt;/em&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;MemMouse&lt;/strong&gt; — a tiny control plane for managing &lt;strong&gt;projects → namespaces → services → policies&lt;/strong&gt; on top of Redis. It’s a dark, glassy Next.js UI that lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create projects and namespaces, set &lt;strong&gt;quota/TTL/eviction&lt;/strong&gt;, freeze/unfreeze writes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Bind services to namespaces via &lt;strong&gt;key patterns, scopes, and rate limits&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Issue/rotate &lt;strong&gt;service tokens&lt;/strong&gt;, and &lt;strong&gt;download a ready-to-use agent config&lt;/strong&gt; for your microservice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;See a &lt;strong&gt;project overview&lt;/strong&gt; (capacity, inventory, ops snapshot, top namespaces, recent events).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a hackathon demo, but the architecture is production-leaning: Redis is the &lt;strong&gt;primary metadata store&lt;/strong&gt;, the UI is cleanly split into a control plane (Next.js API routes) and a data plane (Redis).&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;code&gt;https://github.com/simplizio/memmouse-next-ui&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Docker Hub&lt;/strong&gt;: &lt;code&gt;docker pull simplizio/memmouse-next-ui:latest&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run with Docker Compose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# docker-compose.yml in repo&lt;/span&gt;
docker compose pull
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="c"&gt;# open http://localhost:3000/projects&lt;/span&gt;
&lt;span class="c"&gt;# (optional) seed demo data:&lt;/span&gt;
&lt;span class="c"&gt;# curl "http://localhost:3000/api/dev/seed?force=1&amp;amp;drop=1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;Redis by itself is a blank slate. You can store anything you want inside it, but the organization of data is entirely left to the developer. Key prefixes, access policies, naming conventions — everything is tuned ad-hoc, depending on the project and team. As a result, what you get is a huge messy pile that existing monitoring tools can barely make sense of.&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%2Fyksdgqycpdh5yo97u6ea.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%2Fyksdgqycpdh5yo97u6ea.png" alt="the giant pile of fragments" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We propose to treat this pile as something that deserves its own service. Inside each project, data is organized into namespaces of a given size, with well-defined access for microservices.&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%2Ftpiu028snpa08jftc6mu.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%2Ftpiu028snpa08jftc6mu.png" alt="neatly labeled boxes on the shelf" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This principle allows the process of memory management to be centralized at scale. Policies can be automated and integrated into the corporate landscape — whether it’s cloud environments or custom DevOps setups.&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%2F2do90fegxgn56lxsi22i.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%2F2do90fegxgn56lxsi22i.png" alt="the factory floor of Memory Allocation Dept." width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By applying this tool, teams gain real control and observability over their entire system. In microservice architectures, achieving that is usually a costly and error-prone effort. With our approach, life just became a little easier.&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%2Febzkdbpq4n5hu8sbszkq.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%2Febzkdbpq4n5hu8sbszkq.png" alt="the mouse overseeing with binoculars" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Screenshots:&lt;/em&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Projects overview (capacity bar, counts, ops, top namespaces)
&lt;/h3&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%2Ftad2nmiss7tj8fupplwx.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%2Ftad2nmiss7tj8fupplwx.png" alt="Projects overview" width="800" height="267"&gt;&lt;/a&gt; &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%2Fh2karij78isgeg9glok1.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%2Fh2karij78isgeg9glok1.png" alt="Project memory landscape" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespace details (policy edit, usage bar, bindings)
&lt;/h3&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%2F7oufg0dzgoes4nr2j77i.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%2F7oufg0dzgoes4nr2j77i.png" alt="Namespaces overview" width="800" height="306"&gt;&lt;/a&gt;&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%2F9ijx5z7dswojy5o5p3un.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%2F9ijx5z7dswojy5o5p3un.png" alt="Namespace memory details" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Services (list + details with token rotate &amp;amp; download config)
&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%2Fmizqmtsrcizzw6sfj661.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%2Fmizqmtsrcizzw6sfj661.png" alt="Service list" width="800" height="306"&gt;&lt;/a&gt;    &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%2Fddbxrfhcvlgb6yvliwed.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%2Fddbxrfhcvlgb6yvliwed.png" alt="Service memory access management" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Redis 8
&lt;/h2&gt;

&lt;p&gt;I used Redis &lt;strong&gt;beyond caching&lt;/strong&gt; — as the &lt;strong&gt;control-plane database&lt;/strong&gt; and foundation for future streaming/events. Concretely:&lt;/p&gt;

&lt;h3&gt;
  
  
  Data model in Redis
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strings&lt;/strong&gt; store JSON records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mm:project:{id}&lt;/code&gt;, &lt;code&gt;mm:namespace:{projectId}:{nsId}&lt;/code&gt;, &lt;code&gt;mm:binding:{projectId}:{nsId}:{serviceId}&lt;/code&gt;, &lt;code&gt;mm:service:{projectId}:{serviceId}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Sets&lt;/strong&gt; act as indexes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;mm:idx:projects&lt;/code&gt; (project ids)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mm:idx:namespaces:{projectId}&lt;/code&gt; (ns ids per project)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mm:idx:bindings:{projectId}:{nsId}&lt;/code&gt; (service ids per ns)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reverse index&lt;/strong&gt;: &lt;code&gt;mm:idx:bindings_by_service:{projectId}:{serviceId}&lt;/code&gt; (ns ids per service)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atomicity&lt;/strong&gt;: updates touch both forward &amp;amp; reverse indexes in a single &lt;code&gt;MULTI/EXEC&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Throughput&lt;/strong&gt;: reads of many records use &lt;strong&gt;pipelines&lt;/strong&gt;; admin scans use &lt;code&gt;SCAN&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Durability&lt;/strong&gt;: demo uses AOF (&lt;code&gt;appendonly yes&lt;/code&gt;) in Docker; can flip to &lt;code&gt;tmpfs&lt;/code&gt; for ultra-fast dev runs.&lt;br&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mm:project:...                  -&amp;gt; JSON
mm:idx:projects                 -&amp;gt; Set(projectId)
mm:namespace:&amp;lt;projId&amp;gt;:&amp;lt;nsId&amp;gt;    -&amp;gt; JSON
mm:idx:namespaces:&amp;lt;projId&amp;gt;      -&amp;gt; Set(nsId)
mm:binding:&amp;lt;projId&amp;gt;:&amp;lt;nsId&amp;gt;:&amp;lt;svcId&amp;gt; -&amp;gt; JSON
mm:idx:bindings:&amp;lt;projId&amp;gt;:&amp;lt;nsId&amp;gt; -&amp;gt; Set(serviceId)
mm:idx:bindings_by_service:&amp;lt;projId&amp;gt;:&amp;lt;svcId&amp;gt; -&amp;gt; Set(nsId)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Control plane → Agent handoff
&lt;/h3&gt;

&lt;p&gt;Each service has tokens and can fetch a &lt;strong&gt;signed-by-us config&lt;/strong&gt; (demo uses Bearer token check) from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;GET&lt;/span&gt; &lt;span class="sr"&gt;/api/&lt;/span&gt;&lt;span class="n"&gt;projects&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="ss"&gt;:projectId&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="ss"&gt;:serviceId&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;
&lt;span class="no"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;Bearer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The config contains Redis endpoint, bindings (patterns, permissions, scopes, rate limits), and a telemetry target. A tiny FastAPI agent can bootstrap itself from this and enforce write patterns client-side while we work toward server-side enforcement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Redis (and what’s next)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple, expressive primitives&lt;/strong&gt; (Strings/Sets) make schema evolution trivial.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast fan-out&lt;/strong&gt; with pipelines for listing and dashboards.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Paves the road for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Streams&lt;/strong&gt; for CDC + replay/DLQ,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pub/Sub&lt;/strong&gt; for live UI events,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ACL materialization&lt;/strong&gt; per binding (key patterns → Redis users),&lt;/li&gt;
&lt;li&gt;Backups via RDB/AOF snapshots per namespace.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Team note: Solo submission. &lt;br&gt;
&lt;a class="mentioned-user" href="https://dev.to/vsoldatov"&gt;@vsoldatov&lt;/a&gt; at Dev.to&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/viacheslav-soldatov-472012100/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>redischallenge</category>
      <category>devchallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
