<?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: Manoj Chaurasiya</title>
    <description>The latest articles on DEV Community by Manoj Chaurasiya (@manojchrsya).</description>
    <link>https://dev.to/manojchrsya</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%2F304403%2Feaaba3de-177f-4829-a5ac-0b7c2c2e802c.jpg</url>
      <title>DEV Community: Manoj Chaurasiya</title>
      <link>https://dev.to/manojchrsya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manojchrsya"/>
    <language>en</language>
    <item>
      <title>How to Horizontally Scale Amazon ElastiCache Instance</title>
      <dc:creator>Manoj Chaurasiya</dc:creator>
      <pubDate>Sat, 14 Sep 2024 07:16:09 +0000</pubDate>
      <link>https://dev.to/manojchrsya/how-to-horizontally-scale-amazon-elasticache-instance-eg7</link>
      <guid>https://dev.to/manojchrsya/how-to-horizontally-scale-amazon-elasticache-instance-eg7</guid>
      <description>&lt;p&gt;Amazon ElastiCache provides in-memory data storage using Redis or Memcached, and scaling involves either vertical (instance size) or horizontal scaling (adding nodes or replicas). Horizontal scaling focuses on distributing the data and increasing capacity by adding more nodes to your ElastiCache cluster.&lt;/p&gt;

&lt;p&gt;Redis Cluster Mode Enabled supports sharding out of the box, and this is the recommended way to horizontally scale Redis.&lt;/p&gt;

&lt;p&gt;Lets start with horizontal scaling for ElastiCache instance, We can achieve scaling by updating Shard or Node, here will go for scaling with Nodes. ElastiCache cluster allows to create Dynamic scaling through AWS console but it will use only &lt;code&gt;CPU Utilization&lt;/code&gt; metric.&lt;/p&gt;

&lt;p&gt;If we have to apply dynamic scaling as per other metric then it can be created through AWS CLI.&lt;/p&gt;

&lt;h4&gt;
  
  
  Verify Metric Statistics
&lt;/h4&gt;

&lt;p&gt;Before going further, let's cross check if we are getting proper statistics value for primary node, in our case we had considered primary node to set threshold value for auto scaling. we can select metric name as per uses of redis cluster.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws cloudwatch get-metric-statistics \
  --namespace AWS/ElastiCache \
  --metric-name NetworkBytesOut \
  --dimensions Name=CacheClusterId,Value=primary-node-0001-001 \
  --start-time 2024-09-13T00:00:00Z \
  --end-time 2024-09-13T23:59:59Z \
  --period 300 \
  --statistics Average
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Register Scalable Target
&lt;/h4&gt;

&lt;p&gt;By registering the cluster as a scalable target, you can set the cluster to have a minimum of 2 nodes and a maximum of 5 nodes (number of node depends on cluster load). Based on the load and defined scaling policies (like Network Byte Out), Application Auto Scaling will automatically increase or decrease the number of nodes in your cluster within those limits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  aws application-autoscaling register-scalable-target \
    --service-namespace elasticache \
    --resource-id replication-group/cluster-name-1 \
    --scalable-dimension elasticache:replication-group:Replicas \
    --min-capacity 1 \
    --max-capacity 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Auto Scaling Config File
&lt;/h4&gt;

