<?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: Rupanshi Chawda</title>
    <description>The latest articles on DEV Community by Rupanshi Chawda (@rupanshichawda).</description>
    <link>https://dev.to/rupanshichawda</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F467974%2Fd0163567-b90d-44fd-ab68-2b2ce7579cdf.jpeg</url>
      <title>DEV Community: Rupanshi Chawda</title>
      <link>https://dev.to/rupanshichawda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rupanshichawda"/>
    <language>en</language>
    <item>
      <title>Archiving MongoDB Data at Scale: A Practical Guide</title>
      <dc:creator>Rupanshi Chawda</dc:creator>
      <pubDate>Sun, 02 Aug 2026 14:02:07 +0000</pubDate>
      <link>https://dev.to/rupanshichawda/archiving-mongodb-data-at-scale-a-practical-guide-3bhj</link>
      <guid>https://dev.to/rupanshichawda/archiving-mongodb-data-at-scale-a-practical-guide-3bhj</guid>
      <description>&lt;p&gt;Archival is one of those problems that looks simple until your production database starts hitting hundreds of millions of documents. At that point, the naive "fetch everything, dump it somewhere" approach falls apart fast — and you need a system designed for scale from the ground up.&lt;/p&gt;

&lt;p&gt;This post covers the key engineering decisions we made when building a MongoDB archival system that handles large datasets without bringing production down.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;Archival sounds simple: identify old data, export it to cold storage, delete it from the production database. But doing this at scale introduces several hard problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Memory pressure&lt;/strong&gt;: You can't load millions of documents into the JVM heap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt;: Running archival in a single thread is too slow; running it unconstrained kills your database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Correctness&lt;/strong&gt;: You need to verify data was safely exported &lt;em&gt;before&lt;/em&gt; deleting it from production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tenancy&lt;/strong&gt;: In a SaaS system, each tenant's data must be processed independently and in isolation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Streaming With Cursors, Not Loading Into Memory
&lt;/h2&gt;

&lt;p&gt;The most important decision in the whole system is this: &lt;strong&gt;never load all documents into memory&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Document&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;allDocs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongoTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// OOM waiting to happen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use MongoDB's streaming cursor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;cursorBatchSize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// fetch 2000 docs at a time from the server&lt;/span&gt;
&lt;span class="nc"&gt;Stream&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;entityStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongoTemplate&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MyEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cursor fetches batches of documents from MongoDB on demand. Combined with Java's &lt;code&gt;Stream&lt;/code&gt; API, data flows directly from MongoDB into a CSV serializer and then into a cloud storage upload — without ever materializing the full result set in memory.&lt;/p&gt;

&lt;p&gt;The pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MongoDB Cursor (batch=2000)
    → Stream&amp;lt;Entity&amp;gt;
    → CSV row serializer
    → InputStream (piped)
    → Cloud Storage upload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At any point in time, the JVM holds at most one cursor batch. This keeps memory usage flat regardless of how many documents you're archiving.&lt;/p&gt;




&lt;h2&gt;
  
  
  A State Machine for Reliability
&lt;/h2&gt;

&lt;p&gt;Because archival spans multiple steps — export, verify, purge — we model each archival job as a state machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;READY_FOR_ARCHIVAL
    → ARCHIVAL_IN_PROGRESS   (streaming export to cloud storage)
    → READY_FOR_VERIFICATION (export complete, integrity check pending)
    → READY_FOR_PURGE        (verified, safe to delete)
    → PURGED_FROM_TABLE      (deleted from production, metadata saved)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage is independently retryable. If export fails halfway, the run stays in &lt;code&gt;ARCHIVAL_IN_PROGRESS&lt;/code&gt; and gets retried without re-running discovery. If verification fails, you don't purge. The state machine makes the system resilient to partial failures without complex rollback logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thread Pools Per Stage
&lt;/h2&gt;

