<?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: Sushanta Paudel</title>
    <description>The latest articles on Forem by Sushanta Paudel (@sushanta_paudel).</description>
    <link>https://forem.com/sushanta_paudel</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%2F2934615%2F1ab33037-e8c3-4133-bf39-a40a3e5cbb12.jpg</url>
      <title>Forem: Sushanta Paudel</title>
      <link>https://forem.com/sushanta_paudel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sushanta_paudel"/>
    <language>en</language>
    <item>
      <title>Building a Real-Time Data Streaming Pipeline on AWS</title>
      <dc:creator>Sushanta Paudel</dc:creator>
      <pubDate>Wed, 29 Oct 2025 03:41:36 +0000</pubDate>
      <link>https://forem.com/sushanta_paudel/building-a-real-time-data-streaming-pipeline-on-aws-i3n</link>
      <guid>https://forem.com/sushanta_paudel/building-a-real-time-data-streaming-pipeline-on-aws-i3n</guid>
      <description>&lt;p&gt;Let’s imagine we are building a system to handle continuous streams of IoT sensor data, such as temperature, humidity, and more. In this blog, I will create a data pipeline using AWS Kinesis Data Streams and AWS Lambda.&lt;/p&gt;

&lt;p&gt;For demonstration purposes, I’ll simulate IoT sensor data using a producer Lambda, which will act as our IoT device and push sensor data into the Kinesis stream. On the other end, a consumer Lambda will process the incoming events in real time, logging them to CloudWatch Logs.&lt;/p&gt;

&lt;p&gt;To ensure no data is lost, any failed events will be redirected to an SQS Dead Letter Queue (DLQ) for later analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create the Kinesis Stream:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the AWS Management Console, navigate to Kinesis and select Data streams. Click Create, then provide a name for your stream (for example, iot-sensor-stream). Choose On-demand as the capacity mode or Provisioned if you can predict the amount of data you will be streaming. Finally, click Create to set up the data stream.&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%2F9ji8oopp8v8j4g71m2d8.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%2F9ji8oopp8v8j4g71m2d8.png" alt="Creating a Kinesis Data Stream" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Create a Producer Lambda that simulates IoT sensors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8a7djh5kbnnw0zbu7kx.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%2Fs8a7djh5kbnnw0zbu7kx.png" alt="Creating Producer Lambda" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The code for the Lambda Function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import os
import json
import boto3
import random
import time

# Initialize Kinesis client
kinesis = boto3.client('kinesis')

# Stream ARN is stored in Parameter Store
ssm = boto3.client('ssm')
stream_arn = ssm.get_parameter(Name="/kinesis/iot_sensor_stream_arn")['Parameter']['Value']
stream_name = stream_arn.split("/")[-1]  # extract stream name from ARN

def lambda_handler(event, context):
    # Simulate IoT sensor readings
    sensor_data = {
        "sensor_id": f"sensor-{random.randint(1, 5)}",
        "temperature": round(random.uniform(18.0, 30.0), 2),
        "humidity": round(random.uniform(30.0, 60.0), 2),
        "timestamp": int(time.time())
    }

    # Put record into Kinesis
    response = kinesis.put_record(
        StreamName=stream_name,
        Data=json.dumps(sensor_data),
        PartitionKey=sensor_data["sensor_id"]
    )

    print(f"Produced sensor data: {sensor_data}")
    return {"statusCode": 200, "body": json.dumps(sensor_data)}

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

&lt;/div&gt;



&lt;p&gt;We need to attach IAM role to this Lambda with the following permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kinesis:PutRecord",
                "kinesis:PutRecords"
            ],
            "Resource": "arn:aws:kinesis:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:stream/iot-sensor-stream"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameter",
                "ssm:GetParameters"
            ],
            "Resource": "arn:aws:ssm:&amp;lt;region&amp;gt;:&amp;lt;account-id&amp;gt;:parameter/&amp;lt;parameter-name&amp;gt;"
        }
    ]
}

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

