<?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: oscarrobert-star</title>
    <description>The latest articles on DEV Community by oscarrobert-star (@oscarrobertstar).</description>
    <link>https://dev.to/oscarrobertstar</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%2F819877%2Ff1cc1ccd-476a-475a-8765-f22d4386a9c3.jpeg</url>
      <title>DEV Community: oscarrobert-star</title>
      <link>https://dev.to/oscarrobertstar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oscarrobertstar"/>
    <language>en</language>
    <item>
      <title>E-commerce Business Logic: Customer Journeys and The Services Needed</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Thu, 04 Sep 2025 08:36:40 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/e-commerce-business-logic-customer-journeys-and-the-services-needed-3khm</link>
      <guid>https://dev.to/oscarrobertstar/e-commerce-business-logic-customer-journeys-and-the-services-needed-3khm</guid>
      <description>&lt;p&gt;Ever wondered how e-commerce platforms work? In this series, we'll delve into these details and much more. In the previous posts, I introduced the &lt;a href="https://dev.to/oscarrobertstar/reverse-learning-with-ai-breaking-down-ai-generated-business-cases-into-technical-solutions-42bb"&gt;problem statement&lt;/a&gt; and shared &lt;a href="https://dev.to/oscarrobertstar/my-thoughts-on-the-business-case-by-ai-chatgpt-4pg7"&gt;my initial thoughts&lt;/a&gt; on the same. Here, we now want to get our feet wet by diving into the details that make an e-commerce platform work. And in future posts, we'll talk about development and deployment.&lt;/p&gt;

&lt;p&gt;On a high level, in an e-commerce platform, the goal is to showcase your products, have customers browse your catalog. Enable them to add items into a cart, and once they are done shopping, check out and complete payments. Here is what the customer journey would look like. &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%2F0vg94rm6zdb8hfd0xxqg.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%2F0vg94rm6zdb8hfd0xxqg.png" alt="e-commerce customer journey" width="800" height="1965"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the business owner, you want to be able to add and track your inventory, manage customer details, monitor orders for dispatch, and track payments. &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%2Fqo6u6blwhahgewws9749.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%2Fqo6u6blwhahgewws9749.png" alt="e-commerce back office journey" width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Features &amp;amp; Services
&lt;/h2&gt;

&lt;p&gt;From the description above, some of the services we would need are:&lt;/p&gt;




&lt;h3&gt;
  
  
  1. Product and Inventory Management
&lt;/h3&gt;

&lt;p&gt;We can have one service handle all these. Let's call it Product Service.&lt;/p&gt;

&lt;p&gt;This will handle all the features related to adding products, viewing products, updating product descriptions and inventory, and deleting products. &lt;br&gt;
Here are the api endpoints we will need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /products       # Add a product
GET     /products       # Get all products
GET     /products/:id   # Get products by ID
PATCH   /products/:id   # Editing a product
DELETE  /products/:id   # Deleting a product
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The Product Data Model
&lt;/h4&gt;

&lt;p&gt;We had earlier talked about a high-level data model for each product in the database design. And true to our thoughts, we haven't deviated much. At least for the products model. We've only added one new item, &lt;code&gt;category&lt;/code&gt;, to help us classify our products.&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%2Fbugjnvdhwr0s6yiu9xec.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%2Fbugjnvdhwr0s6yiu9xec.png" alt="Products data model" width="800" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Product image handling.
&lt;/h4&gt;

&lt;p&gt;When adding products, we need to add images. And since we'll design the UI to serve images of some specification, we need to make sure that the images are resized to the defined specification. Since image resizing is a compute-intensive task, we will decouple this process by having a separate function that gets triggered by image upload. A little infra design, ahead of time, this will be managed by a lambda function which will be triggered by S3 event notification for image uploads. We will expose the S3 bucket from api gateway to enable us upload images of whatever size. Once the image processing is complete, the function will update the product table with the image url. &lt;/p&gt;




&lt;h3&gt;
  
  
  2. Shopping carts
&lt;/h3&gt;

&lt;p&gt;It only makes sense to talk about shopping carts at this point. This follows the natural flow of a customer's shopping journey. &lt;/p&gt;

&lt;h4&gt;
  
  
  Cart service.
&lt;/h4&gt;

