Header image

LINE and Mobile Commerce Platform in Japan

20/09/2023

1.28k

We created a mobile application for a multinational conglomerate using LINE, one of Japan’s most popular mobile applications. Nearly 70% of Japanese citizens use the application. This popularity promotes Japanese consumerism by integrating online shopping features within the app. Mobile commerce is obviously on trend throughout Asia.

Transitioning Department Stores to Mobile Commerce (M-Commerce)

We worked with a large conglomerate that works in a multitude of industries in Japan. One such industry is retail. Our client sells daily and household goods in its brick-and-mortar stores. For the longest time, many of its services were exclusive to the physical locations. Mobile commerce (M-Commerce) is a form of e-commerce growing rapidly in Japan. LINE apps, using LIFF (LINE Front End Framework), allow companies to sell their products directly to consumers through the most popular communication application in the country. This article discusses the importance of mobile commerce in Japan and how companies use LINE apps to connect with consumers.

In department stores, consumers can purchase various goods and sign up for membership. In the past, all purchases and membership services were conducted at the physical location. But the consumer landscape continues to shift. Our client noticed the growing popularity M-Commerce amongst the younger generation. They approached us with a proposal to use LINE and bring their business to their customers’ phones and tablets.

LINE in Japan

E-commerce and online shopping are nothing new, and shopping on a smartphone isn’t either. But one of the things the LINE app does well is seamlessly integrate mobile e-commerce into an app that most Japanese people use every day. LINE is the de facto messaging app in Japan.

LINE is similar to WhatsApp, WeChat, or Zalo, with a larger user base than Instagram in Japan. For a while, it fits that niche well. You can add friends and chat with them indefinitely, as long as you have mobile data. But LINE’s ecosystem has grown over the past decade. It behaves more like a complete social networking service (SNS) than the simple chat tool it once was. This means that people are spending more time in the app.

When most people use an application daily, it acts as a primary way to tap directly into their feed. Consumers can follow our client’s brand and receive updates on new products or campaigns. They can purchase items and track their accumulated points, then use them to receive gifts and other perks. They can do all of this without ever leaving the app they use to communicate with their friends and family. It’s one less click away. It’s one less website to visit and one less account to create.

Creating a LINE mini-app Using LIFF

So customers can use LINE to shop online, but what did SupremeTech help build? We used LINE Front-end Framework (LIFF) to create a LINE mini-app for our client to provide their services to customers. LIFF is a web application platform provided by LINE. LIFF apps can receive data from the LINE platform (such as the LINE user ID). They then use this data to provide features that use user data and send messages on behalf of the user.

One of the main features we implemented was the Richmenu. Rich menus are a staple of LINE and Japanese mobile e-commerce. According to LINE for Business, rich menus are defined as “a menu feature anchored at the bottom of the LINE chat screen. They attract users’ attention by filling a large portion of the screen.” By setting links along with creatives, you can direct users to various other official LINE account features, as well as external sites, reservation pages, and more.” We created this rich menu specifically for our client to promote their services and link directly to their website. From the rich menu, customers can create a points card and access special offers available only to those who follow the client on LINE.

>>> Read more related articles: LINE Mini App: Digital Transform Customer Service with Digital Point Cards

Leveling Up Our Technical Expertise

There was one major technical challenge that we faced. This was the first project that SupremeTech completed without using any kind of server. Because the project has so many promotions and various requests, we were asked to complete our first serverless project. In hindsight, it wasn’t a difficult task, but at the time we had to work and develop in a way we were not used to. In this way, this project was a stepping stone for increasing our company’s technical expertise and capabilities.

Technical Stack

Front End: TypeScript (LIFF framework)

Back End: TypeScript

Infrastructure: Serverless architecture with AWS (Lambda, API Gateway, SQS, SNS, DynamoDB, WAF, Cloudwatch Log, .CDK.)

Related Blog

aws-infra

How-to

Online-Merge-Offline Retail