&lt;p&gt;Different stages of archival have different resource profiles. Export is I/O-heavy; purge involves many small delete operations. Rather than using a single shared executor, we run &lt;strong&gt;separate fixed thread pools per stage&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Bean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"archivalRunTaskExecutor"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="nf"&gt;archivalRunTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// concurrent exports&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Bean&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"purgeTaskExecutor"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Executor&lt;/span&gt; &lt;span class="nf"&gt;purgeTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Executors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newFixedThreadPool&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// concurrent deletes&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a job trigger fires, it fetches a batch of pending runs and fans them out to the appropriate executor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;pendingRuns&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forEach&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;archivalRunTaskExecutor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;processArchivalRun&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fire-and-forget pattern keeps the job trigger fast and lets the thread pool manage concurrency. You tune pool sizes independently based on observed bottlenecks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Batched Deletes, Not Bulk Deletes
&lt;/h2&gt;

&lt;p&gt;When purging documents from MongoDB after a verified export, deleting millions of records in one operation is dangerous — it holds locks and can spike replication lag. We delete in small batches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="no"&gt;DELETE_BATCH_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="no"&gt;DELETE_BATCH_SIZE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;subList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;DELETE_BATCH_SIZE&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="o"&gt;()));&lt;/span&gt;
    &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deleteMany&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Criteria&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each batch is a separate operation. This gives the database breathing room between deletes and keeps replication healthy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quota-Based Throttling
&lt;/h2&gt;

&lt;p&gt;In a multi-tenant system, a single large tenant shouldn't be able to exhaust all archival capacity. We track the total number of IDs currently "in-flight" (discovered but not yet purged) and gate new discovery behind a quota check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;currentInFlight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getInFlightIdsCount&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;maxInFlightIds&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;currentInFlight&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;available&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// backpressure: pause discovery until prior runs complete&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This acts as natural backpressure. If the system falls behind, discovery pauses until the pipeline drains. It prevents the archival metadata store from ballooning while export/purge catch up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verification Before Purge
&lt;/h2&gt;

&lt;p&gt;We never purge based on the assumption that export succeeded. Before any document is deleted, the exported file is read back and IDs are verified against what's in the archival metadata store. To avoid loading the entire CSV into memory, we use a chunked iterator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;CsvChunkIterator&lt;/span&gt; &lt;span class="n"&gt;iterator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getCsvColumnIterator&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileUri&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primaryKeyColumn&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunkSizeBytes&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;hasNext&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;iterator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;nextChunk&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;verifyIdsExist&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;runId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// batch DB lookup&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only after all IDs are verified does the run transition to &lt;code&gt;READY_FOR_PURGE&lt;/code&gt;. This gives you a hard guarantee: data is only deleted from production once confirmed safe in cold storage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Memory pressure from large datasets&lt;/td&gt;
&lt;td&gt;Cursor-based streaming, never load full result set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Partial failure recovery&lt;/td&gt;
&lt;td&gt;State machine with idempotent, retryable stages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency without overloading DB&lt;/td&gt;
&lt;td&gt;Fixed thread pools per stage, tuned independently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safe deletes at scale&lt;/td&gt;
&lt;td&gt;Batched deletes with configurable batch size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runaway discovery&lt;/td&gt;
&lt;td&gt;In-flight ID quota with backpressure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Correctness guarantees&lt;/td&gt;
&lt;td&gt;Verify export before purge, chunk-streamed verification&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The common theme: &lt;strong&gt;never do work in bulk that can cascade&lt;/strong&gt;. Whether it's memory allocation, database deletes, or thread scheduling — bounding the work at each step is what keeps the system stable under load.&lt;/p&gt;




&lt;p&gt;If you're building something similar, the most important thing to get right first is the streaming pipeline. Once you've eliminated in-memory loading, the rest of the system — state machines, thread pools, batching — falls into place naturally.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>microservices</category>
      <category>java</category>
      <category>backend</category>
    </item>
    <item>
      <title>Flutter PDF Viewer - Automated using GitHubActions</title>
      <dc:creator>Rupanshi Chawda</dc:creator>
      <pubDate>Tue, 15 Sep 2020 17:27:01 +0000</pubDate>
      <link>https://dev.to/rupanshichawda/flutter-pdf-viewer-automated-using-githubactions-2167</link>
      <guid>https://dev.to/rupanshichawda/flutter-pdf-viewer-automated-using-githubactions-2167</guid>
      <description>&lt;p&gt;View PDF directly into your Flutter App using - &lt;em&gt;flutter_plugin_pdf_viewer&lt;/em&gt; .&lt;/p&gt;

