<?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>Forem: Siddhartha Varma</title>
    <description>The latest articles on Forem by Siddhartha Varma (@bro3886).</description>
    <link>https://forem.com/bro3886</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%2F650159%2Fc88167c3-b1a1-4557-ad9d-f6eb7645f11a.png</url>
      <title>Forem: Siddhartha Varma</title>
      <link>https://forem.com/bro3886</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bro3886"/>
    <language>en</language>
    <item>
      <title>A deep dive into Dynamo's architecture and scale</title>
      <dc:creator>Siddhartha Varma</dc:creator>
      <pubDate>Wed, 05 Feb 2025 09:54:14 +0000</pubDate>
      <link>https://forem.com/bro3886/a-deep-dive-into-dynamos-architecture-and-scale-51ma</link>
      <guid>https://forem.com/bro3886/a-deep-dive-into-dynamos-architecture-and-scale-51ma</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;On Prime Day 2021, Amazon's systems made trillions of API calls to DynamoDB, peaking at 89.2M requests per second (RPS), all while maintaining single digit millisecond latency. Yet, many developers struggle with database scaling issues that DynamoDB was created to solve.&lt;/p&gt;

&lt;p&gt;Having worked extensively with DynamoDB at &lt;a href="https://blog.zomato.com/category/technology" rel="noopener noreferrer"&gt;Zomato&lt;/a&gt; , I have also hit the same roadblocks, like hot partitions throttling applications, costs spiraling due to over-provisioning and data models that worked perfectly in other databases suddenly becoming performance bottlenecks. These challenges often stem from approaching DynamoDB with a traditional database mindset.&lt;/p&gt;

&lt;p&gt;In this article, I'll dive into DynamoDB's architecture through a system design perspective. We'll explore the fundamentals of dynamo, how it's scaling and performance management differs from traditional databases, and more importantly - how to architect your applications to harness the full power of dynamo. Whether you're debugging performance issues, optimizing costs, or just starting with DynamoDB, understanding these internals will help you make better design decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding DynamoDB's core principles
&lt;/h2&gt;

&lt;p&gt;At the heart of DynamoDB's robustness and scalability lie six core principles around which it was architected. These principles prioritize simplicity, predictability, and reliability. Let's explore each, starting with perhaps the most counterintuitive&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Predictability over peak performance
&lt;/h3&gt;

&lt;p&gt;This sounds very counterintuitive from a software perspective. Shouldn't one chase maximum throughput? While other databases also follow this approach, DynamoDB takes a contrarian stance - predictable performance matters more than peak performance.&lt;/p&gt;

&lt;p&gt;If you marinate on this, it does make a lot of sense from a database perspective. What good is a lightning fast database which occasionally hangs for several seconds - even milliseconds? The latency spikes will ultimately affect application performance. DynamoDB's architects recognized this early on and set an ambitious goal - complete all requests with sub 10ms latencies.&lt;/p&gt;

&lt;p&gt;How does it achieve this? Through some clever architectural decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Global Admission Control&lt;/strong&gt; to manage capacity across entire tables, preventing any single partitioning from becoming a bottleneck&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatic partitioning to distribute I/O load evenly, even as access patterns change&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proactive monitoring and rebalancing to prevent resource exhaustion before it impacts performance&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Multi-tenant architecture&lt;/strong&gt; with strict resource isolation ensures consistent performance even under varied workloads&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result - Once &lt;em&gt;properly&lt;/em&gt; configured, applications can rely on consistent performance whether they're handling normal traffic or sudden spikes. No more over-provisioning "just in case" or late-night panic when traffic patterns change.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Multi-tenant Architecture with Isolation
&lt;/h3&gt;

&lt;p&gt;Unlike traditional databases where you might have dedicated instances, DynamoDB takes a different approach - it runs multiple customer's workloads on the same physical machines.&lt;/p&gt;