+0

    Mini Apps – Ứng Dụng Công Nghệ Là Chìa Khoá Thành Công Với Doanh Nghiệp Của Bạn (Part 3)

    Giới thiệu Chào các bạn, như vậy sau 2 bài viết trong chuỗi Seri tìm hiểu về Line Mini App của mình, chắc hẳn mọi người cũng đã nắm được cơ bản về việc tạo channel cũng như khởi tạo LIFF app rồi. Ở bài viết này, chúng ta sẽ tìm hiểu cách để triển khai ứng dụng LIFF app theo đề bài ban đầu. Tạo một ứng dụng chuyên tích điểm dành cho khách hàng thường xuyên check-in tại cửa hàng, và khi khách hàng đạt ngưỡng một số điểm nhất định, chúng ta sẽ gửi thông báo tới khách hàng và tặng khách hàng mã Voucher giảm giá sản phẩm, với yêu cầu đơn giản này, chúng ta hãy cùng xem ứng dụng mini app có thực sự tiện lợi không nhé. Đọc kỹ yêu cầu, chúng ta có 2 yêu cầu chính trong ứng dụng này. Chức năng tích điểm khi check-in tại cửa hàng, mỗi khi khách hàng tới cửa hàng sẽ nhấn nút check-in và hệ thống sẽ lưu lại và tặng điểm cho mỗi lần khách hàng thực hiện thao tác này.Chức năng gửi Voucher cho khách hàng khi tích đủ số Point nhất định. Lựa chọn giải pháp Khi tiến hành với việc triển khai giải pháp bằng việc lựa chọn công nghệ thích hợp, việc đầu tiên chúng ta cần phải nghĩ tới ngay đó là hiệu quả và chi phí vận hành. Rõ ràng, có rất nhiều giải pháp để triển khai một hệ thống, tuy nhiên để cân bằng trạng thái P/P (Price-Performance Ratio - tỷ lệ cân bằng giữa giá và hiệu suất) là điều rất cần thiết. Ở bài này, chúng ta sẽ cùng tìm hiểu về một trong những giải pháp đáp ứng được P/P, đang được rất nhiều hệ thống nhỏ sử dụng hiệu quả, giải pháp liên quan tới Cloud và Serverless, cụ thể trong bài viết này, chúng ta sẽ cùng tìm hiểu và triển khai về AWS Cloud và Serverless (Lambda + API Gateway) Dưới đây là mô hình AWS infrastructure cơ bản để demo sản phẩm này. Giải thích thành phần: API Gateway: cổng kết nối trung gian dịch vụ giữa ứng dụng LIFF và các dịch vụ bên trong (Lambda), là nơi thiết kế các API truy xuất dữ liệu.CloudFront: là CDN dùng để kết nối tới các host chứa dữ liệu, dữ liệu bài viết này là source code của ứng dụng Web, chúng ta sử dụng Single Page Web App cho ứng dụng sắp triển khai.S3: hiện là nơi lưu trữ dữ liệu source code của web app (SPA).Lambda: là một dạng computing được viết theo từng function, thay cho máy chủ để tính toán, truy xuất dữ liệu từ DB và trả về kết quả, chúng ta không cần máy chủ trong ứng dụng này, mọi chi phí sẽ dựa theo lượng request sử dụng.DynamoDB: là cơ sở dữ liệu (Database Engine) lưu trữ thông tin của user, trong khuôn khổ bài viết này, chúng ta sẽ lưu trữ số Point của end-user.CloudWatch: là nơi lưu trữ log của Lambda và dùng để trigger sự kiện theo schedule, ở bài viết này chúng ta sẽ dùng CloudWatch trigger mỗi 5 phút/ lần để gửi mã Voucher thử nghiệm nếu user đã đủ point.Messaging API: Là API do LINE cung cấp, dùng để gửi message tới user đang sử dụng LINE app và đã đăng ký với channel ứng dụng của chúng ta đang triển khai.LIFF SDK: là SDK dùng để tích hợp với Web app mà ta sẽ triển khai. Như vậy, chúng ta đã đi sơ qua các thành phần và giải pháp sẽ triển khai ứng dụng, bước tiếp theo chúng ta cần đăng ký tài khoản AWS và cùng thử xem sơ qua cách tính chi phí vận hành của ứng dụng với mô hình này nhé. Tìm hiểu về AWS và đăng ký tài khoản Ở phần trên, chúng ta sẽ thực hiện giải pháp sử dụng AWS Cloud làm mô hình Serverless cho ứng dụng, để bắt đầu, bạn cần hiểu sơ về AWS Cloud. Amazon Web Services (AWS) là nền tảng đám mây toàn diện và được sử dụng rộng rãi nhất, cung cấp trên 200 dịch vụ đầy đủ tính năng từ các trung tâm dữ liệu trên toàn thế giới. Hàng triệu khách hàng—bao gồm các công ty khởi nghiệp tăng trưởng nhanh nhất, các tập đoàn lớn nhất cũng như các cơ quan hàng đầu của chính phủ—đều tin tưởng vào AWS để giảm chi phí, trở nên linh hoạt hơn và đổi mới nhanh hơn. Đăng ký tài khoản AWS của bạn ngay. Sau khi đã đăng ký được tài khoản, bạn tiến hành đăng nhập, để đảm bảo tuân thủ Security Best Practice, bạn không nên sử dụng Root user, nhưng trong phạm vi khuôn khổ bài viết, chúng ta sẽ sử dụng root user để triển khai. Đừng quên tìm hiểu thêm lý do vì sao không nên xài root user. Giao diện đăng nhập AWS sau khi đăng nhập thành công sẽ như thế này. Như vậy là xong, bạn đã hoàn tất việc tạo 1 tài khoản AWS, lưu ý, mọi dịch vụ trên AWS đều có thể mất phí, vì vậy bạn cần hiểu rõ về dịch vụ mình cần sử dụng, để không mất quá nhiều tiền cho sản phẩm thử nghiệm của mình nhé, trong khuôn khổ bài viết chúng ta không thể phân tích chi tiết về phí dịch vụ, nhưng hãy luôn lưu ý vấn đề này khi sử dụng AWS Cloud. Kết thúc Trong khuôn khổ bài viết này, chúng ta đã hình dung được mô hình cấu trúc (AWS infrastructure) AWS khi triển khai ứng dụng LIFF App cùng với Serverless. Ở bài tiếp theo, chúng ta sẽ xây dựng một ứng dụng và triển khai (deploy) ứng dụng này lên Cloud, các bạn cùng chờ bài viết tiếp theo nhé. Cùng đón đọc các phần trước của series này nhé! Author: Kiet Vo

    03/06/2022

    802

    How-to

    +1

    • Online-Merge-Offline Retail

    Mini Apps – Ứng Dụng Công Nghệ Là Chìa Khoá Thành Công Với Doanh Nghiệp Của Bạn (Part 3)

    03/06/2022

    802

    intro2

    How-to

    Online-Merge-Offline Retail

    +0

      Mini Apps – Ứng Dụng Công Nghệ Là Chìa Khoá Thành Công Với Doanh Nghiệp Của Bạn (Part 2)

      Giới thiệu Ở bài viết trước, chúng ta đã hiểu được Line Mini App là gì, cũng như những ví dụ minh họa cơ bản về những trường hợp nên sử dụng Mini App trên Line. Trong khuôn khổ bài viết này, chúng ta sẽ làm quen với việc tạo một ứng dụng Line Mini App và tích hợp nó vào trong Line. Trước khi bắt đầu tạo một ứng dụng Line Mini App sẽ cần phải xác định trước những yêu cầu của nền tảng mà bạn đang tính xây dựng, thông thường sẽ liên quan tới luật và chính sách của quốc gia sở tại, vậy nên bạn nên đọc kỹ phần chính sách và điều khoản để đáp ứng được các yêu cầu. Đối với Line, yêu cầu đó có thể bao gồm: thông tin khách hàng, thông tin doanh nghiệp, nội dung chia sẻ và vấn đề liên quan tới bản quyền, … và lưu ý quan trọng, trong quá trình phát triển ứng dụng bạn có thể hoạt động tự do. Tuy nhiên, để ứng dụng được Publish, bạn cần được review và chấp nhận từ công ty Line. Để tìm hiểu kỹ hơn về điều khoản và chính sách liên quan tới Line Mini App, bạn có thể xem bảng chi tiết tại đây. Lưu ý, với mỗi quốc gia sẽ có chính sách riêng biệt hãy xem kỹ nội dung theo quốc gia bạn đang hướng tới để áp dụng phù hợp với giải pháp định chọn. Sau khi đã xác định và hiểu rõ, bạn có thể bắt đầu tiến hành tạo một ứng dụng Line Mini App theo các bước trong mục tiếp theo. Tạo ứng dụng Line Mini App Để bắt đầu với một ứng dụng, giả sử chúng ta đang xây dựng ứng dụng Line Mini App là một ứng dụng chuyên tích điểm dành cho khách hàng thường xuyên check-in tại cửa hàng, và khi khách hàng đạt ngưỡng một số điểm nhất định, chúng ta sẽ gửi thông báo tới khách hàng và tặng khách hàng mã Voucher giảm giá sản phẩm, với yêu cầu đơn giản này, chúng ta hãy cùng xem ứng dụng mini app có thực sự tiện lợi không nhé. Dưới đây, là các bước cần chuẩn bị trước khi tạo ứng dụng Mini App. Chuẩn bị tài khoản Line Việc đầu tiên, bạn cần truy cập tới trang quản trị dành cho nhà phát triển ứng dụng (nhấn tại đây). Bạn có thể đăng nhập với tài khoản Line hoặc tài khoản doanh nghiệp trên Line, để tìm hiểu kỹ hơn về tài khoản doanh nghiệp, hãy tham khảo tại đây. Sau khi đã đăng nhập thành công, màn hình quản trị sẽ hiển thị như dưới, bạn cần tạo 1 Provider để thử nghiệm, nhấn vào nút Create Điền tên Provider, ở đây chúng ta đặt tên Test-Mini-App, sau đó nhấn Create Sau khi quá trình tạo Provider hoàn tất, bạn được chuyển tới màn hình mới, với 3 Tabs chính:Channels: đây là tất cả các kênh mà nền tảng Line hỗ trợ để bạn có thể xây dựng các dịch vụ, trong khuôn khổ bài viết này, chúng ta chỉ cần quan tâm tới 2 channel là Line Login Channel và Line Messaging API ChannelRoles: đây là nơi bạn có thể thêm thành viên, nhà phát triển và người kiểm thử (Tester) để có quyền kết nối tới các channel bạn đã tạo.Settings: là những cài đặt cơ bản quan tới Provider. Lựa chọn giữa LIFF hoặc Line Mini App Sau khi khởi tạo tài khoản và tạo Provider ở bước trên, ở bước này chúng ta có thể tiến hành khởi tạo Line Mini App channel để bắt đầu, tuy nhiên, để có thể tạo được 1 Line Mini App channel, bạn sẽ qua bước kiểm tra và xác nhận từ LINE. Việc này sẽ tốn thời gian, vậy nên trong khuôn khổ bài viết này, chúng ta sẽ cùng tìm hiểu tới LIFF (LINE Front-end Framework), là nền tảng tương tự như Line Mini App và không cần phải chờ đợi review từ LINE. Trước hết, chúng ta sẽ xem qua những điểm khác biệt giữa LIFF và Line Mini App Điểm chung: Cả 2 đều chạy trên nền tảng Web và chạy bởi trình duyệt LIFF, được nhúng vào trong ứng dụng Line.Cả 2 đều có thể tích hợp nhiều công nghệ web mới nhất để cung cấp nhanh dịch vụ. Điểm riêng: LIFF appLINE MINI AppMôi trường- Chạy trên ứng dụng LINE.- Chạy được trên hầu hết các trình duyệt phổ biến.- Chỉ chạy được duy nhất trên ứng dụng LINE (điện thoại)LINE review và chấp nhậnKhông cần, bạn có thể phát hành bất cứ lúc nào.- Phải được review và chấp nhận bởi LINE.- Sau khi thỏa mãn điều kiện review, ứng dụng Line Mini App sẽ được xuất hiện bằng chức năng tìm kiếm và tại tab Home của ứng dụng LINE.Service message chat roomKhông có sẵnBạn có thể sử dụng, chức năng có sẵn trên toàn bộ ứng dụng Line Mini Apps. Tham khảo: tại đây Trong khuôn khổ seri này, chúng ta sẽ lựa chọn LIFF app, là phương án nhanh nhất để bắt đầu, sau khi phát triển hoàn tất, chúng ta có thể tiến hành chuyển đổi sang Line Mini App channel. Tiếp theo, hãy tạo 2 channels như đã đề cập bên trên, bao gồm: Line Login channel: hãy để mọi thông tin là mặc định, lưu ý vài điểm sau.Region: chọn JapanCompany or owner's country or region: JapanChannel name: DEV-Login channelChannel description: Line Mini AppApp Type: chọn WebMessaging API channel: hãy để mọi thông tin là mặc định, lưu ý vài điểm sau.Company or owner's country or region: JapanChannel name: DEV-Messaging APIChannel description: Line Mini AppCategory: Local Business and E-commerceSubcategory: Shopping & retail Như vậy, là xong phần chuẩn bị cơ bản liên quan tới quản trị trên nền tảng Line, bạn sẽ cần chuẩn bị thêm về tài liệu để khởi tạo một ứng dụng mini app trên Line, hãy cùng tìm hiểu về LIFF (LINE Front-end Framework), một nền tảng chạy trên web app được cung cấp bởi LINE. Khởi tạo LIFF apps. Ở bước bên trên, chúng ta đã khởi tạo thành công 1 Provider có chứa sẵn 2 Channels là Login channel và Messaging API channel, ở bước này chúng ta sẽ tiến hành khởi tạo 1 LIFF app và cấu hình LIFF app có thể tương tác với 2 channel này nhé. Line Mini App là ứng dụng chạy trên nền tảng web và nó chạy trên LINE.LIFF app (LINE Front-end Framework) là một framework dùng để xây dựng 1 ứng dụng web, được cung cấp bởi LINE, sử dụng LIFF, bạn sẽ giảm rất nhiều thời gian để xây dựng, xử lý, vì mọi thứ đã được LINE định nghĩa và cung cấp bên trong LIFF. Phiên bản mới nhất hiện tại của LIFF là version 2 (LINE Front-end Framework v2)Bạn có thể sử dụng tính năng thử nghiệm (playground) với LIFF playground để dễ hình dung hơn các tính năng của LIFF. Bước 01: Truy cập vào Login channel và tạo 1 LIFF app. Bước 02: Nhập thông tin, ví dụ như bên dưới Tên trườngMô tảGiá trịLIFF app nameTên của ứng dụng.demo-appSizeLà kích thước của LIFF brower khi bật lênFullEndpoint URLLà tên miền của ứng dụng, chúng ta sẽ cập nhật lại sauhttps://localhost.com:3000Scopeskhai báo quyền cần cấp để xin dữ liệu khi chứng thực với LINEprofile, openidBot link featureoffScan QRonModule modeoff Bước 03: Sau khi đã điền đủ thông tin, nhấn vào nút Add, và quá trình tạo 1 LIFF app đã hoàn tất. Kết thúc Như vậy, với những bước trên, bạn đã hoàn thành được việc đăng ký tài khoản LINE, khởi tạo 1 ứng dụng LIFF trên LINE console. Bài tiếp theo, chúng ta sẽ sang một seri mới liên quan tới kỹ thuật, đó là làm thế nào để triển khai ứng dụng LIFF và chạy nó trên nền tảng LINE. Author: Kiet Vo

      20/05/2022

      1.38k

      How-to

      +1

      • Online-Merge-Offline Retail

      Mini Apps – Ứng Dụng Công Nghệ Là Chìa Khoá Thành Công Với Doanh Nghiệp Của Bạn (Part 2)

      20/05/2022

      1.38k

      Knowledge

      +0

        Best Practices for Building Reliable AWS Lambda Functions

        Welcome back to the "Mastering AWS Lambda with Bao" series! The previous episode explored how AWS Lambda connects to the world through AWS Lambda triggers and events. Using S3 and DynamoDB Streams triggers, we demonstrated how Lambda automates workflows by processing events from multiple sources. This example provided a foundation for understanding Lambda’s event-driven architecture. However, building reliable Lambda functions requires more than understanding how triggers work. To create AWS lambda functions that can handle real-world production workloads, you need to focus on optimizing performance, implementing robust error handling, and enforcing strong security practices. These steps optimize your Lambda functions to be scalable, efficient, and secure. In this episode, SupremeTech will explore the best practices for building reliable AWS Lambda functions, covering two essential areas: Optimizing Performance: Reducing latency, managing resources, and improving runtime efficiency.Error Handling and Logging: Capturing meaningful errors, logging effectively with CloudWatch, and setting up retries. Adopting these best practices, you’ll be well-equipped to optimize Lambda functions that thrive in production environments. Let’s dive in! Optimizing Performance Optimize the Lambda function's performance to run efficiently with minimal latency and cost. Let's focus first on Cold Starts, a critical area of concern for most developers. Understanding Cold Starts What Are Cold Starts? A Cold Start occurs when AWS Lambda initializes a new execution environment to handle an incoming request. This happens under the following circumstances: When the Lambda function is invoked for the first time.After a period of inactivity (execution environments are garbage collected after a few minutes of no activity – meaning it will be shut down automatically).When scaling up to handle additional concurrent requests. Cold starts introduce latency because AWS needs to set up a new execution environment from scratch. Steps Involved in a Cold Start: Resource Allocation:AWS provisions a secure and isolated container for the Lambda function.Resources like memory and CPU are allocated based on the function's configuration.Execution Environment Initialization:AWS sets up the sandbox environment, including:The /tmp directory is for temporary storage.Networking configurations, such as Elastic Network Interfaces (ENI), for VPC-based Lambdas.Runtime Initialization:The specified runtime (e.g., Node.js, Python, Java) is initialized.For Node.js, this involves loading the JavaScript engine (V8) and runtime APIs.Dependency Initialization:AWS loads the deployment package (your Lambda code and dependencies).Any initialization code in your function (e.g., database connections, library imports) is executed.Handler Invocation:Once the environment is fully set up, AWS invokes your Lambda function's handler with the input event. Cold Start Latency Cold start latency varies depending on the runtime, deployment package size, and whether the function runs inside a VPC: Node.js and Python: ~200ms–500ms for non-VPC functions.Java or .NET: ~500ms–2s due to heavier runtime initialization.VPC-Based Functions: Add ~500ms–1s due to ENI initialization. Warm Starts In contrast to cold starts, Warm Starts reuse an already-initialized execution environment. AWS keeps environments "warm" for a short time after a function is invoked, allowing subsequent requests to bypass initialization steps. Key Differences: Cold Start: New container setup → High latency.Warm Start: Reused container → Minimal latency (~<100ms). Reducing Cold Starts Cold starts can significantly impact the performance of latency-sensitive applications. Below are some actionable strategies to reduce cold starts, each with good and bad practice examples for clarity. 1. Use Smaller Deployment Packages to optimize lambda function Good Practice: Minimize the size of your deployment package by including only the required dependencies and removing unnecessary files.Use bundlers like Webpack, ESBuild, or Parcel to optimize your package size.Example: const DynamoDB = require('aws-sdk/clients/dynamodb'); // Only loads DynamoDB, not the entire SDK Bad Practice: Bundling the entire AWS SDK or other large libraries without considering modular imports.Example: const AWS = require('aws-sdk'); // Loads the entire SDK, increasing package size Why It Matters: Smaller deployment packages load faster during the initialization phase, reducing cold start latency. 2. Move Heavy Initialization Outside the Handler Good Practice: Place resource-heavy operations, such as database or SDK client initialization, outside the handler function so they are executed only once per container lifecycle – a cold start.Example: const DynamoDB = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => {     const data = await DynamoDB.get({ Key: { id: '123' } }).promise();     return data; }; Bad Practice: Reinitializing resources inside the handler for every invocation.Example: exports.handler = async (event) => {     const DynamoDB = new AWS.DynamoDB.DocumentClient(); // Initialized on every call     const data = await DynamoDB.get({ Key: { id: '123' } }).promise();     return data; }; Why It Matters: Reinitializing resources for every invocation increases latency and consumes unnecessary computing power. 3. Enable Provisioned Concurrency1 Good Practice: Use Provisioned Concurrency to pre-initialize a set number of environments, ensuring they are always ready to handle requests.Example:AWS CLI: aws lambda put-provisioned-concurrency-config \ --function-name myFunction \ --provisioned-concurrent-executions 5 AWS Management Console: Why It Matters: Provisioned concurrency ensures a constant pool of pre-initialized environments, eliminating cold starts entirely for latency-sensitive applications. 4. Reduce Dependencies to optimize the lambda function Good Practice: Evaluate your libraries and replace heavy frameworks with lightweight alternatives or native APIs.Example: console.log(new Date().toISOString()); // Native JavaScript API Bad Practice: Using heavy libraries for simple tasks without considering alternatives.Example: const moment = require('moment'); console.log(moment().format()); Why It Matters: Large dependencies increase the deployment package size, leading to slower initialization during cold starts. 5. Avoid Unnecessary VPC Configurations Good Practice: Place Lambda functions outside a VPC unless necessary. If a VPC is required (e.g., to access private resources like RDS), optimize networking using VPC endpoints.Example:Use DynamoDB and S3 directly without placing the Lambda inside a VPC. Bad Practice: Deploying Lambda functions inside a VPC unnecessarily, such as accessing services like DynamoDB or S3, which do not require VPC access.Why It’s Bad: Placing Lambda in a VPC introduces additional latency due to ENI setup during cold starts. Why It Matters: Functions outside a VPC initialize faster because they skip ENI setup. 6. Choose Lightweight Runtimes to optimize lambda function Good Practice: Use lightweight runtimes like Node.js or Python for faster initialization than heavier runtimes like Java or .NET.Why It’s Good: Lightweight runtimes require fewer initialization resources, leading to lower cold start latency. Why It Matters: Heavier runtimes have higher cold start latency due to the complexity of their initialization process. Summary of Best Practices for Cold Starts AspectGood PracticeBad PracticeDeployment PackageUse small packages with only the required dependencies.Bundle unused libraries, increasing the package size.InitializationPerform heavy initialization (e.g., database connections) outside the handler.Initialize resources inside the handler for every request.Provisioned ConcurrencyEnable provisioned concurrency for latency-sensitive applications.Ignore provisioned concurrency for high-traffic functions.DependenciesUse lightweight libraries or native APIs for simple tasks.Use heavy libraries like moment.js without evaluating lightweight alternatives.VPC ConfigurationAvoid unnecessary VPC configurations; use VPC endpoints when required.Place all Lambda functions inside a VPC, even when accessing public AWS services.Runtime SelectionChoose lightweight runtimes like Node.js or Python for faster initialization.Use heavy runtimes like Java or .NET for simple, lightweight workloads. Error Handling and Logging Error handling and logging are critical for optimizing your Lambda functions are reliable and easy to debug. Effective error handling prevents cascading failures in your architecture, while good logging practices help you monitor and troubleshoot issues efficiently. Structured Error Responses Errors in Lambda functions can occur due to various reasons: invalid input, AWS service failures, or unhandled exceptions in the code. Properly structured error handling ensures that these issues are captured, logged, and surfaced effectively to users or downstream services. 1. Define Consistent Error Structures Good Practice: Use a standard error format so all errors are predictable and machine-readable.Example: {   "errorType": "ValidationError",   "message": "Invalid input: 'email' is missing",   "requestId": "12345-abcd" } Bad Practice: Avoid returning vague or unstructured errors that make debugging difficult. { "message": "Something went wrong", "error": true } Why It Matters: Structured errors make debugging easier by providing consistent, machine-readable information. They also improve communication with clients or downstream systems by conveying what went wrong and how it should be handled. 2. Use Custom Error Classes Good Practice: In Node.js, define custom error classes for clarity: class ValidationError extends Error {   constructor(message) {     super(message);     this.name = "ValidationError";     this.statusCode = 400; // Custom property   } } // Throwing a custom error if (!event.body.email) {   throw new ValidationError("Invalid input: 'email' is missing"); } Bad Practice: Use generic errors for everything, making identifying or categorizing issues hard.Example: throw new Error("Error occurred"); Why It Matters: Custom error classes make error handling more precise and help segregate application errors (e.g., validation issues) from system errors (e.g., database failures). 3. Include Contextual Information in Logs Good Practice: Add relevant information like requestId, timestamp, and input data (excluding sensitive information) when logging errors.Example: console.error({     errorType: "ValidationError",     message: "The 'email' field is missing.",     requestId: context.awsRequestId,     input: event.body,     timestamp: new Date().toISOString(), }); Bad Practice: Log errors without any context, making debugging difficult.Example: console.error("Error occurred"); Why It Matters: Contextual information in logs makes it easier to identify what triggered the error and where it happened, improving the debugging experience. Retry Logic Across AWS SDK and Other Services Retrying failed operations is critical when interacting with external services, as temporary failures (e.g., throttling, timeouts, or transient network issues) can disrupt workflows. Whether you’re using AWS SDK, third-party APIs, or internal services, applying retry logic effectively can ensure system reliability while avoiding unnecessary overhead. 1. Use Exponential Backoff and Jitter Good Practice: Apply exponential backoff with jitter to stagger retry attempts. This avoids overwhelming the target service, especially under high load or rate-limiting scenarios.Example (General Implementation): async function retryWithBackoff(fn, retries = 3, delay = 100) {     for (let attempt = 1; attempt <= retries; attempt++) {         try {             return await fn();         } catch (error) {             if (attempt === retries) throw error; // Rethrow after final attempt             const backoff = delay * 2 ** (attempt - 1) + Math.random() * delay; // Add jitter             console.log(`Retrying in ${backoff.toFixed()}ms...`);             await new Promise((res) => setTimeout(res, backoff));         }     } } // Usage Example const result = await retryWithBackoff(() => callThirdPartyAPI()); Bad Practice: Retrying without delays or jitter can lead to cascading failures and amplify the problem. for (let i = 0; i < retries; i++) {     try {         return await callThirdPartyAPI();     } catch (error) {         console.log("Retrying immediately...");     } } Why It Matters: Exponential backoff reduces pressure on the failing service, while jitter randomizes retry times, preventing synchronized retry storms from multiple clients. 2. Leverage Built-In Retry Mechanisms Good Practice: Use the built-in retry logic of libraries, SDKs, or APIs whenever available. These are typically optimized for the specific service.Example (AWS SDK): const DynamoDB = new AWS.DynamoDB.DocumentClient({     maxRetries: 3, // Number of retries     retryDelayOptions: { base: 200 }, // Base delay in ms }); Example (Axios for Third-Party APIs):Use libraries like axios-retry to integrate retry logic for HTTP requests. const axios = require('axios'); const axiosRetry = require('axios-retry'); axiosRetry(axios, {     retries: 3, // Retry 3 times     retryDelay: (retryCount) => retryCount * 200, // Exponential backoff     retryCondition: (error) => error.response.status >= 500, // Retry only for server errors }); const response = await axios.get("https://example.com/api"); Bad Practice: Writing your own retry logic unnecessarily when built-in mechanisms exist, risking suboptimal implementation. Why It Matters: Built-in retry mechanisms are often optimized for the specific service or library, reducing the likelihood of bugs and configuration errors. 3. Configure Service-Specific Retry Limits Good Practice: Set retry limits based on the service's characteristics and criticality.Example (AWS S3 Upload): const s3 = new AWS.S3({ maxRetries: 5, // Allow more retries for critical operations retryDelayOptions: { base: 300 }, // Slightly longer base delay }); Example (Database Queries): async function queryDatabaseWithRetry(queryFn) {     await retryWithBackoff(queryFn, 5, 100); // Retry with custom backoff logic } Bad Practice: Allowing unlimited retries can cause resource exhaustion and increase costs. while (true) {     try {         return await callService();     } catch (error) {         console.log("Retrying...");     } } Why It Matters: Excessive retries can lead to runaway costs or cascading failures across the system. Always define a sensible retry limit. 4. Handle Transient vs. Persistent Failures Good Practice: Retry only transient failures (e.g., timeouts, throttling, 5xx errors) and handle persistent failures (e.g., invalid input, 4xx errors) immediately.Example: const isTransientError = (error) =>     error.code === "ThrottlingException" || error.code === "TimeoutError"; async function callServiceWithRetry() {     await retryWithBackoff(() => {         if (!isTransientError(error)) throw error; // Do not retry persistent errors         return callService();     }); } Bad Practice: Retrying all errors indiscriminately, including persistent failures like ValidationException or 404 Not Found. Why It Matters: Persistent failures are unlikely to succeed with retries and can waste resources unnecessarily. 5. Log Retry Attempts Good Practice: Log each retry attempt with relevant context, such as the retry count and delay. async function retryWithBackoff(fn, retries = 3, delay = 100) {     for (let attempt = 1; attempt <= retries; attempt++) {         try {             return await fn();         } catch (error) {             if (attempt === retries) throw error;             console.log(`Attempt ${attempt} failed. Retrying in ${delay}ms...`);             await new Promise((res) => setTimeout(res, delay));         }     } } Bad Practice: Failing to log retries makes debugging or understanding the retry behavior difficult. Why It Matters: Logs provide valuable insights into system behavior and help diagnose retry-related issues. Summary of Best Practices for Retry logic AspectGood PracticeBad PracticeRetry LogicUse exponential backoff with jitter to stagger retries.Retry immediately without delays, causing retry storms.Built-In MechanismsLeverage AWS SDK retry options or third-party libraries like axios-retry.Write custom retry logic unnecessarily when optimized built-in solutions are available.Retry LimitsDefine a sensible retry limit (e.g., 3–5 retries).Allow unlimited retries, risking resource exhaustion or runaway costs.Transient vs PersistentRetry only transient errors (e.g., timeouts, throttling) and fail fast for persistent errors.Retry all errors indiscriminately, including persistent failures like validation or 404 errors.LoggingLog retry attempts with context (e.g., attempt number, delay,  error) to aid debugging.Fail to log retries, making it hard to trace retry behavior or diagnose problems. Logging Best Practices Logs are essential for debugging and monitoring Lambda functions. However, unstructured or excessive logging can make it harder to find helpful information. 1. Mask or Exclude Sensitive Data Good Practice: Avoid logging sensitive information like:User credentialsAPI keys, tokens, or secretsPersonally Identifiable Information (PII)Use tools like AWS Secrets Manager for sensitive data management.Example: Mask sensitive fields before logging: const sanitizedInput = {     ...event,     password: "***", }; console.log(JSON.stringify({     level: "info",     message: "User login attempt logged.",     input: sanitizedInput, })); Bad Practice: Logging sensitive data directly can cause security breaches or compliance violations (e.g., GDPR, HIPAA).Example: console.log(`User logged in with password: ${event.password}`); Why It Matters: Logging sensitive data can expose systems to attackers, breach compliance rules, and compromise user trust. 2.  Set Log Retention Policies Good Practice: Set a retention policy for CloudWatch log groups to prevent excessive log storage costs.AWS allows you to configure retention settings (e.g., 7, 14, or 30 days). Bad Practice: Using the default “Never Expire” retention policy unnecessarily stores logs indefinitely. Why It Matters: Unmanaged logs increase costs and make it harder to find relevant data. Retaining logs only as long as needed reduces costs and keeps logs manageable. 3. Avoid Excessive Logging Good Practice: Log only what is necessary to monitor, troubleshoot, and analyze system behavior.Use info, debug, and error levels to prioritize logs appropriately. console.info("Function started processing..."); console.error("Failed to fetch data from DynamoDB: ", error.message); Bad Practice: Logging every detail (e.g., input payloads, execution steps) unnecessarily increases log volume.Example: console.log(`Received event: ${JSON.stringify(event)}`); // Avoid logging full payloads unnecessarily Why It Matters: Excessive logging clutters log storage, increases costs, and makes it harder to isolate relevant logs. 4. Use Log Levels (Info, Debug, Error) Good Practice: Use different log levels to differentiate between critical and non-critical information.info: For general execution logs (e.g., function start, successful completion).debug: For detailed logs during development or troubleshooting.error: For failure scenarios requiring immediate attention. Bad Practice: Using a single log level (e.g., console.log() everywhere) without prioritization. Why It Matters: Log levels make it easier to filter logs based on severity and focus on critical issues in production. Conclusion In this episode of "Mastering AWS Lambda with Bao", we explored critical best practices for building reliable AWS Lambda functions, focusing on optimizing performance, error handling, and logging. Optimizing Performance: By reducing cold starts, using smaller deployment packages, lightweight runtimes, and optimizing VPC configurations, you can significantly lower latency and optimize Lambda functions. Strategies like moving initialization outside the handler and leveraging Provisioned Concurrency ensure smoother execution for latency-sensitive applications.Error Handling: Implementing structured error responses and custom error classes makes troubleshooting easier and helps differentiate between transient and persistent issues. Handling errors consistently improves system resilience.Retry Logic: Applying exponential backoff with jitter, using built-in retry mechanisms, and setting sensible retry limits optimizes that Lambda functions gracefully handle failures without overwhelming dependent services.Logging: Effective logging with structured formats, contextual information, log levels, and appropriate retention policies enables better visibility, debugging, and cost control. Avoiding sensitive data in logs ensures security and compliance. Following these best practices, you can optimize lambda function performance, reduce operational costs, and build scalable, reliable, and secure serverless applications with AWS Lambda. In the next episode, we’ll dive deeper into "Handling Failures with Dead Letter Queues (DLQs)", exploring how DLQs act as a safety net for capturing failed events and ensuring no data loss occurs in your workflows. Stay tuned! Note: 1. Provisioned Concurrency is not a universal solution. While it eliminates cold starts, it also incurs additional costs since pre-initialized environments are billed regardless of usage. When to Use:Latency-sensitive workloads like APIs or real-time applications where even a slight delay is unacceptable.When Not to Use:Functions with unpredictable or low invocation rates (e.g., batch jobs, infrequent triggers). For such scenarios, on-demand concurrency may be more cost-effective.

        13/01/2025

        149

        Bao Dang D. Q.

        Knowledge

        +0

          Best Practices for Building Reliable AWS Lambda Functions

          13/01/2025

          149

          Bao Dang D. Q.

          Knowledge

          +0

            Triggers and Events: How AWS Lambda Connects with the World

            Welcome back to the “Mastering AWS Lambda with Bao” series! In the previous episode, SupremeTech explored how to create an AWS Lambda function triggered by AWS EventBridge to fetch data from DynamoDB, process it, and send it to an SQS queue. That example gave you the foundational skills for building serverless workflows with Lambda. In this episode, we’ll dive deeper into AWS lambda triggers and events, the backbone of AWS Lambda’s event-driven architecture. Triggers enable Lambda to respond to specific actions or events from various AWS services, allowing you to build fully automated, scalable workflows. This episode will help you: Understand how triggers and events work.Explore a comprehensive list of popular AWS Lambda triggers.Implement a two-trigger example to see Lambda in action Our example is simplified for learning purposes and not optimized for production. Let’s get started! Prerequisites Before we begin, ensure you have the following prerequisites in place: AWS Account: Ensure you have access to create and manage AWS resources.Basic Knowledge of Node.js: Familiarity with JavaScript and Node.js will help you understand the Lambda function code. Once you have these prerequisites ready, proceed with the workflow setup. Understanding AWS Lambda Triggers and Events What are the Triggers in AWS Lambda? AWS lambda triggers are configurations that enable the Lambda function to execute in response to specific events. These events are generated by AWS services (e.g., S3, DynamoDB, API Gateway, etc) or external applications integrated through services like Amazon EventBridge. For example: Uploading a file to an S3 bucket can trigger a Lambda function to process the file.Changes in a DynamoDB table can trigger Lambda to perform additional computations or send notifications. How do Events work in AWS Lambda? When a trigger is activated, it generates an event–a structured JSON document containing details about what occurred Lambda receives this event as input to execute its function. Example event from an S3 trigger: { "Records": [ { "eventSource": "aws:s3", "eventName": "ObjectCreated:Put", "s3": { "bucket": { "name": "demo-upload-bucket" }, "object": { "key": "example-file.txt" } } } ] } Popular Triggers in AWS Lambda Here’s a list of some of the most commonly used triggers: Amazon S3:Use case: Process file uploads.Example: Resize images, extract metadata, or move files between buckets.Amazon DynamoDB Streams:Use case: React to data changes in a DynamoDB table.Example: Propagate updates or analyze new entries.Amazon API Gateway:Use case: Build REST or WebSocket APIs.Example: Process user input or return dynamic data.Amazon EventBridge:Use case: React to application or AWS service events.Example: Trigger Lambda for scheduled jobs or custom events. Amazon SQS:Use case: Process messages asynchronously.Example: Decouple microservices with a message queue.Amazon Kinesis:Use case: Process real-time streaming data.Example: Analyze logs or clickstream data.AWS IoT Core:Use case: Process messages from IoT devices.Example: Analyze sensor readings or control devices. By leveraging triggers and events, AWS Lambda enables you to automate complex workflows seamlessly. Setting Up IAM Roles (Optional) Before setting up Lambda triggers, we need to configure an IAM role with the necessary permissions. Step 1: Create an IAM Role Go to the IAM Console and click Create role.Select AWS Service → Lambda and click Next.Attach the following managed policies: AmazonS3ReadOnlyAccess: For reading files from S3.AmazonDynamoDBFullAccess: For writing metadata to DynamoDB and accessing DynamoDB Streams.AmazonSNSFullAccess: For publishing notifications to SNS.CloudWatchLogsFullAccess: For logging Lambda function activity.Click Next and enter a name (e.g., LambdaTriggerRole).Click Create role. Setting Up the Workflow For this episode, we’ll create a simplified two-trigger workflow: S3 Trigger: Processes uploaded files and stores metadata in DynamoDB.DynamoDB Streams Triggers: Sends a notification via SNS when new metadata is added. Step 1: Create an S3 Bucket Open the S3 Console in AWS.Click Create bucket and configure:Bucket name: Enter a unique name (e.g., upload-csv-lambda-st)Region: Choose your preferred region. (I will go with ap-southeast-1)Click Create bucket. Step 2: Create a DynamoDB Table Navigate to the DynamoDB Console.Click Create table and configure:Table name: DemoFileMetadata.Partition key: FileName (String).Sort key: UploadTimestamp (String). Click Create table.Enable DynamoDB Streams with the option New and old images. Step 3: Create an SNS Topic Navigate to the SNS Console.Click Create topic and configure: Topic type: Standard.Name: DemoFileProcessingNotifications. Click Create topic. Create a subscription. Confirm (in my case will be sent to my email). Step 4: Create a Lambda Function Navigate to the Lambda Console and click Create function.Choose Author from scratch and configure:Function name: DemoFileProcessing.Runtime: Select Node.js 20.x (Or your preferred version).Execution role: Select the LambdaTriggerRole you created earlier. Click Create function. Step 5: Configure Triggers Add S3 Trigger:Scroll to the Function overview section and click Add trigger. Select S3 and configure:Bucket: Select upload-csv-lambda-st.Event type: Choose All object create events.Suffix: Specify .csv to limit the trigger to CSV files. Click Add. Add DynamoDB Streams Trigger:Scroll to the Function overview section and click Add trigger. Select DynamoDB and configure:Table: Select DemoFileMetadata. Click Add. Writing the Lambda Function Below is the detailed breakdown of the Node.js Lambda function that handles events from S3 and DynamoDB Streams triggers (Source code). const AWS = require("aws-sdk"); const S3 = new AWS.S3(); const DynamoDB = new AWS.DynamoDB.DocumentClient(); const SNS = new AWS.SNS(); const SNS_TOPIC_ARN = "arn:aws:sns:region:account-id:DemoFileProcessingNotifications"; exports.handler = async (event) => { console.log("Event Received:", JSON.stringify(event, null, 2)); try { if (event.Records[0].eventSource === "aws:s3") { // Process S3 Trigger for (const record of event.Records) { const bucketName = record.s3.bucket.name; const objectKey = decodeURIComponent(record.s3.object.key.replace(/\+/g, " ")); console.log(`File uploaded: ${bucketName}/${objectKey}`); // Save metadata to DynamoDB const timestamp = new Date().toISOString(); await DynamoDB.put({ TableName: "DemoFileMetadata", Item: { FileName: objectKey, UploadTimestamp: timestamp, Status: "Processed", }, }).promise(); console.log(`Metadata saved for file: ${objectKey}`); } } else if (event.Records[0].eventSource === "aws:dynamodb") { // Process DynamoDB Streams Trigger for (const record of event.Records) { if (record.eventName === "INSERT") { const newItem = record.dynamodb.NewImage; // Construct notification message const message = `File ${newItem.FileName.S} uploaded at ${newItem.UploadTimestamp.S} has been processed.`; console.log("Sending notification:", message); // Send notification via SNS await SNS.publish({ TopicArn: SNS_TOPIC_ARN, Message: message, }).promise(); console.log("Notification sent successfully."); } } } return { statusCode: 200, body: "Event processed successfully!", }; } catch (error) { console.error("Error processing event:", error); throw error; } }; Detailed Explanation Importing Required AWS SDK Modules const AWS = require("aws-sdk"); const S3 = new AWS.S3(); const DynamoDB = new AWS.DynamoDB.DocumentClient(); const SNS = new AWS.SNS(); AWS SDK: Provides tools to interact with AWS services.S3 Module: Used to interact with the S3 bucket and retrieve file details.DynamoDB Module: Used to store metadata in the DynamoDB table.SNS Module: Used to publish messages to the SNS topic. Defining the SNS Topic ARN const SNS_TOPIC_ARN = "arn:aws:sns:region:account-id:DemoFileProcessingNotifications"; This is the ARN of the SNS topic where notification will be sent. Replace it with the ARN of your actual topic. Handling the Lambda Event exports.handler = async (event) => { console.log("Event Received:", JSON.stringify(event, null, 2)); The event parameter contains information about the trigger that activated the Lambda function.The event can be from S3 or DynamoDB Streams.The event is logged for debugging purposes. Processing the S3 Trigger if (event.Records[0].eventSource === "aws:s3") { for (const record of event.Records) { const bucketName = record.s3.bucket.name; const objectKey = decodeURIComponent(record.s3.object.key.replace(/\+/g, " ")); console.log(`File uploaded: ${bucketName}/${objectKey}`); Condition: Checks if the event source is S3.Loop: Iterates over all records in the S3 event.Bucket Name and Object Key: Extracts the bucket name and object key from the event.decodeURIComponent() is used to handle special characters in the object key. Saving Metadata to DynamoDB const timestamp = new Date().toISOString(); await DynamoDB.put({ TableName: "DemoFileMetadata", Item: { FileName: objectKey, UploadTimestamp: timestamp, Status: "Processed", }, }).promise(); console.log(`Metadata saved for file: ${objectKey}`); Timestamp: Captures the current time as the upload timestamp.DynamoDB Put Operation:Writes the file metadata to the DemoFileMetadata table.Includes the FileName, UploadTimestamp, and Status.Promise: The put method returns a promise, which is awaited to ensure the operation is completed. Processing the DynamoDB Streams Trigger } else if (event.Records[0].eventSource === "aws:dynamodb") { for (const record of event.Records) { if (record.eventName === "INSERT") { const newItem = record.dynamodb.NewImage; Condition: Checks if the event source is DynamoDB Streams.Loop: Iterates over all records in the DynamoDB Streams event.INSERT Event: Filters only for INSERT operations in the DynamoDB table. Constructing and Sending the SNS Notification const message = `File ${newItem.FileName.S} uploaded at ${newItem.UploadTimestamp.S} has been processed.`; console.log("Sending notification:", message); await SNS.publish({ TopicArn: SNS_TOPIC_ARN, Message: message, }).promise(); console.log("Notification sent successfully."); Constructing the Message:Uses the file name and upload timestamp from the DynamoDB Streams event.SNS Publish Operation:Send the constructed message to the SNS topic.Promise: The publish method returns a promise, which is awaited. to ensure the message is sent. Error Handling } catch (error) { console.error("Error processing event:", error); throw error; } Any errors during event processing are caught and logged.The error is re-thrown to ensure it’s recorded in CloudWatch Logs. Lambda Function Response return {     statusCode: 200,     body: "Event processed successfully!", }; After processing all events, the function returns a successful response. Test The Lambda Function Upload the code into AWS Lambda. Navigate to the S3 Console and choose the bucket you linked to the Lambda Function. Upload a random.csv file to the bucket. Check the result:DynamoDB Table Entry SNS Notifications CloudWatch Logs So, we successfully created a Lambda function that triggered based on 2 triggers. It's pretty simple. Just remember to delete any services after use to avoid incurring unnecessary costs! Conclusion In this episode, we explored AWS Lambda's foundational concepts of triggers and events. Triggers allow Lambda functions to respond to specific actions or events, such as file uploads to S3 or changes in a DynamoDB table. In contrast, events are structured data passed to the Lambda function containing details about what triggered it. We also implemented a practical example to demonstrate how a single Lambda function can handle multiple triggers: An S3 trigger processed uploaded files by extracting metadata and saving it to DynamoDB.A DynamoDB Streams trigger sent notifications via SNS when new metadata was added to the table. This example illustrated the flexibility of Lambda’s event-driven architecture and how it integrates seamlessly with AWS services to automate workflows. In the next episode, we’ll discuss Best practices for Optimizing AWS Lambda Functions, optimizing performance, handling errors effectively, and securing your Lambda functions. Stay tuned to continue enhancing your serverless expertise!

            10/01/2025

            367

            Bao Dang D. Q.

            Knowledge

            +0

              Triggers and Events: How AWS Lambda Connects with the World

              10/01/2025

              367

              Bao Dang D. Q.

              Customize software background

              Want to customize a software for your business?

              Meet with us! Schedule a meeting with us!