<?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: Aparna Krishnamoorthy</title>
    <description>The latest articles on DEV Community by Aparna Krishnamoorthy (@aparkris).</description>
    <link>https://dev.to/aparkris</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%2F3927622%2F9eb7d712-e035-4ef1-812f-a1f71401f76b.png</url>
      <title>DEV Community: Aparna Krishnamoorthy</title>
      <link>https://dev.to/aparkris</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aparkris"/>
    <language>en</language>
    <item>
      <title>Scaling Parameter Store reads for production workloads</title>
      <dc:creator>Aparna Krishnamoorthy</dc:creator>
      <pubDate>Thu, 23 Jul 2026 19:33:35 +0000</pubDate>
      <link>https://dev.to/aparkris/scaling-parameter-store-reads-for-production-workloads-46ie</link>
      <guid>https://dev.to/aparkris/scaling-parameter-store-reads-for-production-workloads-46ie</guid>
      <description>&lt;p&gt;Consider an order-processing service running on Amazon ECS Fargate during a weekend sale. Under normal conditions, 20 tasks read configuration values from Parameter Store at startup. As traffic increases, the service scales to 200 tasks, causing many tasks to request the same parameters at nearly the same time. If these requests exceed the available throughput, new tasks can start slowly or fail, potentially delaying or interrupting customer orders.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsyheu0gk10nqclytk0a6.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsyheu0gk10nqclytk0a6.png" alt="Parameter Store Throughput" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When an application exceeds the available quota, its logs can show a &lt;code&gt;ThrottlingException&lt;/code&gt;or &lt;code&gt;RateExceeded&lt;/code&gt; error from &lt;code&gt;GetParameter&lt;/code&gt;, &lt;code&gt;GetParameters&lt;/code&gt;, or &lt;code&gt;GetParametersByPath&lt;/code&gt;. To diagnose such issues, you can check the error source in application logs, or trace the relevant API calls in CloudTrail. Then compare the timing against a known scaling or deployment event. Throttling or latency issues that cluster around this event are a strong signal that concurrent parameter requests caused the bottleneck. &lt;/p&gt;

&lt;p&gt;You can address Parameter Store throughput issues in the following complementary ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Enable higher throughput.&lt;/strong&gt; Increase the quota so that production workloads handle concurrent reads during normal operation and scaling events. The cost is based on usage. For example, a workload generating approximately 456,000 parameter interactions for a 60-hour sale costs about $2.28.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize read patterns.&lt;/strong&gt; Reduce unnecessary API traffic by retrieving only the parameters the application needs and caching values that it reads repeatedly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Enabling higher throughput raises the quota for each API action in a single account in a single Region. Throughput for &lt;code&gt;SecureString&lt;/code&gt; parameters might be further limited by AWS KMS. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API action&lt;/th&gt;
&lt;th&gt;&lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-throughput.html" rel="noopener noreferrer"&gt;Default quota&lt;/a&gt;&lt;/th&gt;
&lt;th&gt;&lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/parameter-store-throughput.html" rel="noopener noreferrer"&gt;Higher-throughput quota&lt;/a&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GetParameter&lt;/td&gt;
&lt;td&gt;Shared 40 TPS&lt;/td&gt;
&lt;td&gt;10,000 TPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GetParameters&lt;/td&gt;
&lt;td&gt;Shared 40 TPS&lt;/td&gt;
&lt;td&gt;1,000 TPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GetParametersByPath&lt;/td&gt;
&lt;td&gt;Shared 40 TPS&lt;/td&gt;
&lt;td&gt;100 TPS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Improving application resilience by enabling higher throughput
&lt;/h2&gt;