&lt;p&gt;Now, you might be thinking, does it not introduce the &lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/saas-lens/noisy-neighbor.html" rel="noopener noreferrer"&gt;noisy neighbour problem?&lt;/a&gt; This is where DynamoDB's clever resource management comes in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Reservation&lt;/strong&gt; - Each table gets guaranteed capacity through token bucket allocation. When you provision throughput or use on-demand tables, DynamoDB reserves corresponding resources, ensuring your workload gets its fair share regardless of other tenants&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strict Workload Isolation&lt;/strong&gt; - Storage nodes host replicas from different tables and customers, but use partition-level token buckets to enforce throughput limits. Even if one tenant's workload spikes, it can't consume more than its allocated capacity, protecting other tenants' performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic Load Balancing&lt;/strong&gt; - DynamoDB's autoadmin service continuously monitors storage node utilization. If a node's throughput exceeds a threshold percentage of its maximum capacity, DynamoDB automatically redistributes partitions to maintain balanced load across the fleet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Proactive Capacity Management&lt;/strong&gt; - Rather than waiting for resource exhaustion, DynamoDB tracks consumed capacity trends and automatically rebalances partitions before performance is impacted. Storage nodes independently report when they're approaching capacity limits.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These mechanisms ensure workload isolation between co-resident tables while maintaining high resource utilization. The benefit of this is cost savings, which gets passed down to customers while giving performance guarantees.&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%2Fis2r397dtroxk7ng5c22.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%2Fis2r397dtroxk7ng5c22.png" alt="Multi-tenancy in DynamoDB" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;em&gt;Multi-tenancy in DynamoDB&lt;/em&gt;&lt;/center&gt;

&lt;blockquote&gt;
&lt;p&gt;Autoadmin service is responsible for fleet health, partition health, scaling of tables, and execution of all control plane requests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  3. Boundless Scale for Tables
&lt;/h3&gt;

&lt;p&gt;DynamoDB takes another contrarian approach with this principle. In traditional databases, we often have to carefully plan capacity and manage storage thresholds. Unlike these databases - for DynamoDB there are no predefined limits for the amount of data each table can store. Tables grow elastically to meet the demand of the customers' applications.&lt;/p&gt;

&lt;p&gt;DynamoDB is designed to scale the resources dedicated to a table from several servers to many thousands as needed. How does DynamoDB achieve this seemingly infinite scalability? The secret lies in its partitioning strategy&lt;/p&gt;

&lt;p&gt;When you create a table, DynamoDB splits it into multiple partitions. Each partition being a dedicated slice of storage and compute that's responsible for a specific range of keys. These ranges are organized so that no two partitions overlap (disjoint ranges), and each partition handles all keys within its assigned range (continuous ranges).&lt;/p&gt;

&lt;p&gt;For example, if your table uses numeric keys from 1-100, you might have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Partition A: Keys 1-35&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition B: Keys 36-70&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Partition C: Keys 71-100&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each key range is handled by exactly one partition, with no gaps or overlaps between partitions. As your table grows in size or throughput demands increase, DynamoDB automatically splits these partitions when:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Size:&lt;/strong&gt; When a partition's stored data exceeds its size threshold. This ensures no single partition grows too large to manage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Throughput:&lt;/strong&gt; When a partition's consumed capacity consistently exceeds partition limits. DynamoDB monitors actual usage patterns and splits partitions based on observed traffic, not just size.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This automatic splitting enables tables to scale horizontally as they grow. Each new partition adds more dedicated storage and compute capacity to your table, all managed transparently by DynamoDB.&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%2Fo8q6p4xhdt4vzc377ze4.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%2Fo8q6p4xhdt4vzc377ze4.png" alt="Automatic splitting" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;em&gt;Automatic splitting&lt;/em&gt;&lt;/center&gt;



&lt;h3&gt;
  
  
  4. High Availability
&lt;/h3&gt;

&lt;p&gt;In today's world, even a few minutes of database downtime can severely impact businesses. DynamoDB is architected for high availability, offering a 99.99% SLA for regular tables and an even higher 99.999% SLA for global tables.&lt;/p&gt;

&lt;p&gt;At its core, DynamoDB achieves this through a sophisticated replication strategy. Every partition of your table is replicated across multiple Availability Zones (AZs) - physically separate data centers in the same region. But replication alone isn't enough - it's how DynamoDB manages these replicas that makes the difference.&lt;/p&gt;

&lt;p&gt;Each partition has multiple replicas distributed across different AZs, forming what's called a &lt;strong&gt;replication group&lt;/strong&gt;. Within each group, one replica acts as the leader, coordinating writes and strongly consistent reads.&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%2Fh4vo779ivncols3sfc7i.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%2Fh4vo779ivncols3sfc7i.png" alt="Interaction Between Core Components" width="706" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;em&gt;Interaction Between Core Components&lt;/em&gt;&lt;/center&gt;