&lt;p&gt;This service enables us to add items to a virtual cart. The objectives for this service are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To enable any user to add items into cart, whether authenticated or as a guest&lt;/li&gt;
&lt;li&gt;To have a shopping cart that can be accessed from multiple devices for authenticated customers&lt;/li&gt;
&lt;li&gt;To have a cart that clears after some time of inactivity. Time to live (ttl) is updated each time there is an activity on the cart e.g. adding an item.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For cart management, I'm opting to write data to Redis. This lets us load the cart quickly and reduces queries to the database. It will also enable us to clear the cart after a set period of time of inactivity. As a buffer, in case of memory pressure, I'm setting the eviction policy on redis to &lt;code&gt;volatile-lru&lt;/code&gt; which evicts among keys with TTL, and since all the cart items have ttl, this should help clear the cart items.&lt;/p&gt;

&lt;p&gt;This approach of cart management assumes that the inventory churn rate is high and therefore ensures we don't have stale carts. Furthermore, since we know when the cart will be cleared, we can inform the customers via pop up banners on the UI that their carts will expire after a given number of minutes.&lt;/p&gt;

&lt;p&gt;The api endpoints are as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /cart/add                 # Add to cart
GET     /cart                     # Get cart data
POST    /cart/remove              # Remove an item from cart
POST    /cart/clear?x-cart-id     # Clear cart
PATCH   /cart/edit                # Edit item quantity in the cart
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  3. Done shopping? Check out.
&lt;/h3&gt;

&lt;p&gt;Checking out shows us the intention to buy and therefore, we can proceed to create orders. This is the first time we are persisting data. The checkout service does only 2 actions, creating orders and initiating payments. That's it! The service's function is straightforward.&lt;/p&gt;

&lt;p&gt;Api endpoint&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /checkout    # Creating an order and initiate payment process
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  4. Orders
&lt;/h3&gt;

&lt;p&gt;The Orders service allows us to manage orders. Here we can see the order details including the items ordered, payment status and shipping status. &lt;/p&gt;

&lt;h4&gt;
  
  
  The orders data model.
&lt;/h4&gt;

&lt;p&gt;We'll have 2 tables for this. One is &lt;code&gt;orders&lt;/code&gt; and the other &lt;code&gt;order_items&lt;/code&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%2F5j2caq8xlmxy90yogcie.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%2F5j2caq8xlmxy90yogcie.png" alt="order service model" width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The endpoints will be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /orders                            # Create an order
GET     /orders                            # Get all orders
GET     /orders/:id                        # Get order by ID
PATCH   /orders/:id/payment_status         # Update payment status
PATCH   /orders/:id/shipping_status        # Update shipping status
GET     /orders/status/:payment_reference  # Get order by payment reference
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above definition, we should be able to handle all requests related to order management.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. Payments
&lt;/h3&gt;

&lt;p&gt;To complete an order, payment is required. Therefore, we have a Payment Service for the sole purpose of initiating payment. In this case study, we are using &lt;a href="https://paystack.com/" rel="noopener noreferrer"&gt;PayStack&lt;/a&gt; as the payment service provider. Payment service calls Paystack API which returns a link that is redirected to on the UI to have the clients fill in their payment details. All payment transactions are handled in PayStack, and a callback is sent to us via public webhook for verification and order completion. &lt;/p&gt;

&lt;p&gt;We have the following endpoints that perform the described payments functionality:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /payments/pay        # Initiates payment
POST    /payments/webhook    # Receives the payment callback
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  6. Users and Customers
&lt;/h3&gt;

&lt;p&gt;Obviously, we can't allow unauthenticated users to perform actions in our system. Therefore, we have a Users service that handles the business logic of creating customers and staff users.&lt;br&gt;
For authentication and authorization, we'll leverage AWS Cognito. We will manage both customers and users using a single Cognito user pool and add groups (&lt;code&gt;Customers&lt;/code&gt; and &lt;code&gt;admins&lt;/code&gt;). This approach centralizes identity management while maintaining a clear separation for authorization rules. &lt;/p&gt;

&lt;p&gt;On logging in, Cognito provides us with JWT (JSON Web Token). Our backend endpoints are secured by verifying this JWT. This allows us to lock down endpoints not by just authenticating users but to specific user groups based on the claims inside the tokens.&lt;/p&gt;
&lt;h4&gt;
  
  
  Customer and user models