&lt;p&gt;Consider enabling higher throughput in the following scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parameter Store is part of a production request path, not a one-time deployment. A higher quota ensures configuration requests don’t become a bottleneck at runtime. &lt;/li&gt;
&lt;li&gt;Many instances, containers, or Lambda functions read parameters within the same window. Higher throughput lets your fleet scale without individual instances competing for a shared, undersized quota. &lt;/li&gt;
&lt;li&gt;Deployments, restarts, or autoscaling events produce bursts of reads. You can absorb these predictable spikes, so a routine deployment doesn't fail.&lt;/li&gt;
&lt;li&gt;Usage regularly approaches or exceeds the default 40 TPS quota. By proactively increasing your quota, you eliminate bottlenecks instead of waiting for them to recur under heavier load.&lt;/li&gt;
&lt;li&gt;You want more throughput but don’t want to redesign the system. Enabling the higher-throughput setting increases your quota immediately without touching your infrastructure or application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you enable higher throughput, you increase the request quota for your AWS account and Region. &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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3chxqgjmgn1vo6efo5br.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3chxqgjmgn1vo6efo5br.png" alt="Parameter Store Higher Throughput" width="799" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The cost of higher throughput is &lt;a href="https://aws.amazon.com/systems-manager/pricing/" rel="noopener noreferrer"&gt;$0.05 per 10,000 parameter interactions&lt;/a&gt;. A request that retrieves multiple parameters counts as one interaction for each parameter returned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An order-processing example&lt;/strong&gt;&lt;br&gt;
Assume that our order-processing service runs 20 tasks under normal conditions. During a promotional event lasting 60 hours (6 p.m. Friday to 6 a.m. Monday), it scales to 200 tasks for the duration of the sale. To limit stale values, each task refreshes the database endpoint, inventory service, and order dead-letter queue parameters every 5 minutes as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 tasks × (60 hours × 12 refreshes per hour) = 144,000 refresh calls.&lt;/li&gt;
&lt;li&gt;144,000 calls × 3 parameters each = 432,000 parameter interactions.&lt;/li&gt;
&lt;li&gt;A Lambda function handling checkout cold starts approximately 8,000 times during traffic bursts, creating 24,000 additional interactions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is approximately 456,000 parameter interactions for the 60-hour sale. With higher throughput enabled, the application avoids throttling errors caused by hitting quota limits. At $0.05 per 10,000 interactions, the total additional cost is $2.28.&lt;/p&gt;

&lt;p&gt;Because the higher-throughput setting is billed on usage, you can enable it before an anticipated traffic spike and disable it afterward. If your application is throttled during normal production workloads, however, consider enabling higher throughput as a permanent setting.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enabling higher throughput in the AWS console and CLI
&lt;/h2&gt;

&lt;p&gt;A throughput setting applies at the account and Region level. It takes effect for all applications reading from Parameter Store in the specified scope.&lt;/p&gt;

&lt;p&gt;In the console, increase throughput by choosing &lt;strong&gt;Systems Manager &amp;gt; Parameter Store &amp;gt; Settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the AWS CLI, run the following command to enable higher throughput, replacing the AWS Region and account ID with your own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shell
aws ssm update-service-setting &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--setting-id&lt;/span&gt; arn:aws:ssm:us-east-1:123456789012:servicesetting/ssm/parameter-store/high-throughput-enabled &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--setting-value&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Optimizing read patterns
&lt;/h2&gt;