&lt;p&gt;Here's how it works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For writes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When a write request arrives, the leader generates a WAL (write ahead log) record&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This record must be persisted by a quorum of replicas before acknowledging the write&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even if one replica fails, as long as the quorum exists, writes continue uninterrupted&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For reads&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Strongly consistent reads are served by the leader&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Eventually consistent reads can be served by any replica&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This flexibility allows it to balance load and maintain availability even during failures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case when things go wrong, DynamoDB has multiple layers of failure protection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fast recovery&lt;/strong&gt; - If a replica becomes unhealthy, DynamoDB quickly adds a "log replica", which is a lightweight replica that only stores recent write logs. This ensures durability while a full replica is being rebuilt.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Smart failure detection&lt;/strong&gt; - Before triggering failovers, replicas check with their peers to confirm if a leader is truly unavailable, preventing disruptions from temporary network issues&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automatic healing&lt;/strong&gt; - DynamoDB's autoadmin service continuously monitors partition health and automatically replaces unhealthy replicas, ensuring your data remains triple-replicated&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fdwr24e63k32kyh6yix9r.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%2Fdwr24e63k32kyh6yix9r.png" alt="Interaction inside a Replication Group" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;&lt;em&gt;Interaction inside a Replication Group&lt;/em&gt;&lt;/center&gt;



&lt;p&gt;DynamoDB maintains this level of availability without requiring any operational overhead from developers. You don't need to configure replication, manage failovers, or worry about cross-AZ communication - it's all handled automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Fully Managed Cloud Service
&lt;/h3&gt;

&lt;p&gt;DynamoDB takes another fundamentally different approach to database management compared to traditional databases - it's fully managed, meaning developers never have to worry about the underlying infrastructure. This principle goes beyond simple automation; it's baked into DynamoDB's core design:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developers interact purely through the DynamoDB API to create tables and perform operations&lt;/li&gt;
&lt;li&gt;No need to think about server provisioning, storage allocation, or cluster configuration&lt;/li&gt;
&lt;li&gt;The service automatically handles resource scaling based on your needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Operational Tasks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All software patching and upgrades happen transparently&lt;/li&gt;
&lt;li&gt;Hardware failures are automatically detected and remediated&lt;/li&gt;
&lt;li&gt;Backups are managed systematically without impacting performance&lt;/li&gt;
&lt;li&gt;Data encryption is handled automatically at rest and in transit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No need to configure distributed database clusters&lt;/li&gt;
&lt;li&gt;Automatic recovery from failures without manual intervention&lt;/li&gt;
&lt;li&gt;Built-in security features like encryption and access control&lt;/li&gt;
&lt;li&gt;Continuous monitoring and maintenance without downtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty of this approach is that developers can focus entirely on their application logic rather than database administration. Whether you're running a small application or handling millions of requests per second, the operational complexity remains zero.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Flexible Use Cases
&lt;/h3&gt;

&lt;p&gt;While DynamoDB is often categorized as a NoSQL database, it's designed with flexibility in mind, accommodating various data models and consistency requirements. This flexibility manifests in several key ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Model Flexibility&lt;/strong&gt; - DynamoDB doesn't force developers into a particular data model or consistency model. DynamoDB tables don't have a fixed schema but instead allow each data item to contain any number of attributes with varying types, including multi-valued attributes. Tables use a key-value or document data model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency Options&lt;/strong&gt; - Developers can choose between eventual or strong consistency for reads, which allows applications to balance performance and consistency reads. You could choose to have strong consistency for critical operations and eventual consistency for better performance when absolute consistency isn't required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Patterns&lt;/strong&gt; - DynamoDB supports both single item operations and range queries, with secondary indexes for flexible access patterns and global tables for low latency multi region access. It also supports ACID transactions across items without compromising the scalability, availability, and performance characteristics of DynamoDB tables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Pitfalls
&lt;/h2&gt;

&lt;p&gt;While DynamoDB's architecture solves many scaling challenges, teams often hit roadblocks when approaching it with a traditional database mindset. Here are common pitfalls to avoid:&lt;/p&gt;

&lt;h3&gt;
  
  
  Poor Partition Key Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using sequential IDs as partition keys, causing write hotspots&lt;/li&gt;