&lt;/div&gt;



&lt;p&gt;We need to replace 'region' with our AWS region and also replace 'account-id' with our AWS account ID. Finally, replace 'parameter-name' with the name of the SSM parameter our Lambda needs to access. This provides Lambda permission to put records into a specific Kinesis stream and read parameters from SSM Parameter Store. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Create Consumer Lambda that will process IoT data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsaeckxra39tdprnecqp.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%2Fdsaeckxra39tdprnecqp.png" alt="Creating Consumer Lambda" width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code for the consumer Data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import base64
import json

def lambda_handler(event, context):
    for record in event['Records']:
        # Kinesis data is base64 encoded
        payload = base64.b64decode(record['kinesis']['data']).decode('utf-8')
        sensor_data = json.loads(payload)

        # For demo: just log it
        print(f"Consumed sensor data: {sensor_data}")

        # Example future processing:
        # - store in DynamoDB
        # - send alerts if thresholds exceeded
        # - forward to analytics pipeline

    return {"statusCode": 200}

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

&lt;/div&gt;



&lt;p&gt;We need to attach AWSLambdaKinesisExecutionRole and sqs:SendMessage permissions to this Lambda.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Connecting Kinesis Stream to the Consumer Lambda&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the Lambda console, we need to go to consumer-lambda. In the configuration section, we will find Triggers and add Kinesis as a trigger. Our trigger is named iot-sensor-stream. &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%2Ffdo5weinqa9m0o1ck02b.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%2Ffdo5weinqa9m0o1ck02b.png" alt="Adding Kinesis Stream as a trigger in Consumer Lambda" width="800" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will keep the Starting position as latest and under on failure settings , we will select the SQS DLQ and put the ARN of iot-sensor-dlq.&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%2F6u1rusbz4az8b8b41csh.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%2F6u1rusbz4az8b8b41csh.png" alt="SQS DLQ settings" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Monitoring&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Producer Monitoring&lt;/strong&gt;&lt;br&gt;
We can go to CloudWatch Logs and open the log group /aws/lambda/lambda-producer. Verify that the logs show entries like:&lt;/p&gt;

&lt;p&gt;Produced sensor data:&lt;br&gt;
&lt;code&gt;{'sensor_id': 'sensor-3', 'temperature': 24.1, ...}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, in the Kinesis console, we can navigate to our data stream and open the Monitoring tab. Watch metrics such as IncomingRecords and PutRecord. Success to ensure that the producer is sending data successfully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consumer Monitoring&lt;/strong&gt;&lt;br&gt;
For the consumer, we can go to CloudWatch Logs → /aws/lambda/lambda-consumer and verify that entries like the following appear:&lt;/p&gt;

&lt;p&gt;Consumed sensor data:&lt;br&gt;
&lt;code&gt;{'sensor_id': 'sensor-3', 'temperature': 24.1, ...}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In the Kinesis console’s Monitoring tab, we can check metrics such as GetRecords.Success and IteratorAgeMilliseconds. These helps us ensure that the consumer is processing records in near real time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DLQ Monitoring&lt;/strong&gt;&lt;br&gt;
Finally, in the SQS console, we can open our dead letter queue (iot-sensor-dlq) and check the Approximate number of messages. If the consumer fails (for example, if you intentionally break JSON parsing in the code), failed batches will appear here for later inspection.&lt;/p&gt;

&lt;p&gt;So with this setup we have a working IoT sensor streaming pipeline with a Producer Lambda (IoT simulator) which will use Kinesis Stream for buffering and a Consumer Lambda will process this data stream. We also have provisioned SQS DLQ for failures and have integrated CloudWatch and Kinesis metrics for monitoring.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awskinesis</category>
      <category>datapipeline</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Transforming and Querying JSON Data in AWS S3 with Glue and Athena</title>
      <dc:creator>Sushanta Paudel</dc:creator>
      <pubDate>Wed, 15 Oct 2025 10:34:36 +0000</pubDate>
      <link>https://forem.com/aws-builders/transforming-and-querying-json-data-in-aws-s3-with-glue-and-athena-15ep</link>
      <guid>https://forem.com/aws-builders/transforming-and-querying-json-data-in-aws-s3-with-glue-and-athena-15ep</guid>
      <description>&lt;p&gt;AWS Glue is an AWS service that helps discover, prepare, and integrate all your data at any scale. It can aid in the process of transformation, discovering, and integrating data from multiple sources.&lt;/p&gt;