&lt;/h4&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%2Fdoegcuj3ylnr78e6xjtk.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%2Fdoegcuj3ylnr78e6xjtk.png" alt="Customer and user models" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Endpoints to our backend include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /users/signup            # Sign up
POST    /users/confirm-signup    # Confirm email address
POST    /users/login             # Log in
GET     /users/profile           # Get user profile
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  7. Notifications
&lt;/h3&gt;

&lt;p&gt;Communication is key. At different points in this customer journey we'll have to communicate with our customer not only to get them informed on different events like order completion or order dispatch  but also for customer satisfaction and feedback. There are tools to measure customer satisfaction like net promoter score (NPS) but we won't get into that here. &lt;br&gt;
We'll create a notification service to manage communication templates and send out notifications via text messages or emails. &lt;br&gt;
Remember, to send promotional messages, we must have an opt in option for compliance purposes. &lt;/p&gt;

&lt;p&gt;To handle communication via different channels like phone numbers and email, we can employ services such as AWS SES and AWS SNS. The details for these yet to come in the cloud infrastructure section.&lt;/p&gt;

&lt;p&gt;This way none of the services sending notifications care about how they are sent, rather they focus on what is being sent out.&lt;/p&gt;

&lt;h4&gt;
  
  
  Api Endpoint
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST    /notifications/order/confirmation
POST    /notifications/order/dispatched
POST    /notifications/order/payment-reminder
POST    /notifications/promotions
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  8. Client pages.
&lt;/h3&gt;

&lt;p&gt;These include customer page (the e-commerce shop itself) and the admin page (the back office). These pages piece everything together in nice UI/UX designs to make it appealing for user interactions. Since this is not a UI/UX series, we will not be getting into those details. &lt;/p&gt;




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

&lt;p&gt;This is getting rather long. Let's stop it here and pick it up on the next post, &lt;a href=""&gt;Developing an E-commerce website&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>architecture</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>My thoughts on the business case by AI (ChatGPT)</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Wed, 27 Aug 2025 13:27:31 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/my-thoughts-on-the-business-case-by-ai-chatgpt-4pg7</link>
      <guid>https://dev.to/oscarrobertstar/my-thoughts-on-the-business-case-by-ai-chatgpt-4pg7</guid>
      <description>&lt;p&gt;So I've decided to take on the challenge to build an e-commerce platform as a solutions architect for a new startup. The client? AI (ChatGPT). I have a business case that was generated for me by AI, and from it, I'd like to go through the intricacies and nuances of building a fully scalable platform.&lt;/p&gt;

&lt;p&gt;Before we get into the solutions, here are my thoughts on the problem AI provided. Here is the &lt;a href="https://dev.to/oscarrobertstar/business-case-e-commerce-platform-for-a-niche-market-2kj9"&gt;business case&lt;/a&gt; to refresh your memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The scope
&lt;/h2&gt;

&lt;p&gt;The scope of this particular problem is quite wide and would need an entire tech department to build and maintain. Companies pay thousands of dollars to have such a system developed. This problem spans multiple areas like solution designing, UI/UX, Development (Both frontend and backend code), Deployment, Monitoring, and then the cycle starts over. Visually, this is what that cycle ideally looks like.&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%2Fbw7rlrxd9aicb43da91p.webp" 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%2Fbw7rlrxd9aicb43da91p.webp" alt="Software Development Life Cycle" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Business case validation
&lt;/h2&gt;

&lt;p&gt;From a product perspective, a business case of this scope would require its product team to conduct a lot of market research to prove that this is a viable business and the demand is as described. Only then can it warrant a solution that scales to serve clients between 5,000 and 50,000 in a day. It would be a good idea to start small and scale as demand grows. That way, you get to validate and iterate your value proposition with real customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. ChatGPT has somewhat simplified this case.
&lt;/h2&gt;

&lt;p&gt;What's fascinating here is that the AI has already done a lot of the heavy lifting. In a real-world scenario, a solutions architect would be the one translating the CEO's high-level vision and the business team's needs into these specific, quantifiable requirements. This ChatGPT-generated case essentially hands us the technical blueprint, skipping a crucial and often challenging part of the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Tackling the Mountain: Where We'll Start.
&lt;/h2&gt;