&lt;p&gt;Optimizing how your application retrieves parameters is an operational best practice. If your application retrieves only necessary parameters and caches values that it reads repeatedly, it reduces latency and uses throughput more efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Avoid retrieving more than your application needs.&lt;/strong&gt; Parameter hierarchies are a useful way to organize configuration values. For example, you can group parameters for a checkout application as follows: &lt;code&gt;/prod/checkout/db-host&lt;/code&gt;, &lt;code&gt;/prod/checkout/inventory-service-endpoint&lt;/code&gt;, and &lt;code&gt;/prod/checkout/order-dlq-arn&lt;/code&gt;. It’s tempting to use &lt;code&gt;GetParametersByPath&lt;/code&gt; to retrieve an entire subtree when your application knows the specific parameters it needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Gets the subtree, including parameters your app might not need`&lt;/span&gt;
&lt;span class="sb"&gt;`&lt;/span&gt;aws ssm get-parameters-by-path &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--path&lt;/span&gt; &lt;span class="s2"&gt;"/prod/checkout/"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--with-decryption&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With higher throughput enabled, &lt;code&gt;GetParametersByPath&lt;/code&gt; is limited to 100 TPS, compared to 1,000 for &lt;code&gt;GetParameters&lt;/code&gt; and 10,000 for single-parameter &lt;code&gt;GetParameter&lt;/code&gt; calls. With default throughput, all three share the same 40 TPS pool. If your application knows its parameter names, requesting them directly means that your application is less likely to hit the quota.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="c"&gt;# Retrieves only the parameters your app actually needs&lt;/span&gt;
aws ssm get-parameters &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--names&lt;/span&gt; &lt;span class="s2"&gt;"/prod/checkout/db-host"&lt;/span&gt; &lt;span class="s2"&gt;"/prod/checkout/inventory-service-endpoint"&lt;/span&gt; &lt;span class="s2"&gt;"/prod/checkout/order-dlq-arn"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--with-decryption&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a best practice, remove unused parameters from a hierarchy. You prevent &lt;code&gt;GetParametersByPath&lt;/code&gt; calls from returning parameters that the application doesn’t need and can reduce the paginated requests for larger hierarchies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cache parameter values in the application.&lt;/strong&gt; Many configuration values don’t change often enough to justify reading them on every request. If your application reads the same parameter many times per minute, read it once and reuse the value for an appropriate period. For example, use a short reuse window for values that change often and a longer one for values that don’t. &lt;/p&gt;

&lt;p&gt;The following sample code defines a &lt;code&gt;get_parameter()&lt;/code&gt; function. You can call this function every 10 seconds for a specific parameter. The first call after the five-minute TTL expires retrieves the latest value from Parameter Store and updates the cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;ssm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ssm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;TTL_SECONDS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;  &lt;span class="c1"&gt;# how long to trust a cached value
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pname&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pname&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cached_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cached_at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;TTL_SECONDS&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;value&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ssm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_parameter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;pname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WithDecryption&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Parameter&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pname&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&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;value&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Spread out reads when many resources start at the same time.&lt;/strong&gt; A common source of throttling is simultaneous startup. This occurs when many EC2 instances or ECS tasks read the same parameters within the same second during deployment or scaling. You can avoid concentrating the read burst by reading parameters once and passing the values to the application, or by staggering reads with a slight delay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Lambda functions, consider the AWS Parameters and Secrets Lambda Extension.&lt;/strong&gt; The extension caches parameter values locally for reuse across invocations. This reduces both the number of calls to Parameter Store and the latency of retrieving values. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Your application logs might show &lt;code&gt;ThrottlingException&lt;/code&gt; or &lt;code&gt;RateExceeded&lt;/code&gt;errors from &lt;code&gt;GetParameter&lt;/code&gt;, &lt;code&gt;GetParameters&lt;/code&gt;, or &lt;code&gt;GetParametersByPath&lt;/code&gt;. The results of throttling can be outages and degraded customer experience.&lt;/p&gt;

&lt;p&gt;Enabling the higher-throughput setting removes the risk of hitting an API quota during production. You can enable it before an anticipated event and disable it afterward, or leave it on permanently. For most production workloads, the operational benefit of resilience outweighs the modest cost.&lt;/p&gt;

&lt;p&gt;You can also address latency by optimizing read patterns. For example, you can replace a &lt;code&gt;GetParametersByPath&lt;/code&gt; call with &lt;code&gt;GetParameters&lt;/code&gt;, or cache values in your application. The combination of higher throughput and optimized reads helps make your application more resilient when multiple tasks run concurrently. &lt;/p&gt;

&lt;p&gt;Questions? Comments? Leave them below!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>parameterstore</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Improving operational resilience by decoupling code deployments from feature activation using AWS AppConfig feature flags</title>
      <dc:creator>Aparna Krishnamoorthy</dc:creator>
      <pubDate>Wed, 13 May 2026 14:31:22 +0000</pubDate>
      <link>https://dev.to/aparkris/improving-operational-resilience-by-decoupling-code-deployments-from-feature-activation-using-aws-i3</link>
      <guid>https://dev.to/aparkris/improving-operational-resilience-by-decoupling-code-deployments-from-feature-activation-using-aws-i3</guid>
      <description>&lt;p&gt;Shipping quickly isn’t the hard part anymore. The hard part is recovering when something goes wrong.&lt;br&gt;