&lt;p&gt;You can implement this using the flutter plugin and load a PDF directly into your Flutter App. It works offline too as it downloads the pdf and then loads it into the app.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;The GitHub Action PDF_Flutter CI is designed to automate certain tasks for the developers making their life less complicated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configuring Flutter version&lt;/li&gt;
&lt;li&gt;Installing dependencies&lt;/li&gt;
&lt;li&gt;Run Test&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves and Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File and Link to Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: PDF_Flutter CI

# This workflow is triggered on pushes to the repository.

on:
  push:
    branches:
    - master

# on: push    # Default will running for every branch.

jobs:
  build:
    # This job will run on ubuntu virtual machine
    runs-on: ubuntu-latest
    steps:

    # Setup Java environment in order to build the Android app.
    - uses: actions/checkout@v1
    - uses: actions/setup-java@v1
      with:
        java-version: '12.x'

    # Setup the flutter environment.
    - uses: subosito/flutter-action@v1
      with:
        channel: 'stable' # 'dev', 'alpha', default to: 'stable'
        flutter-version: '1.17.5' # you can also specify exact version of flutter

    # Get flutter dependencies.
    - name: Install dependencies
      run: flutter pub get
    - name: run tests
      run: flutter pub run tests

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

&lt;/div&gt;



&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rupanshi-chawda"&gt;
        rupanshi-chawda
      &lt;/a&gt; / &lt;a href="https://github.com/rupanshi-chawda/Pdf-Viewer-in-Flutter"&gt;
        Pdf-Viewer-in-Flutter
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;h1&gt;
Flutter PDF Viewer&lt;/h1&gt;
&lt;p&gt;View PDF directly into your Flutter App using -&lt;/p&gt;
&lt;h4&gt;
flutter_plugin_pdf_viewer&lt;/h4&gt;
&lt;h2&gt;
Implementation -&lt;/h2&gt;
&lt;p&gt;You can implement this using the flutter plugin and load a PDF directly into your Flutter App.
It works offline too as it downloads the pdf and then loads it into the app.&lt;/p&gt;
&lt;/div&gt;

  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rupanshi-chawda/Pdf-Viewer-in-Flutter"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/subosito"&gt;
        subosito
      &lt;/a&gt; / &lt;a href="https://github.com/subosito/flutter-action"&gt;
        flutter-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Flutter environment for use in actions. It works on Linux, Windows, and macOS.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;h1&gt;
flutter-action&lt;/h1&gt;
&lt;p&gt;This action sets up a flutter environment for use in actions. It works on Linux, Windows, and macOS.&lt;/p&gt;
&lt;h1&gt;
Usage&lt;/h1&gt;
&lt;div class="highlight highlight-source-yaml position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;steps&lt;/span&gt;:
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v2&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/setup-java@v2&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;distribution&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;zulu&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
    &lt;span class="pl-ent"&gt;java-version&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;11&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;subosito/flutter-action@v1&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;flutter-version&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;2.0.5&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
- &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;flutter pub get&lt;/span&gt;
- &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;flutter test&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Use latest release for particular channel:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;steps&lt;/span&gt;:
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v2&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/setup-java@v2&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;distribution&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;zulu&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
    &lt;span class="pl-ent"&gt;java-version&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;11&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;subosito/flutter-action@v1&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;channel&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;stable&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; or: 'beta', 'dev' or 'master'&lt;/span&gt;
- &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;flutter pub get&lt;/span&gt;
- &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;flutter test&lt;/span&gt;
- &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;flutter build apk&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Use latest release for particular version and/or channel:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;steps&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v2&lt;/span&gt;
- &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/setup-java@v2&lt;/span&gt;
  &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;distribution&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;zulu&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/subosito/flutter-action"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h6&gt;
  
  
  &lt;em&gt;Made with love by rupanshi-chawda&lt;/em&gt;
&lt;/h6&gt;

</description>
      <category>actionshackathon</category>
      <category>flutter</category>
      <category>github</category>
      <category>dart</category>
    </item>
  </channel>
</rss>