&lt;p&gt;Here's an example configuration file for AWS ElastiCache autoscaling using Application Auto Scaling. This configuration defines the CloudWatch metric used for scaling (e.g., NetworkBytesOut) and details of the primary node and replicas. The auto scaling policy will leverage CloudWatch data points to adjust the number of nodes based on usage patterns. let's store this configuration in config.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "TargetValue": 7000000000,
  "CustomizedMetricSpecification":
  {
    "MetricName": "NetworkBytesOut",
    "Namespace": "AWS/ElastiCache",
    "Dimensions": [
      {"Name": "CacheClusterId","Value":"primary-node-0001-001"},
      {"Name": "CacheNodeId","Value": "0001"}
    ],
    "Statistic": "Average"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Scaling Policy
&lt;/h4&gt;

&lt;p&gt;The scaling policy defines the conditions under which the cluster should scale in (remove nodes) or scale out (add nodes). These conditions are usually based on metrics collected by Amazon CloudWatch (like CPU or network usage), in our case it is NetworkByteOut.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws application-autoscaling put-scaling-policy \
    --policy-name elastic-cache-asg \
    --policy-type TargetTrackingScaling \
    --resource-id replication-group/cluster-name-1 \
    --service-namespace elasticache \
    --scalable-dimension elasticache:replication-group:Replicas \
    --target-tracking-scaling-policy-configuration file://config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you configure the scaling policy, two CloudWatch alarms will automatically be created: HighAlarm and LowAlarm. These alarms monitor the selected metric (like CPU utilization) and trigger scaling actions when thresholds are crossed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HighAlarm&lt;/strong&gt;: This alarm triggers when the metric exceeds the upper threshold, resulting in a scale-out action to add more nodes to the cluster, improving performance.&lt;br&gt;
   &lt;strong&gt;LowAlarm&lt;/strong&gt;: This alarm triggers when the metric drops below the lower threshold, resulting in a scale-in action to remove unnecessary nodes, optimizing resource usage.&lt;/p&gt;

&lt;p&gt;The alarms ensure that the number of nodes in the ElastiCache cluster is adjusted dynamically, maintaining both performance and cost-efficiency. You can monitor these alarms in CloudWatch to confirm that scaling actions are taking place as expected.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;In this post, we explored the implementation of Horizontal Auto Scaling for an ElastiCache Redis Cluster. One important point to note is that AWS ElastiCache supports autoscaling only for instance types m7g.large and above. This means that if you're using smaller instance types, such as t3 or m6g.medium, autoscaling will not be available. To take advantage of automatic scaling, ensure that your cluster is using at least the m7g.large instance type or higher.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>elasticache</category>
      <category>autoscaling</category>
    </item>
    <item>
      <title>How to Vertically Scale Your Amazon RDS Instance</title>
      <dc:creator>Manoj Chaurasiya</dc:creator>
      <pubDate>Sat, 07 Sep 2024 10:25:34 +0000</pubDate>
      <link>https://dev.to/manojchrsya/how-to-vertically-scale-your-amazon-rds-instance-3f2e</link>
      <guid>https://dev.to/manojchrsya/how-to-vertically-scale-your-amazon-rds-instance-3f2e</guid>
      <description>&lt;p&gt;Vertical scaling, often referred to as scaling up, involves increasing the capacity of a single database instance by adding more resources such as CPU, memory, and storage. This approach contrasts with horizontal scaling (or scaling out), which adds more instances to distribute the load.&lt;/p&gt;

&lt;p&gt;AWS provides feature for horizontal scaling in Aurora RDS, but there no direct method to use auto scaling for RDS PostgreSQL, though vertical scaling can be achieve using Cloud Watch and Lambda.&lt;/p&gt;

&lt;p&gt;Vertical scaling can be cost-effective in certain scenarios, particularly when compared to the alternative of horizontal scaling or maintaining an oversized infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud watch alarms
&lt;/h3&gt;

&lt;p&gt;First we need to create Cloud watch alarm as per required metric, in our case we have used &lt;code&gt;DBLoadCPU&lt;/code&gt; metric.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws cloudwatch put-metric-alarm \
    --alarm-name db-rds-postgres-high-alarm \
    --metric-name DBLoadCPU \
    --namespace AWS/RDS \
    --statistic Maximum \
    --period 180 \
    --threshold 3 \
    --comparison-operator GreaterThanThreshold \
    --dimensions Name=DBInstanceIdentifier,Value=db-identifier-name \
    --evaluation-periods 1 \
    --alarm-actions arn:aws:lambda:***:*****:function:lambda-arn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we can create multiple alarms for same db instance, in case we have to scale down if metric data points are below threshold.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws cloudwatch put-metric-alarm \
    --alarm-name db-rds-postgres-low-alarm \
    ...
    --period 180 \
    --threshold 1 \
    --comparison-operator LessThanThreshold \
    ...
    --alarm-actions arn:aws:lambda:***:*****:function:lambda-arn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lambda function
&lt;/h3&gt;

&lt;p&gt;We can use lambda function to update database instances. we can use JavaScript or Python to create auto scaling script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
import json
# Initialize the RDS client
rds_client = boto3.client('rds')

def lambda_handler(event, context):

    db_instance_id = 'db-identifier-name'
    try:
        response = rds_client.describe_db_instances(DBInstanceIdentifier=db_instance_id)            

        db_status = response['DBInstances'][0]['DBInstanceStatus']

        if db_status != 'available':
            return { message: 'database is not in available state.' }

        reason_data = json.loads(event['alarmData']['state']['reasonData'])
        cpu_load = reason_data['recentDatapoints'][0]

        if cpu_load &amp;gt; 3:
            new_instance_class = 'db.t4g.large'
        else:
            new_instance_class = db_instance

        rds_client.modify_db_instance(
            DBInstanceIdentifier=db_instance_id,
            DBInstanceClass=new_instance_class,
            ApplyImmediately=True
        )

        return { 'message': 'instance modification started.' }

    except Exception as e:
        return { 'message': f"Failed to scale RDS instance {str(e)}" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resource-based Policy statement
&lt;/h3&gt;

&lt;p&gt;We also have to add Resource-based Policy statement to Lambda function to get executed from Cloud Watch Events.&lt;br&gt;
We can use AWS CLI to attach this policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws lambda add-permission \
--function-name prod-postgres-rds-asg \
--statement-id prod-postgres-rds-high-policy \
--action 'lambda:InvokeFunction' \
--principal lambda.alarms.cloudwatch.amazonaws.com \
--source-account ******** \
--source-arn arn:aws:cloudwatch:***:******:alarm:db-rds-postgres-high-alarm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lambda Role and Permissions
&lt;/h3&gt;

&lt;p&gt;We will also have to add few more permission to get details or modify db instance by lambda, for this you have to edit the assigned the Role to Lambda function, and add below JSON object to lambda role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; {
   "Effect": "Allow",
   "Action": ["rds:DescribeDBInstances", "rds:ModifyDBInstance"],
   "Resource": "arn:aws:rds:**:*****:db:db-prod-replica-1"
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it we have implemented Vertical scaling for RDS PostgreSQL database.&lt;br&gt;
Now just to verify this implementation, you can hit multiple SQL queries, in our case we had called same API multiple time using below script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const apiEndpoints = [
  'Replace with your APP API URL'
];

const token = `secrete-token`;
// Define the function to call all APIs
async function callApis() {
  try {
    const requests = apiEndpoints.map(url =&amp;gt; axios.get(url, { headers: {"Authorization" : `Bearer ${token}`} }));
    const responses = await Promise.all(requests);

    responses.forEach((response, index) =&amp;gt; {
      console.log(`Response from ${apiEndpoints[index]}`);
    });
  } catch (error) {
    console.error('Error calling APIs:', error);
  }
}
const intervalId = setInterval(callApis, 500)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;In this post, we explored the implementation of Vertical Auto Scaling for an RDS PostgreSQL database. While this approach offers some advantages, it also has notable drawbacks, especially when dealing with sudden and unpredictable spikes in load. Vertical scaling can take approximately 10 minutes to update the instance size and become fully operational, which may not be fast enough to handle rapid fluctuations in demand.&lt;/p&gt;

&lt;p&gt;Additionally, it's crucial that the database is configured for Multi-AZ (Availability Zone) support. Without this, there could be downtime during the instance resizing process, as it requires a reboot. Multi-AZ deployment helps mitigate this risk by ensuring that your database remains available during such changes.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>postgres</category>
      <category>autoscaling</category>
      <category>lambda</category>
    </item>
  </channel>
</rss>