A lot of teams still release features the same way: deploy code and whatever’s in that deployment goes live immediately. It’s simple, and it works — until it doesn’t. Because when a feature causes problems, you don’t just turn off the feature. You end up rolling back the entire deployment. That means waiting, coordinating, and sometimes introducing new risk just to undo the last change.&lt;br&gt;
That’s a heavy price to pay for something that should be lightweight.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Where the risk actually comes from *&lt;/em&gt;&lt;br&gt;
The issue isn’t deployments themselves. It’s the fact that feature activation is tightly coupled to them. When those two things are tied together, every release becomes an all-or-nothing event. A small issue can impact your entire user base, and recovery depends on how quickly you can redeploy or roll back. That’s where Mean Time to Resolution starts to creep up—not because the fix is complicated, but because the mechanism to apply it is. It also makes it difficult to test safely in production. You either release to everyone or no one, which isn’t much of a choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separating deployment from release&lt;/strong&gt;&lt;br&gt;
A more resilient approach is to treat deployment and feature release as two different concerns. You can deploy code whenever you want, but keep new functionality inactive until you explicitly turn it on. That control layer is what feature flags provide.&lt;/p&gt;

&lt;p&gt;Using AWS AppConfig on Amazon Web Services, feature state becomes configuration rather than code. Your application checks that configuration at runtime and decides which path to execute.&lt;br&gt;
That one change removes the need to redeploy just to change behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What changes in practice&lt;/strong&gt;&lt;br&gt;
Instead of hardcoding whether a feature is on or off, your application asks AWS AppConfig for the current state and responds accordingly. The flow is straightforward: the application retrieves configuration, evaluates the relevant flag, and executes the appropriate logic.&lt;br&gt;
Here’s a simple example. Imagine you’re introducing a new checkout flow.&lt;br&gt;
Your configuration might look like this:&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"flags"&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;"enableNewCheckout"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Enable new checkout experience"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&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;"version"&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;"constraints"&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;"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;"string"&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="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;"values"&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;"enableNewCheckout"&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;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&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="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;That lives in AWS AppConfig, not in your codebase.&lt;/p&gt;

&lt;p&gt;To retrieve it at runtime, use AWS AppConfig Agent. The agent is an Amazon-managed process that retrieves configuration data from AWS AppConfig in the cloud. It caches configuration data locally and asynchronously polls the AWS AppConfig data plane for updates. This approach keeps configuration data readily available to your application while reducing latency and cost.&lt;br&gt;
&lt;em&gt;Although you can retrieve configuration data by calling the APIs directly, using the agent is the recommended approach. It improves application performance and simplifies configuration management.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With your configuration profile stored in AWS AppConfig and the agent running in your compute environment, using the configuration is just a conditional in your application logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;application_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyDemoApp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;environment_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyEnvironment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config_profile_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MyConfigProfile&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;flag_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// retrieve a single flag's data by providing the "flag" query string parameter&lt;/span&gt;
    &lt;span class="c1"&gt;// note: the configuration's type must be AWS.AppConfig.FeatureFlags&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`http://localhost:2772/applications/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;application_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/environments/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;environment_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/configurations/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config_profile_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?flag=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;flag_name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handleCheckout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enableNewCheckoutFlag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;loadFlag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enableNewCheckout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// {"enabled":true,"version":"2.0"}&lt;/span&gt;


  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;enableNewCheckoutFlag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&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="nf"&gt;newCheckoutFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;


  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;legacyCheckoutFlow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That small shift—moving the decision out of your deployment and into runtime configuration—gives you a surprising amount of control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reducing mean time to resolution with gradual deployments&lt;/strong&gt;&lt;br&gt;