&lt;li&gt;Using too few unique partition keys, leading to throttling&lt;/li&gt;
&lt;li&gt;Using highly correlated values (like dates) that create temporal hotspots&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Approach:&lt;/strong&gt; Choose partition keys with high cardinality and good distribution. Consider composite keys or adding random suffixes for better distribution&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inefficient Access Patterns
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating too many indexes, increasing write costs and complexity&lt;/li&gt;
&lt;li&gt;Not aligning schema with query patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Approach:&lt;/strong&gt; Design your schema around your access patterns. Start with your queries and work backwards to your data model.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Over-Relying on Secondary Indexes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creating an index for every possible query pattern&lt;/li&gt;
&lt;li&gt;Not considering the write amplification cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Approach:&lt;/strong&gt; Use sparse indexes and carefully evaluate the cost-benefit of each index&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Inappropriate Item Size
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Storing items that approach the 400KB limit, not considering item size growth over time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Approach:&lt;/strong&gt; Consider chunking strategies for large items, and plan for data growth.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Having faced these challenges at scale, I'll share our journey of overcoming them in an upcoming article&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Cost Optimization Strategies
&lt;/h2&gt;

&lt;p&gt;One of the most painful lessons teams learn with DynamoDB is how quickly costs can spiral without proper planning. Let's dive into strategies that can help you optimize costs while maintaining performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing Your Capacity Mode
&lt;/h3&gt;

&lt;p&gt;DynamoDB offers two capacity modes, each with its own trade-offs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provisioned capacity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Provisioned Capacity is best for predictable workloads and lowers cost when properly sized. But it requires careful capacity planning and one should also consider using auto scaling to handle traffic variations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On-demand capacity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;On-demand capacity is perfect for unpredictable workloads or development environments where traffic patterns are still unclear. While it might cost more than steady-state workloads, the operational simplicity and peace of mind can be worth the premium.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart Capacity Planning
&lt;/h3&gt;

&lt;p&gt;Success with DynamoDB requires a data-driven approach to capacity planning. Start by monitoring your CloudWatch metrics to understand your usage patterns. Look for daily and weekly trends, seasonal spikes, and any anomalies. If you're just starting out, consider using on-demand capacity during development - the usage data you gather will be invaluable for optimizing costs later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lifecycle Management
&lt;/h3&gt;

&lt;p&gt;Just like cleaning out your closet, regularly reviewing and managing your data can lead to significant savings. Use TTL (Time To Live) for temporary data like session information or logs. For historical data that you need to keep but don't access frequently, consider archiving to S3. Another often-overlooked strategy is using sparse indexes - they not only improve query performance but can significantly reduce storage costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stay Alert: Monitor Your Costs
&lt;/h3&gt;

&lt;p&gt;The best way to avoid cost surprises is to stay vigilant. Set up CloudWatch alarms for throttling events - they're often a sign that your capacity planning needs adjustment. Monitor your consumed capacity against what you've provisioned to identify opportunities for optimization. Track costs at a granular level - by table and index - to understand where your money is going. Most importantly, set up budget alerts to catch any unexpected increases before they become painful surprises.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;DynamoDB's architecture represents a fundamental shift in how we think about databases. Its design principles - from predictable performance to global admission control - weren't chosen arbitrarily, but evolved from real-world challenges of running databases at scale.&lt;/p&gt;

&lt;p&gt;As I've experienced firsthand at Zomato, success with DynamoDB requires embracing these principles rather than fighting them. Whether it's rethinking our partition keys for better distribution, chunking large items for efficient storage, or carefully planning our capacity needs - each decision needs to align with DynamoDB's architectural foundations.&lt;/p&gt;

&lt;p&gt;DynamoDB isn't just another database with a different query language. By understanding it's principles and avoiding common pitfalls, you can harness this same power for your applications, regardless of scale. The effort you invest in understanding its architecture and aligning your design decisions with its principles will pay dividends in scalability, reliability, and operational simplicity.&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.usenix.org/system/files/atc22-elhemali.pdf" rel="noopener noreferrer"&gt;https://www.usenix.org/system/files/atc22-elhemali.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hemantkgupta.medium.com/insights-from-paper-part-i-amazon-dynamodb-a-scalable-predictably-performant-and-fully-6d93dfbfe2fb" rel="noopener noreferrer"&gt;https://hemantkgupta.medium.com/insights-from-paper-part-i-amazon-dynamodb-a-scalable-predictably-performant-and-fully-6d93dfbfe2fb&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dynamodb</category>
      <category>aws</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Create a folder and push multiple files under a single commit through GitHub API</title>
      <dc:creator>Siddhartha Varma</dc:creator>
      <pubDate>Sun, 06 Mar 2022 12:34:33 +0000</pubDate>
      <link>https://forem.com/bro3886/create-a-folder-and-push-multiple-files-under-a-single-commit-through-github-api-23kc</link>
      <guid>https://forem.com/bro3886/create-a-folder-and-push-multiple-files-under-a-single-commit-through-github-api-23kc</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;I could not understand how to push multiple files under a single commit, using GitHub API. Some googling landed me on &lt;a href="https://docs.github.com/en/rest/reference/git" rel="noopener noreferrer"&gt;Git Database API Docs&lt;/a&gt;. Wasn't very clear how it worked so I tried getting my hands dirty! Documenting it here for anyone who's looking for it.&lt;/p&gt;