&lt;p&gt;In this blog we have a data source that uploads JSON data files periodically to an Amazon S3 bucket named 'uploads-bucket'. These JSON data files contain log entries.&lt;/p&gt;

&lt;p&gt;Below is an example of one of the log entries JSON files that are being uploaded to the Amazon S3 bucket named uploads-bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "timestamp": "2025-10-04T10:15:30Z",
  "level": "ERROR",
  "service": "authentication",
  "message": "Failed login attempt",
  "user": {
    "id": "4626",
    "username": "johndoe",
    "ip_address": "192.168.1.101"
  },
  "metadata": {
    "session_id": "abc123xyz",
    "location": "Kathmandu"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 1: Create the processing Lambda Function&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, we will implement an AWS Lambda function that processes Amazon S3 object-created events for the JSON files and the Lambda code will transform the data and write it to a second Amazon S3 bucket named &lt;br&gt;
target-bucket. This function will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Transform the JSON data.&lt;/li&gt;
&lt;li&gt;Write it to a target S3 bucket named target-bucket in Parquet format.&lt;/li&gt;
&lt;li&gt;Catalog the data in AWS Glue for querying.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import boto3
import awswrangler as wr
import pandas as pd

GLUE_DATABASE = "log_database"
TARGET_BUCKET = "target-bucket"

def parse_event(event):
    # EventBridge S3 object-created structure
    key = event['detail']['object']['key']
    bucket = event['detail']['bucket']['name']
    return key, bucket

def read_object(bucket, key):
    s3 = boto3.resource('s3')
    obj = s3.Object(bucket, key)
    return obj.get()['Body'].read().decode('utf-8')

def create_database():
    databases = wr.catalog.databases()
    if GLUE_DATABASE not in databases['Name'].values:
        wr.catalog.create_database(GLUE_DATABASE)
        print(f"Database {GLUE_DATABASE} created")
    else:
        print(f"Database {GLUE_DATABASE} already exists")

def lambda_handler(event, context):
    key, bucket = parse_event(event)
    object_body = read_object(bucket, key)

    create_database()

    log_entry = json.loads(object_body)

    # Flatten JSON
    log_df = pd.json_normalize(log_entry)

    # Create partition columns for Glue
    log_df['log_level'] = log_df['level']
    log_df['service_name'] = log_df['service']

    # Write logs to Glue catalog
    wr.s3.to_parquet(
        df=log_df.astype(str),
        path=f"s3://{TARGET_BUCKET}/data/logs/",
        dataset=True,
        database=GLUE_DATABASE,
        table="logs",
        mode="append",
        partition_cols=["log_level", "service_name"],
        description="Application log table",
        parameters={
            "source": "Application",
            "class": "log"
        },
        columns_comments={
            "timestamp": "Time of the log event",
            "level": "Log level (INFO, WARN, ERROR, etc.)",
            "service": "Service generating the log",
            "message": "Log message",
            "user.id": "User identifier",
            "user.username": "Username"
        }
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We need to attach the necessary permission role to the Lambda function. The function needs access to both the S3 bucket and AWS Glue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:Creating an Amazon EventBridge Rule&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we will create an Amazon EventBridge rule to invoke our AWS Lambda function when an object is uploaded to the Amazon S3 bucket. We will create a new Amazon EventBridge rule as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: s3-uploads&lt;/li&gt;
&lt;li&gt;Event bus: default&lt;/li&gt;
&lt;li&gt;Rule type: Rule with an event pattern&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%2Fftbass14ovsax9j5zgjy.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%2Fftbass14ovsax9j5zgjy.png" alt="Creating an AWS EventBridge Rule" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Scroll down to the Event pattern section, and enter and select:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event source: AWS Services&lt;/li&gt;
&lt;li&gt;AWS service: S3&lt;/li&gt;
&lt;li&gt;Event type: Object Created&lt;/li&gt;
&lt;li&gt;Specific Bucket: uploads-bucket&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%2F9xxl8m5kbbllduw52poe.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%2F9xxl8m5kbbllduw52poe.png" alt="Specifying the S3 bucket" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Target Configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Target types: AWS Lambda&lt;/li&gt;
&lt;li&gt;Function: Enter our Lambda function name&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%2Fsfikm7ymsoxs3xyxpt88.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%2Fsfikm7ymsoxs3xyxpt88.png" alt="Selecting the Lambda as target" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The event pattern JSON here will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "source": ["aws.s3"],
  "detail-type": ["Object Created"],
  "detail": {
    "bucket": {
      "name": ["uploads-bucket"]
    }
  }
}

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Add index partition to the logs table using AWS Glue&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the Lambda function we created runs, it will create tables named 'logs table' in the Glue Database. &lt;/p&gt;

&lt;p&gt;In the AWS Console, go to the Glue dashboard. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To see databases, in the left-hand menu, under Data Catalog, click Databases. We will find the database our Lambda function created on this section. Click on this database.&lt;/li&gt;
&lt;li&gt;Click on the logs table. The table data is stored in the target Amazon S3 bucket named target-bucket.&lt;/li&gt;
&lt;li&gt;We will now add a partition index in this table for faster query performance.&lt;/li&gt;
&lt;li&gt;To begin creating an index, click Add index&lt;/li&gt;
&lt;li&gt;Enter and select the following to configure the index
Index name: log_level_index
Index keys: log_level
Click Update&lt;/li&gt;
&lt;li&gt;Now we can also view this data using Amazon Athena. For this, there is an option at the top of the page , where we need to click on Actions and then View Data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Searching within your Indexed AWS S3 data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With index now in place, we can query efficiently using log_level as filter.&lt;/p&gt;

&lt;p&gt;We need to first open the Athena console and open the query editor and select our database.&lt;/p&gt;

&lt;p&gt;Example query: Retrieve all ERROR logs from the authentication service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT timestamp, service, message, user_username, metadata_location
FROM logs
WHERE log_level = 'ERROR'
  AND service_name = 'authentication';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, we can combine AWS Lambda, Amazon S3, AWS Glue, and Athena, to build a fully serverless, scalable data pipeline that transforms, catalogs, and queries e-commerce data in near real-time. We can also leverage Glue partitions and indexes for allows for efficient storage and faster analytics, with Athena enabling ad-hoc queries without the overhead of managing traditional databases.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>s3</category>
      <category>data</category>
      <category>awsglue</category>
    </item>
    <item>
      <title>ETL Made Easy: Integrating Multi-Source Data with AWS Glue</title>
      <dc:creator>Sushanta Paudel</dc:creator>
      <pubDate>Fri, 03 Oct 2025 07:23:37 +0000</pubDate>
      <link>https://forem.com/sushanta_paudel/etl-made-easy-integrating-multi-source-data-with-aws-glue-29p1</link>
      <guid>https://forem.com/sushanta_paudel/etl-made-easy-integrating-multi-source-data-with-aws-glue-29p1</guid>
      <description>&lt;p&gt;AWS Glue is a serverless data integration service that you can use to perform Extract, Transform, and Load (ETL) jobs. It is often used to handle large datasets and you can use it with a large variety of data sources and formats. It can be used with data lake services like Amazon S3 , Amazon Redshift, DynamoDB, data pipelines and other data warehouses.&lt;/p&gt;

&lt;p&gt;The ETL process in AWS Glue is usually as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracting information from different data stores like relational databases, NoSQL databases or object stores like Amazon S3.&lt;/li&gt;
&lt;li&gt;Transforming the information by converting to required data formats or combining different data sets to compute new values&lt;/li&gt;
&lt;li&gt;Loading information into a new data store as required for the use case&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this guide we will be unifying multi-Store order and product data with AWS Glue for analytics and marketing Insights.&lt;/p&gt;

&lt;p&gt;Step 1: Log in to your AWS account and open the AWS DynamoDB service. Then, find and click on the Book_Orders table. Once inside, you’ll be able to view all the records stored in the table, which look like this:&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%2Fwxu8w0k7bigvmtv9y8g9.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%2Fwxu8w0k7bigvmtv9y8g9.png" alt="Book Order Data stored in DynamoDB" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Go to the S3 service in AWS and locate the relevant buckets. Open each bucket to explore and review the data stored inside.&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%2Fghyt5mhnnby50cnb1ptv.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%2Fghyt5mhnnby50cnb1ptv.png" alt="Product Data stored in AWS S3" width="800" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data in these files is stored in JSON format and looks like the following example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "book_id": 101,&lt;br&gt;
  "title": "Learn Python",&lt;br&gt;
  "author": "John Doe",&lt;br&gt;
  "weight_kg": 0.5,&lt;br&gt;
  "category": "Programming"&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt;: Now let's create the destination DynamoDB Table&lt;/p&gt;

&lt;p&gt;This is where the transformed data will go.&lt;/p&gt;

&lt;p&gt;a.Create a new DynamoDB table: book_orders_transformed&lt;/p&gt;

&lt;p&gt;b.Partition key: order_id (Number)&lt;/p&gt;

&lt;p&gt;c.Leave defaults → Create table.&lt;/p&gt;

&lt;p&gt;Initially, it will have no items.&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%2F4j7yk80w4j12pc35qazp.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%2F4j7yk80w4j12pc35qazp.png" alt="Destination Dynamo DB table for transformed data" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 4: Now let us create an AWS Glue Job&lt;/p&gt;

&lt;p&gt;a. Open AWS Glue Console&lt;br&gt;
In the AWS Console, let's go the AWS Glue dashboard and then click in ETL jobs and create a new ETL job.&lt;/p&gt;

&lt;p&gt;b: Configure the Job&lt;br&gt;
Let us configure the job with the following parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: book_orders_etl&lt;/li&gt;
&lt;li&gt;IAM role: select an existing role with S3 &amp;amp; DynamoDB permissions or create one.&lt;/li&gt;
&lt;li&gt;Type: Spark Python&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 5&lt;/strong&gt;: Implementing the Glue ETL Script&lt;br&gt;
Here’s the Python Spark script for our data transformation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sys
from awsglue.transforms import *
from awsglue.utils import getResolvedOptions
from pyspark.context import SparkContext
from awsglue.context import GlueContext
from awsglue.job import Job
from awsglue.dynamicframe import DynamicFrame

# Accept parameters at runtime
args = getResolvedOptions(sys.argv, ['JOB_NAME', 's3_bucket'])

sc = SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)