One of the less obvious benefits of feature flags is how they change how quickly you understand and resolve issues, not just how you prevent them.&lt;br&gt;
When you roll out a feature gradually using AWS AppConfig, you’re effectively turning a production release into a controlled experiment. Instead of exposing 100% of users at once, you start with a small segment and watch what happens. That alone shortens the feedback loop. If something is wrong, you’ll see it earlier—and in a much smaller slice of traffic. But the real impact on mean time to resolution comes from the combination of three things working together:&lt;br&gt;
First, reduced scope. If only 5% of users are impacted, you’re not dealing with a full-scale incident. That lowers urgency just enough to make debugging more methodical instead of reactive.&lt;br&gt;
Second, clearer signal. When a change is introduced gradually, it’s easier to correlate cause and effect. You’re not sifting through noise from a full deployment—you’re looking at a controlled change with a defined rollout window.&lt;br&gt;
Third, faster reversal. If metrics start trending in the wrong direction, you don’t need to redeploy or coordinate a rollback. You stop the rollout or revert the configuration.  Integration with Amazon CloudWatch or monitoring platforms like DataDog and New Relic (using custom extensions) allow you to define guardrails. If key metrics cross a threshold, AWS AppConfig can automatically roll back to a known good configuration without waiting for someone to step in.&lt;br&gt;
Put together, gradual deployments don’t just reduce blast radius—they reduce the time it takes to understand, isolate, and resolve issues in the first place.&lt;br&gt;
&lt;em&gt;AWS AppConfig also supports pre-deployment syntax and functional validation through integration with AWS Lambda. Pre-deployment validation reduces the chance of a bad configuration making it into production in the first place.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operational feature flags that make a difference&lt;/strong&gt;&lt;br&gt;
Once you start using feature flags, it’s tempting to think of them only in terms of user-facing features. In practice, some of the most valuable flags are operational—they exist purely to give you more control during incidents or high-risk changes.&lt;br&gt;
A simple but powerful example is an operational toggle or kill switch. Instead of rolling back an entire service, you can disable a specific capability that’s causing issues. This is especially useful for integrations or newly introduced dependencies where failure modes aren’t fully understood yet.&lt;br&gt;
Another common pattern is traffic shaping. You can route a percentage of requests to a new code path, a new backend, or even a different region. If something looks off, you dial it back immediately. This gives you a level of control that traditional deployments don’t offer.&lt;br&gt;
You can also use flags to control fallback behavior. For example, if a downstream dependency starts failing, a flag can switch your application into a degraded mode—serving cached data, skipping non-critical steps, or simplifying responses. That kind of switch can be the difference between a partial degradation and a full outage.&lt;br&gt;
There’s also value in flags that control operational safeguards. Rate limiting thresholds, retry behavior, or timeout values can all be externalized into configuration. Instead of pushing a code change during an incident, you adjust behavior in real time.&lt;br&gt;
Finally, some teams use feature flags to control observability itself. Increasing logging, enabling additional metrics, or turning on debug paths can all be done dynamically. When paired with validation via AWS Lambda, you can safely introduce these changes without risking malformed configurations.&lt;br&gt;
None of these flags are particularly complex on their own. What matters is that they give you options when things aren’t going smoothly.&lt;br&gt;
And that’s really the point: operational resilience isn’t just about preventing failures—it’s about having enough control to respond effectively when they happen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When this starts to matter&lt;/strong&gt;&lt;br&gt;
This approach becomes especially valuable once you’re deploying frequently or operating systems where uptime really matters. If you’ve ever had to rush a rollback, or sit through a tense deployment wondering if something might break, you’ve already felt the limitations of tightly coupled releases.&lt;br&gt;
Decoupling feature activation from deployment doesn’t eliminate failures, but it makes them smaller and easier to recover from.&lt;/p&gt;

&lt;p&gt;Most teams focus on improving how they deploy code. Fewer spend time improving how they release features. Using AWS AppConfig shifts that focus. It gives you a way to control behavior independently of deployments, which in turn makes your system more resilient and your releases less stressful. It’s not a massive architectural overhaul. It’s a small change in where decisions are made.&lt;/p&gt;

&lt;p&gt;But it has a disproportionate impact on how safely you can move.&lt;/p&gt;

&lt;p&gt;For more information, see the &lt;a href="https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html" rel="noopener noreferrer"&gt;AWS AppConfig User Guide&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>aws</category>
      <category>cicd</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