&lt;p&gt;Disclosure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;This API needs atleast 1 commit to work. Empty repositories don't work.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Git Database API
&lt;/h2&gt;

&lt;p&gt;The Git Database API enables you to read and write raw Git objects to your Git database on GitHub and to list and update Git references (branch heads and tags).&lt;/p&gt;

&lt;p&gt;The whole process is as follows: create blobs corresponding to files, create tree, create a commit for the changes and finally updating refs to reflect the commit.&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%2F1paoytdkvtczvkzhcg85.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1paoytdkvtczvkzhcg85.jpg" alt="Image description" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating blobs
&lt;/h2&gt;

&lt;p&gt;A Git blob (binary large object) is the object type used to store the contents of each file in a repository. The file's SHA-1 hash is computed and stored in the blob object.&lt;/p&gt;

&lt;p&gt;To create a blob we need to hit the following endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://api.github.com/repos/{user}/{repo}/git/blobs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's create a blob for a file called &lt;code&gt;main.py&lt;/code&gt; with 1 line of python code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"print(&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;hello world !&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"encoding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"utf-8"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can create blobs for each file we want to upload. In the response, we get &lt;code&gt;SHA&lt;/code&gt; of the blob which we need to send while creating the tree. Sample response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"638eff25696b982124deeb1f3dfcceabfdc81a93"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/blobs/638eff25696b982124deeb1f3dfcceabfdc81a93"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a tree
&lt;/h2&gt;

&lt;p&gt;Now, we need to create a tree with the files we added. For that, first we need to get the SHA of the base tree. Then we need to create a tree for the files we need to add:&lt;/p&gt;

&lt;h3&gt;
  
  
  Get SHA for &lt;code&gt;base_tree&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The base tree can be thought of as the folder where you'd like to create your commit. If you want to create it at the root folder, you can make request to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://api.github.com/repos/{user}/{repo}/git/trees/{branch}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns a response like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0d43a3b20104b4baa402c09a6c9c6c3298390e4a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{url of tree}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"040000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{sha}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{url of folder/tree}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"README.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100644"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{some SHA}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;885&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{some URL}"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"truncated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we can extract the &lt;code&gt;SHA&lt;/code&gt; from &lt;code&gt;response.sha&lt;/code&gt; or SHA of the folder under &lt;code&gt;response.tree[i].sha&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create tree
&lt;/h3&gt;

&lt;p&gt;Then, we need to hit the create tree api:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://api.github.com/repos/{user}/{repo}/git/trees
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the body as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"helloworld/main.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100644"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"blob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"638eff25696b982124deeb1f3dfcceabfdc81a93"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"helloworld/main2.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"100644"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"blob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"638eff25696b982124deeb1f3dfcceabfdc81a93"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"base_tree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"3c408bafa55eda6b1c51de5df0fc36304f37414c"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;request.tree&lt;/code&gt; would have an array of blobs that you want to push. For each blob we need the SHA that we got as a response from create blob API.&lt;/p&gt;