# Function to calculate total price and total weight
def calculate_totals(row):
    row["total_price"] = round(row["quantity"] * row["unit_price"], 2)
    row["total_weight_kg"] = round(row["quantity"] * row["weight_kg"], 2)
    return row

# Load product data from S3
input_path = f"s3://{args['s3_bucket']}/data/"
books_frame = glueContext.create_dynamic_frame.from_options(
    connection_type="s3",
    connection_options={"paths": [input_path]},
    format="json",
    recurse=True
)

# Load order data from DynamoDB
orders_frame = glueContext.create_dynamic_frame.from_options(
    connection_type="dynamodb",
    connection_options={
        "dynamodb.input.tableName": "book_orders",
        "dynamodb.throughput.read.percent": "1.0"
    }
)

# Join orders with product info
joined_frame = Join.apply(
    frame1=orders_frame,
    frame2=books_frame,
    keys1=['book_id'],
    keys2=['book_id']
)

# Convert DynamicFrame to DataFrame to apply map
df = joined_frame.toDF()

# Apply transformation
transformed_df = df.rdd.map(lambda row: calculate_totals(row.asDict())).toDF()

# Convert back to DynamicFrame
transformed_frame = DynamicFrame.fromDF(transformed_df, glueContext, "transformed_frame")

# Write transformed data back to DynamoDB
glueContext.write_dynamic_frame.from_options(
    frame=transformed_frame,
    connection_type="dynamodb",
    connection_options={
        "dynamodb.output.tableName": "book_orders_transformed",
        "dynamodb.throughput.write.percent": "1.0"
    }
)