&lt;p&gt;As much as AI has done some work for us, we still have a mountain to tackle. We know that we need to have 2 client pages, one for admins and the other for clients. We need to design the workflows for browsing the product catalog, cart management, placing orders, making payments, and sending notifications, to mention a few areas. We also need to bring all these together, and make sure that there is seamless Interservice communication. We need to design the authentication mechanism, the data layer and so much more. We will get into all these in detail in the coming sections of the series.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Technical interview point of view
&lt;/h2&gt;

&lt;p&gt;If you were asked to design a solution for this in an interview, how would you approach it?&lt;/p&gt;

&lt;p&gt;The first thing that comes to mind is the 2 client pages. We can serve these from a Content Delivery Network (CDN) such such AWS CloudFront or GCP's Cloud CDN. This ensures that the pages can load quickly globally since we'll have static content cached. &lt;/p&gt;

&lt;p&gt;For the dynamic content, the clients call the backend via a load balancer that distributes the traffic to different backend applications. We can have the backend apps autoscale based on some metric of choice such as CPU or memory utilization, or even based on request count. &lt;/p&gt;

&lt;p&gt;The backend reads data from the database. Between the applications and the database, we have caching enabled for frequently accessed data e.g product data. We can use least recently used(LRU) cache invalidation strategies to ensure we always have the latest version of the product data displayed to the customers. The other option we have is using least frequently used cache invalidation. However, this can be computationally expensive since we would have to keep track of the counts for each item accessed in the cache.&lt;/p&gt;

&lt;p&gt;Once an order has been placed, initiate payment processing to Stripe (or whatever payment platform you prefer). We then receive callbacks via webhooks from the payment provider and send notifications to the customer on successful order placement or when the order has been dispatched.&lt;/p&gt;

&lt;p&gt;Here is a pictorial depiction of the above:&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%2Fd5h5gmshjlde83fwuwap.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%2Fd5h5gmshjlde83fwuwap.png" alt="Initial System design" width="800" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The database design. &lt;br&gt;
to store data, we would need the following tables: customer, product, order, order_items, users. Here is what the data schemas would look like. &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%2Fa8fub443er39ig2d1qg5.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%2Fa8fub443er39ig2d1qg5.png" alt="Database schemas" width="800" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will use an SQL database to store the data because we can benefit from relationships to ensure data integrity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;We'll be designing &lt;a href=""&gt;the business logic, customer journeys, and the services needed&lt;/a&gt; to make it all possible. Stay tuned!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Business Case: E-Commerce Platform for a Niche Market</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Tue, 26 Aug 2025 07:19:53 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/business-case-e-commerce-platform-for-a-niche-market-2kj9</link>
      <guid>https://dev.to/oscarrobertstar/business-case-e-commerce-platform-for-a-niche-market-2kj9</guid>
      <description>&lt;h3&gt;
  
  
  Business Summary:
&lt;/h3&gt;

&lt;p&gt;You're building an e-commerce platform for a small-to-medium enterprise (SME) selling handmade, eco-friendly products. The company expects seasonal traffic spikes (especially during sales like Earth Day, Black Friday), and they need the site to be highly available, scalable, and secure. &lt;br&gt;
They also plan to expand globally within the next year.&lt;br&gt;
The MVP (minimum viable product) must be ready to handle 5,000 daily users with the capability to scale to 50,000 during sales events.&lt;br&gt;
 The CEO loves "serverless" buzzwords, but they’re open to containers if needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Core Functional Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Customers must browse products, add to cart, checkout, and receive email confirmations.&lt;/li&gt;
&lt;li&gt;Admins need an internal dashboard to manage inventory, orders, and customer data.&lt;/li&gt;
&lt;li&gt;Orders should trigger payment processing (assume you’re using Stripe).&lt;/li&gt;
&lt;li&gt;Inventory must update in real time to avoid overselling.&lt;/li&gt;
&lt;li&gt;Support for user accounts, including password reset and MFA.&lt;/li&gt;
&lt;li&gt;All product images and static assets must load quickly worldwide.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Non-Functional Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Scalability&lt;/em&gt;: Must handle spikes in traffic without downtime.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Availability&lt;/em&gt;: 99.9% uptime (no single points of failure).&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Security&lt;/em&gt;:

&lt;ul&gt;
&lt;li&gt;PCI-DSS compliance for payment data (Stripe handles most of it, but your app must be secure).&lt;/li&gt;
&lt;li&gt;Customer data must be encrypted at rest and in transit.&lt;/li&gt;
&lt;li&gt;Protection from common web attacks (SQL injection, XSS, DDoS).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;em&gt;Performance&lt;/em&gt;: Page load time under 3 seconds globally.&lt;/li&gt;

&lt;li&gt;

&lt;em&gt;Observability&lt;/em&gt;: Full monitoring, logging, and alerting for failures.&lt;/li&gt;

&lt;li&gt;

&lt;em&gt;Cost Optimization&lt;/em&gt;: Minimal operational overhead; pay-for-use preferred.&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. User Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Customer Portal&lt;/em&gt;: Browse catalog, search products, checkout process.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Admin Portal&lt;/em&gt;: CRUD for products, view orders, manage customers.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Authentication&lt;/em&gt;: Cognito (or something equivalent), with social login (Google, Facebook).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Data Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Product catalog (name, price, description, image, stock).&lt;/li&gt;
&lt;li&gt;Customer data (PII, shipping info, order history).&lt;/li&gt;
&lt;li&gt;Orders (customer, items, payment status, shipping status).
Audit logs (who did what, and when).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Operational Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;CI/CD pipeline: Push to main → automatic build, test, deploy.
Blue/Green or Canary deployments for releases.&lt;/li&gt;
&lt;li&gt;Disaster recovery: Backup and restore within 4 hours (RTO). Data loss no more than 15 minutes (RPO).&lt;/li&gt;
&lt;li&gt;Cost reporting: Regular cost monitoring and alerts for unusual spikes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Compliance &amp;amp; Legal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GDPR compliance (data deletion on request, explicit consent for data processing).&lt;/li&gt;
&lt;li&gt;PCI-DSS (payment handling done through Stripe, but secure the backend and database).&lt;/li&gt;
&lt;li&gt;Data residency: Store customer data in EU and US regions based on customer location.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Optional Stretch Goals (if you're feeling spicy)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Integrate with AWS Personalize to offer product recommendations.&lt;/li&gt;
&lt;li&gt;Add real-time order tracking via WebSockets or AppSync subscriptions.&lt;/li&gt;
&lt;li&gt;Build a mobile app backend alongside the web version.&lt;/li&gt;
&lt;li&gt;Implement Infrastructure as Code (IaC) in Terraform or CDK.&lt;/li&gt;
&lt;li&gt;Implement serverless-first architecture (if you can justify it).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  On to the solutioning
&lt;/h2&gt;

&lt;p&gt;How exciting is this, right?😅&lt;br&gt;
Let's not keep you waiting, let's get cracking. &lt;a href=""&gt;My thoughts on this business problem&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Reverse learning with AI: Breaking down AI-generated business cases into technical solutions</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Wed, 20 Aug 2025 12:31:42 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/reverse-learning-with-ai-breaking-down-ai-generated-business-cases-into-technical-solutions-42bb</link>
      <guid>https://dev.to/oscarrobertstar/reverse-learning-with-ai-breaking-down-ai-generated-business-cases-into-technical-solutions-42bb</guid>
      <description>&lt;p&gt;In the wake of AI and vibe coding, most of us, developers, gravitate towards prompting AI agents to find solutions, or debug, or build something. &lt;br&gt;
So I figured, why not let AI give me a problem, and then I work backwards to get the solution?&lt;/p&gt;

&lt;p&gt;I'm going to take you on my journey to build a system, from a problem statement generated by AI (ChatGPT). &lt;/p&gt;

&lt;p&gt;But first, &lt;/p&gt;

&lt;h2&gt;
  
  
  Who am I?
&lt;/h2&gt;

&lt;p&gt;Hi, my name is Oscar Okiya. I'm passionate about solving problems, especially tech-related. I serve as a DevOps/Cloud Engineer. You can find me on &lt;a href="https://www.linkedin.com/in/oscar-robert-okiya/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, I'd be happy to connect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why am I doing this?
&lt;/h2&gt;

&lt;p&gt;Other than learning (of course), I'm working on improving my solutions architecture and technical writing skills. &lt;/p&gt;

&lt;p&gt;That said,...&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;A few months ago, I wanted to start doing projects to refresh my knowledge, test out new cloud offerings, and put out new content. It turned out that at the same time, I was engaging ChatGPT quite a lot. Then it dawned on me that instead of prompting AI to give me answers to random questions, why don't I ask it for a business problem and try to see if I transform it into technical requirements, break it down into bite-size and develop it. Guess what, it did. And that will be the start of this journey. &lt;/p&gt;

&lt;h2&gt;
  
  
   The first problem statement
&lt;/h2&gt;

&lt;p&gt;For our first case, let's look at building an e-commerce platform for a new startup that is selling handmade, eco-friendly products. The company serves 5k clients on a daily, and scales to 50k clients seasonally on events like black Friday. &lt;/p&gt;

&lt;p&gt;I bet you are wondering, is this all AI gave you? Of course not. I'm showing you the details of the requirements next. But before then,&lt;/p&gt;

&lt;h3&gt;
  
  
  Pause
&lt;/h3&gt;

&lt;p&gt;If you're as excited as I am about this, give me a thumbs up! I'd like to know who I'm taking with me in this journey. A final note, this is going to be a series, so at the end of each post, you will find links to the next phase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's Go!
&lt;/h3&gt;

&lt;p&gt;Here is the detailed business case. &lt;a href="https://dev.to/oscarrobertstar/business-case-e-commerce-platform-for-a-niche-market-2kj9"&gt;1. An E-Commerce Platform for a Niche Market&lt;/a&gt;. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>3 tier architecture with CICD</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Mon, 16 Oct 2023 09:04:56 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/3-tier-architecture-with-cicd-4p1g</link>
      <guid>https://dev.to/oscarrobertstar/3-tier-architecture-with-cicd-4p1g</guid>
      <description>&lt;h2&gt;
  
  
  ABC Platform Documentation
&lt;/h2&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%2Fcb6fdlv1s6gdhuvn6ij6.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%2Fcb6fdlv1s6gdhuvn6ij6.png" alt=" " width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The ABC platform is structured into three distinct tiers: Frontend, Backend, and Database. This documentation provides an overview of the architecture, technologies used, and deployment strategies within each tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Tier
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hosting
&lt;/h3&gt;

&lt;p&gt;The Frontend of the ABC platform is hosted in AWS S3, and its content is distributed via AWS CloudFront, a content delivery network. AWS Certificate Manager is used to request SSL/TLS certificates for the CloudFront domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  DNS Management
&lt;/h3&gt;

&lt;p&gt;The CloudFront DNS is managed through AWS Route 53, where all Domain Name System (DNS) configurations are handled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Backend Tier
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Hosting
&lt;/h3&gt;

&lt;p&gt;Backend services are hosted in AWS ECS Fargate, a serverless service designed for orchestrating Docker containers. To facilitate this, we create an ECS cluster, where services are deployed. Each service is defined by a task definition, specifying details like the Docker image to run. Deploying task definitions results in the creation of tasks, which are the containers responsible for running each service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Images
&lt;/h3&gt;

&lt;p&gt;Docker images are built and stored in AWS Elastic Container Registry (ECR), from which they are pulled into AWS ECS services for execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database Tier
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Main Database
&lt;/h3&gt;

&lt;p&gt;The primary database for the ABC platform is MySQL. The data will be migrated from its original source into AWS RDS Aurora for MySQL. This transition is made to optimize cost-efficiency and enhance overall database performance, as Aurora for MySQL is considered more efficient than RDS for MySQL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chat App Database
&lt;/h3&gt;

&lt;p&gt;For the chat app component of the platform, the current MongoDB database will be migrated to use Amazon DynamoDB, a NoSQL database service compatible with MongoDB. This migration aims to improve the efficiency and scalability of the chat app's data management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Log Management
&lt;/h3&gt;

&lt;p&gt;All logs generated by the ABC platform are sent to AWS CloudWatch. This centralizes log management and facilitates the creation of metrics and alarms to promptly notify administrators of potential issues within the platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notifications
&lt;/h3&gt;

&lt;p&gt;AWS Simple Notification Service (SNS) is utilized for all notification purposes, ensuring that administrators are promptly informed of any critical events.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI/CD (Continuous Integration/Continuous Deployment)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Source Code Management
&lt;/h3&gt;

&lt;p&gt;The source code of the ABC platform is stored in Bitbucket, a Git-based source code management platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD Pipelines
&lt;/h3&gt;

&lt;p&gt;Bitbucket is configured to run CI/CD pipelines responsible for building and deploying artifacts to AWS S3 for the frontend and Docker images to AWS ECR for storage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend Deployment
&lt;/h3&gt;

&lt;p&gt;To deploy the backend services, AWS CodeDeploy is used in conjunction with Bitbucket. This combination facilitates seamless updates to the AWS ECS tasks, ensuring a smooth deployment process.&lt;/p&gt;

&lt;h3&gt;
  
  
  SonarQube Integration
&lt;/h3&gt;

&lt;p&gt;The ABC platform utilizes SonarQube, a powerful code analysis tool, within the CI/CD pipeline. SonarQube is used to perform continuous code quality checks and identify issues, vulnerabilities, and code smells in the source code. These checks help maintain code quality and security throughout the development and deployment process.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Accounts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Multi-Account Strategy
&lt;/h3&gt;

&lt;p&gt;ABC employs a multi-account strategy to host various environments, including development, staging, and production. AWS Organizations is used for centralized management of these accounts, while AWS IAM Identity Center is leveraged to manage permissions for users across the accounts.&lt;/p&gt;

&lt;p&gt;This documentation provides an insight into the architecture, technologies, and strategies used within the ABC platform. For more detailed instructions and configurations, please refer to specific documents related to each tier or service.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to automate using MFA in AWS CLI</title>
      <dc:creator>oscarrobert-star</dc:creator>
      <pubDate>Wed, 03 May 2023 10:05:19 +0000</pubDate>
      <link>https://dev.to/oscarrobertstar/how-automate-using-mfa-in-aws-cli-5753</link>
      <guid>https://dev.to/oscarrobertstar/how-automate-using-mfa-in-aws-cli-5753</guid>
      <description>&lt;h2&gt;
  
  
  Problem Statement
&lt;/h2&gt;

&lt;p&gt;I am a frequent AWS CLI user, and this has never been a challenge until my organisation decided to enforce AWS MFA for all users - a recommended practice. This significantly affected how I use the AWS CLI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;How to enable MFA:&lt;/strong&gt; &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable_virtual.html" rel="noopener noreferrer"&gt;AWS Documentation on Enabling a Virtual MFA Device&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;How to use MFA with the CLI:&lt;/strong&gt; &lt;a href="https://repost.aws/knowledge-center/authenticate-mfa-cli" rel="noopener noreferrer"&gt;AWS Knowledge Center Guide&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look at the hustle you have to go through when using the CLI. To add to that, imagine if you had 4 AWS environments. Will you be copying these temporary credentials into the &lt;code&gt;.aws/credentials&lt;/code&gt; file all the time, or updating the environment variables each time?&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;In the DevOps spirit, I had to find a way to automate this. My solution has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; A Python script that handles the authentication and updates &lt;code&gt;.aws/credentials&lt;/code&gt; with the new session keys and token.&lt;/li&gt;
&lt;li&gt; Creating shell aliases to run the Python script seamlessly.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Part 1: The Python Script
&lt;/h3&gt;

&lt;p&gt;The script uses &lt;code&gt;argparse&lt;/code&gt; to define required command-line arguments: your MFA device ARN, the MFA token from your virtual device, and the AWS CLI profile you wish to authenticate.&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;fileinput&lt;/span&gt;

&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authenticate and update AWS credentials with MFA tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--mfa_serial_number&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mfa_serial_number&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Enter your mfa device arn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--profile_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;profile_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;use default if you dont have any unique profiles&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--mfa_token_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;mfa_token_code&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;MFA code from your virtual device&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Parse the command-line arguments
&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Assign arguments to variables
&lt;/span&gt;&lt;span class="n"&gt;mfa_serial_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mfa_serial_number&lt;/span&gt;
&lt;span class="n"&gt;profile_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;profile_name&lt;/span&gt;
&lt;span class="n"&gt;mfa_token_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mfa_token_code&lt;/span&gt;

&lt;span class="c1"&gt;# Check that all inputs are present
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;mfa_serial_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mfa_token_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;profile_name&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
    &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Required: --mfa_token_code, --mfa_serial_number and --profile_name are required.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script then uses the &lt;code&gt;boto3&lt;/code&gt; STS client to authenticate and retrieve temporary session credentials. The session duration is configurable.&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="c1"&gt;##################### Authenticate MFA ##########################
&lt;/span&gt;&lt;span class="n"&gt;session&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="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;profile_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;profile_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# enter profile 
&lt;/span&gt;&lt;span class="n"&gt;sts_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&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;sts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&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;sts_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_session_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;DurationSeconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Value changes between 900 (15 mins) - 129600 (36 hours)
&lt;/span&gt;    &lt;span class="n"&gt;SerialNumber&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mfa_serial_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TokenCode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mfa_token_code&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;access_key&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;Credentials&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;AccessKeyId&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;secret_key&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;Credentials&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;SecretAccessKey&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;session_token&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;Credentials&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;SessionToken&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the script updates the &lt;code&gt;.aws/credentials&lt;/code&gt; file in-place. It searches for a specific profile block (e.g., &lt;code&gt;[mfa]&lt;/code&gt;) and replaces the subsequent three lines with the new credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisite:&lt;/strong&gt; You must pre-create the profile block in &lt;code&gt;~/.aws/credentials&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[mfa]
wertyio
asdfgh
zxcvbn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#################### Update .aws/credential file with the temporary mfa credentials #####################
&lt;/span&gt;
&lt;span class="c1"&gt;# Define the pattern to search for
&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\[mfa\]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the replacement content for the three lines
&lt;/span&gt;&lt;span class="n"&gt;replacement_lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;aws_access_key_id = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;access_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;aws_secret_access_key = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;secret_key&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;aws_session_token = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;session_token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Open the file in inplace mode using fileinput
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;fileinput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/.aws/credentials&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&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="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Iterate over the lines in the file
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# If the line matches the pattern, print it and then modify the next three lines
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Print the new replacement lines
&lt;/span&gt;            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;replacement_line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;replacement_lines&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;replacement_line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Skip the next three lines in the original file
&lt;/span&gt;            &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Otherwise, just print the line
&lt;/span&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Part 2: Creating Aliases
&lt;/h3&gt;

&lt;p&gt;Aliases are shortcuts in your shell to execute longer commands. This is a personal preference; feel free to modify them.&lt;/p&gt;

&lt;p&gt;First, create an alias to source your Python virtual environment (if you use one).&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="c"&gt;# Add to ~/.zshrc or ~/.bashrc&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;source_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'source /Users/devops/Desktop/python_lab/env/bin/activate'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create aliases for each of your AWS environments. The number of aliases depends on the number of environments you have (e.g., &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;staging&lt;/code&gt;, &lt;code&gt;prod&lt;/code&gt;).&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="c"&gt;# Add to ~/.zshrc or ~/.bashrc&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;mfaTest&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'source_env &amp;amp;&amp;amp; python /Users/devops/Desktop/python_lab/enableMFA/newCred.py --mfa_serial_number $TEST_DEVICE --profile_name test --mfa_token_code '&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;mfaStaging&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'source_env &amp;amp;&amp;amp; python /Users/devops/Desktop/python_lab/enableMFA/newCred.py --mfa_serial_number $STAGING_DEVICE --profile_name staging --mfa_token_code '&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;mfaProd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'source_env &amp;amp;&amp;amp; python /Users/devops/Desktop/python_lab/enableMFA/newCred.py --mfa_serial_number $PROD_DEVICE --profile_name prod --mfa_token_code '&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; The &lt;code&gt;mfa_serial_number&lt;/code&gt; argument is passed from an environment variable. You must define these variables in your shell configuration file:&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="c"&gt;# Add to ~/.zshrc or ~/.bashrc&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TEST_DEVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'arn:aws:iam::123456789012:mfa/my-device'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;STAGING_DEVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'arn:aws:iam::210987654321:mfa/my-device'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PROD_DEVICE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'arn:aws:iam::098765432109:mfa/my-device'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt; To authenticate, call the alias followed by the current MFA code from your authenticator app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mfaTest 123456
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running, you can verify your credentials by calling any AWS CLI command using the &lt;code&gt;--profile mfa&lt;/code&gt; flag.&lt;/p&gt;




&lt;h2&gt;
  
  
  Alternative Approach
&lt;/h2&gt;

&lt;p&gt;If you are an admin and have IAM permissions across your AWS accounts, you can create an IAM role with cross-account permissions. This allows you to assume a role directly for the account you need, which can often be a more scalable and secure solution than managing long-term credentials and MFA tokens for the CLI.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