&lt;p&gt;For the &lt;code&gt;mode&lt;/code&gt;:&lt;br&gt;
The file mode; one of &lt;code&gt;100644&lt;/code&gt; for file (blob), &lt;code&gt;100755&lt;/code&gt; for executable (blob), &lt;code&gt;040000&lt;/code&gt; for subdirectory (tree), &lt;code&gt;160000&lt;/code&gt; for submodule (commit), or &lt;code&gt;120000&lt;/code&gt; for a blob that specifies the path of a symlink.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GitHub doesn't store folders, so the only way to make a folder is to set the &lt;code&gt;path&lt;/code&gt; for the blob as &lt;code&gt;{folderName}/{fileName}&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here, we get another &lt;code&gt;SHA&lt;/code&gt; in the response, which we need when we create a commit corresponding to the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"a69117177bb067933189072b2b8799c63f388f32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/trees/a69117177bb067933189072b2b8799c63f388f32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"README.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100644"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"blob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bc7b1321063b4075c97bf16e6f8130b6f9fa6537"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/blobs/bc7b1321063b4075c97bf16e6f8130b6f9fa6537"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"helloworld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"040000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"82a82f6788b44fe93774597ff2e76ac66ae1e657"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/trees/82a82f6788b44fe93774597ff2e76ac66ae1e657"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"truncated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we need &lt;code&gt;response.sha&lt;/code&gt; for the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add a commit
&lt;/h2&gt;

&lt;p&gt;This step is pretty simple. We just need the &lt;code&gt;response.sha&lt;/code&gt; from the previous step. We make a request to the following endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST https://api.github.com/repos/{user}/{repo}/git/commits
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Along with the body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tree"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"a69117177bb067933189072b2b8799c63f388f32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"some commit msg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parents"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"3c408bafa55eda6b1c51de5df0fc36304f37414c"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;parents&lt;/code&gt;: The SHAs of the commits that were the parents of this commit. If omitted or empty, the commit will be written as a root commit. For a single parent, an array of one SHA should be provided; for a merge commit, an array of more than one should be provided.&lt;/p&gt;

&lt;p&gt;In our case, for the parent, since we want to add another commit on a particular branch, we need to get the SHA of it.&lt;/p&gt;

&lt;p&gt;For that, we need to make a request to the following endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://api.github.com/repos/BRO3886/git-db-example/git/refs/heads/{branch}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It returns a &lt;code&gt;JSON&lt;/code&gt; with details about the branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"refs/heads/main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REF_kwDOG87gc69yZWZzL2hlYWRzL21haW4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/refs/heads/main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3c408bafa55eda6b1c51de5df0fc36304f37414c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/commits/3c408bafa55eda6b1c51de5df0fc36304f37414c"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the parent SHA, we need &lt;code&gt;response.object.sha&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the response of create commit API, we'll get another SHA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"544aa83c4d4a784c4c8490d6548c248b0e57d0ac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"node_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C_kwDOG87gc9oAKDU0NGFhODNjNGQ0YTc4NGM0Yzg0OTBkNjU0OGMyNDhiMGU1N2QwYWM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.github.com/repos/BRO3886/git-db-example/git/commits/544aa83c4d4a784c4c8490d6548c248b0e57d0ac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"html_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/BRO3886/git-db-example/commit/544aa83c4d4a784c4c8490d6548c248b0e57d0ac"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll need this SHA value for the last step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating ref
&lt;/h2&gt;

&lt;p&gt;This step is for updating the ref from where we pulled the SHA under &lt;code&gt;parents&lt;/code&gt; (create commit step). For my case, since the ref was main, I'll update it. Make a request to the following endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PATCH https://api.github.com/repos/{user}/{repo}/git/refs/heads/{branch}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Along with the body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"544aa83c4d4a784c4c8490d6548c248b0e57d0ac"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If in the response the &lt;code&gt;object.sha&lt;/code&gt; is same as the one sent as a part of the request, along with status code 200, that means your changes will be reflected on GitHub.&lt;/p&gt;