job.commit()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Feh9nrk5o1o415xhdjjth.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%2Feh9nrk5o1o415xhdjjth.png" alt="AWS Glue Job ETL script" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6&lt;/strong&gt;: Run the Glue Job&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We will open our job and click on Run with parameters option&lt;/li&gt;
&lt;li&gt;Add parameter:
Key: s3_bucket
Value: my-glue-books-data&lt;/li&gt;
&lt;li&gt;Click Run job&lt;/li&gt;
&lt;li&gt;We can then monitor the job in Run details and wait till the Status changes to Succeeded&lt;/li&gt;
&lt;li&gt;Now we can open book_orders_transformed table in DynamoDB and verify that the book_orders_transformed table has our transformed data fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 7&lt;/strong&gt;: Validate Your ETL Output&lt;/p&gt;

&lt;p&gt;The DynamoDB table book_orders_transformed will now have our transformed data fields.&lt;/p&gt;

&lt;p&gt;Example records in the table:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
  "order_id": 1,&lt;br&gt;
  "customer_name": "Alice",&lt;br&gt;
  "book_id": 101,&lt;br&gt;
  "quantity": 2,&lt;br&gt;
  "unit_price": 12.5,&lt;br&gt;
  "order_date": "2025-10-01",&lt;br&gt;
  "title": "Learn Python",&lt;br&gt;
  "author": "John Doe",&lt;br&gt;
  "weight_kg": 0.5,&lt;br&gt;
  "category": "Programming",&lt;br&gt;
  "total_price": 25.0,&lt;br&gt;
  "total_weight_kg": 1.0&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So in this guide we have successfully unified and transformed multi-source order and product data using AWS Glue. The ETL workflow efficiently extracted data from both DynamoDB and S3, applied necessary transformations including calculations for total price and total weight, and loaded the enriched dataset into a new DynamoDB table ready for analytics and marketing insights.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>etl</category>
      <category>awsglue</category>
      <category>dynamodb</category>
    </item>
    <item>
      <title>Just published a new blog on Blue-Green Deployment for Next.js apps using AWS EC2, CodeDeploy, and Auto Scaling! Learn how to achieve zero-downtime deployments with a scalable, production-grade CI/CD pipeline on AWS. Perfect for teams looking to level up</title>
      <dc:creator>Sushanta Paudel</dc:creator>
      <pubDate>Tue, 29 Jul 2025 06:27:19 +0000</pubDate>
      <link>https://forem.com/sushanta_paudel/just-published-a-new-blog-on-blue-green-deployment-for-nextjs-apps-using-aws-ec2-codedeploy-and-4adc</link>
      <guid>https://forem.com/sushanta_paudel/just-published-a-new-blog-on-blue-green-deployment-for-nextjs-apps-using-aws-ec2-codedeploy-and-4adc</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik" class="crayons-story__hidden-navigation-link"&gt;Blue-Green Deployment of a Next.js App on EC2 Using AWS CodeDeploy&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/aws-builders"&gt;
            &lt;img alt="AWS Community Builders  logo" 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%2Forganization%2Fprofile_image%2F2794%2F88da75b6-aadd-4ea1-8083-ae2dfca8be94.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/sushanta_paudel" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&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%2Fuser%2Fprofile_image%2F2934615%2F1ab33037-e8c3-4133-bf39-a40a3e5cbb12.jpg" alt="sushanta_paudel profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/sushanta_paudel" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Sushanta Paudel
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Sushanta Paudel
                
              
              &lt;div id="story-author-preview-content-2729937" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/sushanta_paudel" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F2934615%2F1ab33037-e8c3-4133-bf39-a40a3e5cbb12.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Sushanta Paudel&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/aws-builders" class="crayons-story__secondary fw-medium"&gt;AWS Community Builders &lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 29 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik" id="article-link-2729937"&gt;
          Blue-Green Deployment of a Next.js App on EC2 Using AWS CodeDeploy
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cicd"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cicd&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/nextjs"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;nextjs&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>aws</category>
      <category>devops</category>
      <category>cicd</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Blue-Green Deployment of a Next.js App on EC2 Using AWS CodeDeploy</title>
      <dc:creator>Sushanta Paudel</dc:creator>
      <pubDate>Tue, 29 Jul 2025 06:24:46 +0000</pubDate>
      <link>https://forem.com/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik</link>
      <guid>https://forem.com/aws-builders/blue-green-deployment-of-a-nextjs-app-on-ec2-using-aws-codedeploy-34ik</guid>
      <description>&lt;p&gt;In this blog, we'll walk through setting up a Blue-Green deployment strategy for a Next.js application hosted on Amazon EC2 instances.&lt;/p&gt;

&lt;p&gt;With Blue-Green Deployment we can deploy application updates with zero-downtime and we will be using AWS services like EC2, Auto-Scaling, Load Balancing and Code Deploy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Setup AMI Image for Auto-Scaling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In AWS Auto Scaling, an Amazon Machine Image (AMI) acts as the blueprint for launching new EC2 instances. Setting up a custom AMI ensures that every instance in the Auto Scaling group launches with the exact configuration needed (OS, applications, libraries, security settings, etc.).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Steps:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch a Base EC2 Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start an EC2 instance with a base AMI (like Amazon Linux or Ubuntu).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customize the Instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install required software, configure settings, apply security patches, and set up your application.&lt;/p&gt;

&lt;p&gt;Here, we need to make sure CodeDeploy agent is installed and running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Update packages
sudo apt-get update -y

# Install dependencies
sudo apt-get install ruby-full wget unzip -y

# Download and install the CodeDeploy agent
cd /home/ubuntu
wget https://aws-codedeploy-&amp;lt;region&amp;gt;.s3.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto

# Start and enable the agent
sudo systemctl start codedeploy-agent
sudo systemctl enable codedeploy-agent

# Verify status
sudo systemctl status codedeploy-agent

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the AMI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Use the AMI to create a Launch Template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When creating a launch template or configuration for your Auto Scaling group, specify the custom AMI ID.&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%2Fo371k3885o2a4ve613ey.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%2Fo371k3885o2a4ve613ey.png" alt="Creating a launch template" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We do this to make sure all the instances that we will launch by Auto-scaling are identical, reliable and also ready to serve traffic immediately upon startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Create a Load balancer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a load balancer after navigating to the EC2 dashboard. Select Internet-facing as the scheme. Add a listener on port 80(HTTP) or 443(HTTPS). Under Availability Zones, select your VPC and the subnets across at least two availability zones. Then , we need to configure a security group that allows inbound traffic on the listener port ( HTTP:80).&lt;/p&gt;