&lt;p&gt;I hope you got some idea. Here is the GitHub link of the sample repo you can refer: &lt;a href="https://github.com/BRO3886/git-db-example" rel="noopener noreferrer"&gt;github.com/BRO3886/git-db-example&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>github</category>
      <category>git</category>
      <category>api</category>
    </item>
    <item>
      <title>Conditionally loading Flutter App's first screen with AutoRoute and Navigator 2.0</title>
      <dc:creator>Siddhartha Varma</dc:creator>
      <pubDate>Tue, 15 Jun 2021 21:08:12 +0000</pubDate>
      <link>https://forem.com/bro3886/app-entrypoint-with-autoroute-and-navigator-2-0-16p5</link>
      <guid>https://forem.com/bro3886/app-entrypoint-with-autoroute-and-navigator-2-0-16p5</guid>
      <description>&lt;p&gt;This is just a small blog (or bloglet, if that's a word), to help you understand how easy it is to navigate to a different page on app launch with &lt;a href="https://pub.dev/packages/auto_route" rel="noopener noreferrer"&gt;auto-route&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;I'm assuming you already have auto router setup. If not, check &lt;a href="https://pub.dev/packages/auto_route#installation" rel="noopener noreferrer"&gt;this link&lt;/a&gt; to see how to set it up with navigator 2.0 in Flutter.&lt;/p&gt;

&lt;p&gt;If you have setup everything, your root widget's build method would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt; &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="s"&gt;'App Bane'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;theme:&lt;/span&gt; &lt;span class="n"&gt;lightThemeData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;routerDelegate:&lt;/span&gt; &lt;span class="n"&gt;_appRouter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;initialRoutes:&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LandingScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;PledgeScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;DashboardScreen&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;routeInformationParser:&lt;/span&gt;
            &lt;span class="n"&gt;_appRouter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;defaultRouteParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;includePrefixMatches:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&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;For context: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Here &lt;code&gt;_appRouter&lt;/code&gt; is initialised before the &lt;code&gt;initState&lt;/code&gt; function:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_appRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AppRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;I also have some booleans being fetched from hive at run-time, in the &lt;code&gt;initState&lt;/code&gt; method:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isVerified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code-snippet of importance is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nl"&gt;routerDelegate:&lt;/span&gt; &lt;span class="n"&gt;_appRouter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
     &lt;span class="nl"&gt;initialRoutes:&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LandingScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;PledgeScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;DashboardScreen&lt;/span&gt;&lt;span class="p"&gt;(),&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;So, basically we can provide any screens/routes conditionally to the &lt;code&gt;initialRoutes&lt;/code&gt; prop in &lt;code&gt;_appRouter.delegate&lt;/code&gt;, which is used to setup the &lt;code&gt;routerDelegate&lt;/code&gt; for our &lt;code&gt;MaterialApp&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Explanation
&lt;/h4&gt;

&lt;p&gt;In my case, if the user is not signed in, it returns LandingScreen. If the user is signed in and has not accepted the terms, it takes them to the PledgeScreen, else, it takes them to the DashboardScreen.&lt;/p&gt;

&lt;h4&gt;
  
  
  Full Code example
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;main.dart&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;_MyAppState&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_MyAppState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_MyAppState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;AppState&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;_appRouter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AppRouter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isVerified&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;//initialise bools&lt;/span&gt;
    &lt;span class="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;isVerified&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="s"&gt;'My App'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;theme:&lt;/span&gt; &lt;span class="n"&gt;lightThemeData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;routerDelegate:&lt;/span&gt; &lt;span class="n"&gt;_appRouter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;initialRoutes:&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="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isSignedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;LandingScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;PledgeScreen&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="n"&gt;isSignedIn&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;isTnCAccepted&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;DashboardScreen&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="nl"&gt;routeInformationParser:&lt;/span&gt;
            &lt;span class="n"&gt;_appRouter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;defaultRouteParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;includePrefixMatches:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&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;blockquote&gt;
&lt;p&gt;Here &lt;code&gt;PledgeScreen&lt;/code&gt; and &lt;code&gt;LandingScreen&lt;/code&gt; come from the file of routes generated by &lt;code&gt;auto_router&lt;/code&gt; (router.gr.dart, check auto_router documentation for reference) .&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;router.dart&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="nd"&gt;@MaterialAutoRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nl"&gt;replaceInRouteName:&lt;/span&gt; &lt;span class="s"&gt;'Page,Route'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nl"&gt;routes:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AutoRoute&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[&lt;/span&gt;
    &lt;span class="n"&gt;AutoRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;page:&lt;/span&gt; &lt;span class="n"&gt;LandingScreen&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;AutoRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;page:&lt;/span&gt; &lt;span class="n"&gt;PledgeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="s"&gt;"/signup/complete"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;AutoRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;page:&lt;/span&gt; &lt;span class="n"&gt;DashboardScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;path:&lt;/span&gt; &lt;span class="s"&gt;"/dashboard"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nc"&gt;AppRouter&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Conclusion
&lt;/h4&gt;

&lt;p&gt;This is how easy it was to use AutoRouter with Navigator2.0 where you have to conditionally open a page in the app. In addition to this, AutoRouter also simplifies deeplinks etc, opening the correct page on launch with dynamic links. Will be covering that soon! Hope you liked my first blog here :). Would love to hear suggestions to improve.&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>firstpost</category>
    </item>
  </channel>
</rss>