&lt;p&gt;Create a new Target Group or select an existing one and select Instance or IP as the target type. Select an appropriate health check path. We need to point the app’s health check endpoint here. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Set up Auto Scaling Group with the launch template&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate to Auto-Scaling Group in the dashboard and click Create Auto Scaling Group. Choose the appropriate VPC and subnets for our instances. &lt;/p&gt;

&lt;p&gt;Select the launch template we created earlier.&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%2Fy9kcoy1winebclo14l3m.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%2Fy9kcoy1winebclo14l3m.png" alt="Choose the launch template" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Attach the internet-facing Application Load Balancer we created earlier to the auto scaling group. &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%2F6xi89mdoi5ocimy9a5u1.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%2F6xi89mdoi5ocimy9a5u1.png" alt="Attach the load balancer to the Auto Scaling Group" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Define the scaling capacity as required ;minimum: 2, desired: 2, and maximum: 3 instances. Finally, review all settings and click "Create Auto Scaling Group" to complete the setup.&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%2F0cea0ov2c2dhjnsy9624.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%2F0cea0ov2c2dhjnsy9624.png" alt="Define the scaling parameters" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We need to make sure our source code repository includes a valid appspec.yml file in the root directory. This file tells CodeDeploy how to deploy your application and when to run specific scripts during the deployment lifecycle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/app

hooks:
  BeforeInstall:
    - location: scripts/stop_server.sh
      timeout: 60
  AfterInstall:
    - location: scripts/install_dependencies.sh
      timeout: 120
  ApplicationStart:
    - location: scripts/start_server.sh
      timeout: 60

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Create application and deployment group with CodeDeploy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate to AWS CodeDeploy, go to Deploy &amp;gt; Applications, and click Create Application". After creating the application, proceed to create a Deployment Group by filling in all the required details such as service role, deployment type, and environment configuration. The deployment type should be set to Blue/Green.&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%2Fsoq4623inyy6umccs2z5.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%2Fsoq4623inyy6umccs2z5.png" alt="Deployment Type" width="684" height="597"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the Load Balancer we created earlier and attached to the auto-scaling group , then click Create Deployment Group to complete the setup.&lt;/p&gt;

&lt;p&gt;Make sure to select the correct deployment settings as per requirement. &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%2F7iv1mjm2z7auzyzj84il.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%2F7iv1mjm2z7auzyzj84il.png" alt="Deployment Settings" width="684" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to select how long you want to keep the older instance running. It is relevant to completion of the code pipeline run. Here I have chosen to terminate the instances immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Integrate this CodeDeploy application to the CodePipeline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To integrate CodeDeploy with CodePipeline, navigate to AWS CodePipeline and create or edit an existing pipeline. In the Deploy stage, choose AWS CodeDeploy as the deployment provider. Select the previously created CodeDeploy application and deployment group. This will link our pipeline to the deployment process, allowing automated deployments to our EC2 instances whenever new changes are pushed from your source repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Blue/Green Deployment&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we can monitor our blue/green deployment process in the CodeDeploy console. Blue/Green deployments allow quick rollback if something fails.&lt;/p&gt;

&lt;p&gt;In the first step, a replacement instance is provisioned.&lt;br&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%2Fxethibjp99sfqoxhq0md.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%2Fxethibjp99sfqoxhq0md.jpg" alt="Replacement Instance being created" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the second step, our application will be installed in the replacement instance launched.&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%2Fwhk7v0jcbfkm1dajio5t.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%2Fwhk7v0jcbfkm1dajio5t.jpg" alt="Application being installed in the replacement instance" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, the next step is blocking the traffic to the original instance and redirecting traffic to the new instance. We can track the progress of this in the CodeDeploy console.&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%2Fmrs52as73j7idx8qo1y8.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%2Fmrs52as73j7idx8qo1y8.jpg" alt="Traffic being moved to the replacement instance" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, when the traffic is shifted to the replacement instance, the original instance is then terminated.&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%2Fhy91g83hronviristvqw.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%2Fhy91g83hronviristvqw.jpg" alt="Deleting the original instance" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By combining CodeDeploy Blue-Green deployment with EC2, Auto Scaling, Load Balancer and CodePipeline, we can achieve seamless, zero-downtime deployments for our Next.js application—ensuring high availability, easy rollbacks, and production-grade scalability on AWS.&lt;/p&gt;

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