<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Fabric</title>
    <description>The latest articles on Forem by Fabric (@fabric_commerce).</description>
    <link>https://forem.com/fabric_commerce</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%2Forganization%2Fprofile_image%2F3037%2Fecf7aa0f-f822-460f-bc0e-6e4bc376c8b7.png</url>
      <title>Forem: Fabric</title>
      <link>https://forem.com/fabric_commerce</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fabric_commerce"/>
    <language>en</language>
    <item>
      <title>5 Challenges for Magento E-Commerce Web Development</title>
      <dc:creator>Dana</dc:creator>
      <pubDate>Tue, 04 Jan 2022 00:28:32 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/5-challenges-for-magento-e-commerce-web-development-1150</link>
      <guid>https://forem.com/fabric_commerce/5-challenges-for-magento-e-commerce-web-development-1150</guid>
      <description>&lt;p&gt;Magento is one of the most popular e-commerce platforms today. Businesses that want to create a custom shopping experience, a platform that grows with them, or a platform that provides many out-of-the-box features generally lean toward &lt;a href="https://resources.fabric.inc/blog/magento-to-microservices"&gt;Magento&lt;/a&gt;, as it promises all that and more.&lt;/p&gt;

&lt;p&gt;However, every developer who has learned and worked with Magento, including myself, can tell you a handful of reasons why it’s very challenging: It’s very hard to learn, has frequent quirky bugs and issues, and is very slow.&lt;/p&gt;

&lt;p&gt;In this article, we’ll cover the features Magento offers to e-commerce developers. Then we’ll go over five challenges e-commerce developers face when working with Magento. In the end, we’ll take a look at Magento’s alternatives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Magento
&lt;/h2&gt;

&lt;p&gt;When an &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-manager"&gt;e-commerce manager&lt;/a&gt; or &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-professionals"&gt;developer&lt;/a&gt; looks for different &lt;a href="https://resources.fabric.inc/blog/ecommerce-framework"&gt;e-commerce frameworks&lt;/a&gt; and platforms to choose from, Magento is one of the first choices they find that fits many requirements. &lt;/p&gt;

&lt;p&gt;Magento is an &lt;a href="https://resources.fabric.inc/blog/open-source-ecommerce-platforms"&gt;open source e-commerce platform&lt;/a&gt; released in 2008 that is built with PHP. Magento lets developers and business owners create a platform that grows with them as necessary. Adobe recently &lt;a href="https://news.adobe.com/news/news-details/2018/Adobe-to-Acquire-Magento-Commerce/default.aspx"&gt;acquired Magento in 2018&lt;/a&gt;, and since then have made many improvements, most notably on Magento’s documentation.&lt;/p&gt;

&lt;p&gt;Magento is a highly customizable e-commerce framework. When you need to add new features, you can create modules or themes that add to, modify, or override existing features. You have the ability to change the platform per your requirements.&lt;/p&gt;

&lt;p&gt;However, in a lot of use cases, you won’t need to add new features. Magento comes with many features that most businesses find more than enough.&lt;/p&gt;

&lt;p&gt;Furthermore, Magento has a huge community. As an open source platform, it has over &lt;a href="https://github.com/magento/magento2"&gt;1,400 contributors&lt;/a&gt; that help resolve bugs and issues, as well as add enhancements to the platform. A huge part of Magento’s growth is the community that has contributed to it countless times.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magento E-Commerce Development Challenges
&lt;/h2&gt;

&lt;p&gt;This is the part that most developers and teams miss when they look for the right e-commerce platform and land on Magento. Although Magento has a lot of advantages, it comes with many other challenges that most developers, teams, and businesses discover when it’s too late.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s a summary of the difficulties e-commerce developers face when using Magento:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Challenge&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Steep learning curve&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Its complex architecture makes it hard to find experienced Magento e-commerce developers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slow development and websites&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Magento’s e-commerce web development workflow is slow, leading to a bad user experience.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Breaking updates&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Magento occasionally has breaking minor patches.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Costly Resources&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Magento’s resources, such as developers, hosting, and deployment lead to a high “e-commerce tax”.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lacking bug fixes&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Many bugs are labeled as “Cannot Reproduce.”&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  1. Steep learning curve
&lt;/h3&gt;

&lt;p&gt;In 2018, I was hired at a company for the sole purpose of learning Magento. Although I was a pretty skilled PHP developer back then, it was so hard to learn. I’ve been using it every day since then, and I still discover new quirks and unexpected errors or issues.&lt;/p&gt;

&lt;p&gt;As I mentioned earlier, Magento’s documentation has improved since Adobe acquired it. However, it’s still not easy to learn because its architecture is complex. &lt;/p&gt;

&lt;p&gt;Whether it’s something as simple as using Bootstrap in your theme (there are &lt;a href="https://magento.stackexchange.com/search?q=bootstrap"&gt;about 500 questions on Magento StackExchange&lt;/a&gt; just about that) or as complex as creating a module that customizes core functionalities or adds to them, everything in Magento is done the hard way.&lt;/p&gt;

&lt;p&gt;Because it’s hard to learn, it’s hard to find expert Magento e-commerce developers. You’ll either have to hire someone to learn it and become an expert; hire experts that are not easy to find and, consequently, are costly; or rely on freelancer developers, which comes with its own set of problems. &lt;/p&gt;

&lt;p&gt;I once was hired as a freelance developer to fix bugs and issues made by previous freelance developers. Thus, finding and hiring developers to do the job is definitely costly and one of the biggest challenges of using Magento.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Slow development and websites
&lt;/h3&gt;

&lt;p&gt;This challenge deals directly with Magento e-commerce web development. Because of Magento’s complex architecture, two additional problems arise: slow development workflow and slow e-commerce websites.&lt;/p&gt;

&lt;p&gt;The slightest change you have to make might require you to compile the generated code or the static assets for the website—even if it’s something as simple as changing the background color of the page. To see it in action, you have to deploy the static content. That basically means compiling Less, CSS, JavaScript, or other frontend assets for the changes to appear on the website. &lt;/p&gt;

&lt;p&gt;This process becomes more time-wasting as you add more modules and themes because Magento will need to compile all of them even if the change is in just one. This means that developers take longer to implement or release features in Magento compared to the time it would take in other platforms.&lt;/p&gt;

&lt;p&gt;Furthermore, the &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-frontend-backend"&gt;frontend&lt;/a&gt; of your store is pretty slow. This leads to a bad user experience and, ultimately, a bad &lt;a href="https://resources.fabric.inc/blog/ecommerce-seo"&gt;search engine optimization (SEO)&lt;/a&gt; and lower ranking on search engines. &lt;/p&gt;

&lt;p&gt;To make your website faster, you can use some of Magento’s configurations, like bundling and minifying assets. However, you’ll most likely need to use additional tools and services, like &lt;a href="https://www.varnish-cache.org"&gt;Varnish&lt;/a&gt; and &lt;a href="https://redis.io"&gt;Redis&lt;/a&gt; for your website to actually be considerably fast.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Breaking updates
&lt;/h3&gt;

&lt;p&gt;After almost every major or minor release, multiple patches are released to fix the issues these releases bring with them. What makes it worse is that a lot of these problems involve &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-security-issues"&gt;security issues&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you take a look at &lt;a href="https://magento.com/security/patches"&gt;Magento’s Security Center&lt;/a&gt;, you’ll find many patches and some for the same release version.This means that whenever Magento has a new release, you should be careful before updating your platform, as the update can introduce bugs and security issues into it. This also means that using Magento requires constant maintenance for unexpected changes and bugs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Costly resources
&lt;/h3&gt;

&lt;p&gt;The previous points have highlighted this issue quite a bit. Magento requires a lot of costly resources. From the developers you need to hire (whether freelance or in-house) to the hosting, deployment, and maintenance, the costs pile up with time.&lt;/p&gt;

&lt;p&gt;You’ll realize just how much you’ve put into Magento more and more as your business grows. You’ll need more experienced e-commerce developers, especially if you need complex features. You’ll need more cloud, storage, and hosting resources. The list of additional costs can heavily increase with time.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Lacking bug fixes
&lt;/h3&gt;

&lt;p&gt;Again, this is another drawback of Magento’s complex system. Many bugs that might occur in your development or production environment could be hard to reproduce by Magento’s team of developers, which is why there are now &lt;a href="https://github.com/magento/magento2/issues?q=label:%22Issue:%20%20Cannot%20Reproduce%22%20is:closed"&gt;1,500-plus closed issues with the label “Cannot Reproduce”&lt;/a&gt; on GitHub.&lt;/p&gt;

&lt;p&gt;Admittedly, a lot of these bugs and issues occur because of modules you find online or even create yourself. This is because a small change you make might affect something deep in the system that you don’t know about, and might even never find out about, or require a lot of debugging. &lt;/p&gt;

&lt;p&gt;Hence, all these factors mean that although Magento has a strong community that supports it in solving bugs and issues, some bugs might not get a fix, and you’ll have to figure out a way to resolve them on your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magento Alternatives
&lt;/h2&gt;

&lt;p&gt;Magento’s many challenges all go back to its complex architecture. The system is tightly coupled and advanced in a way that makes it hard to learn, causes issues when you try to modify it, and slows down the platform and development process.&lt;/p&gt;

&lt;p&gt;A better alternative to Magento’s monolithic architecture is microservices-based commerce. Microservices-based commerce is the set of e-commerce services you can usually get from an e-commerce platform or framework, except they’re all independent. You can use them together or couple and integrate them with other external services.&lt;/p&gt;

&lt;p&gt;The move from a large system with lots of features and services that are tightly knit to smaller modules or services that are independent of one another but can still work harmoniously together removes the complications and challenges that occur in platforms like Magento.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fabric.inc"&gt;fabric&lt;/a&gt; is a platform that lets you do exactly that—providing a &lt;a href="https://fabric.inc/products"&gt;set of microservices&lt;/a&gt; that you can integrate as necessary.&lt;/p&gt;

&lt;p&gt;With fabric’s &lt;a href="https://fabric.inc/ecommerce-apis"&gt;headless e-commerce APIs&lt;/a&gt; that provide the core functionalities of an e-commerce store through an API independent of the frontend, you have more flexibility in your platform. You can easily make changes to the frontend and the look and feel of your store without worrying about what goes on under the hood. Similarly, you can add new services and integrations to the backend without it affecting the frontend of your store.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Magento offers a lot of built-in features and is very extensible. However, Magento’s challenges often outweigh the advantages of using it. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The 5 developer challenges for Magento e-commerce development include a steep learning curve, slow development and websites, breaking updates, high costs, and the lack of bug fixes. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microservices-based commerce is the better alternative for monolithic platforms like Magento. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With &lt;a href="https://fabric.inc"&gt;fabric&lt;/a&gt;, you get the same advantages you would need from Magento, including its extensibility and wide set of features, but with fewer e-commerce developer challenges.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Building Our E-Commerce Platform with Serverless FaaS</title>
      <dc:creator>Robert Gibb</dc:creator>
      <pubDate>Sun, 26 Sep 2021 22:57:33 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/building-our-e-commerce-platform-with-serverless-faas-fcl</link>
      <guid>https://forem.com/fabric_commerce/building-our-e-commerce-platform-with-serverless-faas-fcl</guid>
      <description>&lt;p&gt;&lt;em&gt;This post was published here on behalf of &lt;a href="https://www.linkedin.com/in/devashish90/" rel="noopener noreferrer"&gt;Devashish Pandey&lt;/a&gt;, a lead software development engineer at &lt;a href="https://fabric.inc" rel="noopener noreferrer"&gt;fabric&lt;/a&gt; who previously worked on platform and API development at SecureDB and StormDB.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With so many "something-as-a-service" options at our disposal for infrastructure, in 2017 we opted for &lt;a href="https://www.cloudflare.com/learning/serverless/glossary/function-as-a-service-faas/" rel="noopener noreferrer"&gt;function-as-a-service (FaaS)&lt;/a&gt; to build our platform of e-commerce services. Our mission was, and remains, to build for e-commerce services what AWS built for web services, or what we call the commerce fabric of the internet.&lt;/p&gt;

&lt;p&gt;Building with FaaS and only paying for function execution time rather than constantly running servers (i.e. &lt;a href="https://www.cloudflare.com/learning/serverless/what-is-serverless/" rel="noopener noreferrer"&gt;serverless&lt;/a&gt;) allowed us to serve customers early on without incurring high infrastructure costs. These customers were large, household names and referrals from our founding team who had &lt;a href="https://resources.fabric.inc/blog/answers/staples-b2b-commerce" rel="noopener noreferrer"&gt;transformed digital at Staples&lt;/a&gt;. Part of this transformation involved moving from the monolithic e-commerce platform IBM Websphere to a &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-microservices-architecture" rel="noopener noreferrer"&gt;service-oriented architecture&lt;/a&gt; with open-source and custom-built software.&lt;/p&gt;

&lt;p&gt;E-commerce veterans who knew our founding team wanted to transform digital for their companies, which led us to build our platform of modular commerce services in 2017. Using serverless FaaS with &lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; supported these services reliably and efficiently, and it continued to support them through 2020 when we raised &lt;a href="https://news.crunchbase.com/news/next-top-brand-fabric-closes-9-5m-seed-for-e-commerce-platform/" rel="noopener noreferrer"&gt;our $9.5M seed round&lt;/a&gt; and attracted customers outside of our circle of friends.&lt;/p&gt;

&lt;p&gt;But as we raise more money (most recently &lt;a href="https://www.bloomberg.com/news/articles/2021-07-20/e-commerce-tech-startup-fabric-raises-100-million-in-new-round" rel="noopener noreferrer"&gt;our $100M Series B&lt;/a&gt;) and onboard global brands &lt;a href="https://www.capterra.com/p/215448/Fabric/#reviews" rel="noopener noreferrer"&gt;like GNC&lt;/a&gt;, life on the serverless backend is not as easy as it once was. As a result, some challenges that were inconsequential at the time are now more pronounced. In this post, I will explain how we direct these serverless challenges and show you how serverless FaaS powers &lt;a href="https://fabric.inc/" rel="noopener noreferrer"&gt;our platform of commerce services&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Serverless Architecture
&lt;/h2&gt;

&lt;p&gt;The current iteration of the fabric platform can be hosted in either AWS, GCP, Azure, and even Knative since all of these are supported by the &lt;a href="https://www.serverless.com/" rel="noopener noreferrer"&gt;serverless framework&lt;/a&gt; we use. However, in 2017 when we adopted serverless, AWS had the &lt;a href="https://www.veritis.com/blog/cloud-computing-maturity-model/" rel="noopener noreferrer"&gt;most mature&lt;/a&gt; offering so we made the simple choice in choosing Lambda for FaaS.&lt;/p&gt;

&lt;p&gt;Flash forward to today and we still use Lambda and sparingly route requests through &lt;a href="https://aws.amazon.com/fargate/" rel="noopener noreferrer"&gt;AWS Fargate&lt;/a&gt;, a container-as-a-service (CaaS) environment. Fargate is mainly used when we can't meet latency service level agreements (SLAs) with Lambda due to cold start problems. However, since Lambda powers 95% of all processes within our platform, we've found ways to direct these issues which I'll talk about below.&lt;/p&gt;

&lt;p&gt;As for the way our products are structured, a data store layer is used, followed by a business layer in which most logic is programmed as you would with any other backend scenario. Lambda orchestrates event-driven workflows at the business and data storage layers.&lt;/p&gt;

&lt;p&gt;The actual product offerings consist of commerce applications like a &lt;a href="https://fabric.inc/pim" rel="noopener noreferrer"&gt;product information manager (PIM)&lt;/a&gt; and &lt;a href="https://fabric.inc/oms" rel="noopener noreferrer"&gt;order management system (OMS)&lt;/a&gt;, referred to as Co-Pilot Apps in the diagram below. (Co-Pilot is the name of the UI that merchandisers, marketers, and other business users interact with.) We also offer &lt;a href="https://fabric.inc/storefront" rel="noopener noreferrer"&gt;e-commerce storefronts&lt;/a&gt; that fast-track storefront development. Each type of offering has a separate yet connected business layer. &lt;/p&gt;

&lt;p&gt;On the top level, each layer is supported by Lambda in a serverless manner. API gateway routes interface between them, and the logic layer and external services layer interface through integrations.&lt;/p&gt;

&lt;p&gt;Every action, process module, and element of the platform is isolated into standalone functions in Lambda. The resulting layout achieves full separation of concern, with a single gateway route connecting with a single layer action/process at any given time. This cancels out the most common issues with resource sharing and allows each action/module to scale independently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fcopilot-apps-1.png%3Fwidth%3D1490%26name%3Dcopilot-apps-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fcopilot-apps-1.png%3Fwidth%3D1490%26name%3Dcopilot-apps-1.png" alt="copilot-apps-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing Serverless
&lt;/h2&gt;

&lt;p&gt;There are numerous tools engineers can use to manage serverless setups of the type I've discussed thus far. However, mainly because it was one of the earlier market representatives, we decided to use &lt;a href="https://www.serverless.com/" rel="noopener noreferrer"&gt;the Serverless Framework&lt;/a&gt; to manage serverless infrastructure through &lt;a href="https://serverless-stack.com/chapters/what-is-infrastructure-as-code.html" rel="noopener noreferrer"&gt;infrastructure as code (IaC)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Adopting the Serverless Framework as our infrastructure modeling and standardization tool enables quick spring-ups of environments. Further, the vendor-agnostic nature of the framework leaves room for any migration toward a cloud-agnostic, client-requested offering down the road. Using the Serverless Framework, we could support this offering while maintaining the same variables for mushroomed fabric platform instances.&lt;/p&gt;

&lt;p&gt;In addition to these benefits, we found getting started with the Serverless Framework incredibly easy, even for a robust platform of applications &lt;a href="https://api.fabric.inc/" rel="noopener noreferrer"&gt;and APIs&lt;/a&gt; like ours. If you want to try it yourself, just launch your terminal and install the &lt;a href="https://www.npmjs.com/package/serverless" rel="noopener noreferrer"&gt;node package manager&lt;/a&gt;. After that, a simple serverless command sets your environment up for configuration and management through the &lt;a href="https://www.serverless.com/framework/docs/providers/aws/cli-reference/config" rel="noopener noreferrer"&gt;framework's CLI&lt;/a&gt;. A serverless.yml file is then created, which is where it all started for us in 2017!&lt;/p&gt;

&lt;p&gt;Below is what a typical serverless.yml file configuration looks like using the Serverless Framework. The scripting language used is proprietary serverless.js, specific for a node.js app running on a MongoDB data store layer. This setup is similar to our own.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fserverless.yml-file-configuration-1.png%3Fwidth%3D1532%26name%3Dserverless.yml-file-configuration-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fserverless.yml-file-configuration-1.png%3Fwidth%3D1532%26name%3Dserverless.yml-file-configuration-1.png" alt="serverless.yml-file-configuration-1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The provider section of the config file allows for the full exploration of cloud services providers. However, we continue to use AWS as our go-to provider as we've found that other providers cause capacity bottlenecks as we continue supporting &lt;a href="https://resources.fabric.inc/blog/ecommerce-api-security" rel="noopener noreferrer"&gt;more of the world's largest retailers&lt;/a&gt; and brands. After AWS is selected, each function across the implementation is associated with a handler and specific API gateways. &lt;/p&gt;

&lt;p&gt;Using this template has dramatically improved the accuracy and speed of infrastructure configurations as we scale with serverless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless Challenges 
&lt;/h2&gt;

&lt;p&gt;As good as the story sounds so far, we have experienced our fair share of challenges with serverless and continue to experiment with ways to maintain business efficiencies while improving capacity and performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Capacity
&lt;/h3&gt;

&lt;p&gt;While our current setup has enough capacity to support existing customers, there's always concern about having enough serverless infrastructure to support more, larger customers---especially during &lt;a href="https://www.cnbc.com/2019/12/25/reuters-america-corrected-record-online-sales-give-u-s-holiday-shopping-season-a-boost-report.html" rel="noopener noreferrer"&gt;holiday shopping bursts&lt;/a&gt;. To get ahead of this, we are experimenting with augmenting Lambda with &lt;a href="https://aws.amazon.com/eks/" rel="noopener noreferrer"&gt;Amazon EKS&lt;/a&gt; using serverless containers with AWS Fargate. &lt;/p&gt;

&lt;p&gt;Cloud-agnostic support is an option we are exploring as well. But before allowing customers to dictate their cloud provider, we need to better understand capacity with GCP and Azure. With customers calling the shots for infrastructure, capacity issues could also arise with AWS. For instance, if a customer selects an AWS region of deployment outside USA East and West, &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/invocation-scaling.html" rel="noopener noreferrer"&gt;burst concurrency diminishes&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;What makes serverless efficient for your business can cause inefficiencies with application performance, particularly when using Lambda functions. These inefficiencies occur during the cold start duration when Lambda is downloading your code and starting a new execution environment. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Flambda-performance.png%3Fwidth%3D855%26name%3Dlambda-performance.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Flambda-performance.png%3Fwidth%3D855%26name%3Dlambda-performance.png" alt="lambda-performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To reduce inefficiencies, we have tested and implemented &lt;a href="https://aws.amazon.com/blogs/compute/operating-lambda-performance-optimization-part-1/" rel="noopener noreferrer"&gt;several performance optimizations&lt;/a&gt;. One workaround we use for avoiding cold starts is periodic warmup events that counteract environment timeouts. We are also exploring &lt;a href="https://aws.amazon.com/lambda/edge/#:~:text=Lambda%40Edge%20is%20a%20feature,improves%20performance%20and%20reduces%20latency.&amp;amp;text=With%20Lambda%40Edge%2C%20you%20can,all%20with%20zero%20server%20administration." rel="noopener noreferrer"&gt;Lambda@Edge&lt;/a&gt; (&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html" rel="noopener noreferrer"&gt;Lambda + Amazon Cloudfront&lt;/a&gt;) to offset any latency caused by Lambda. However, while doing this, we are trying not to defeat the cost-benefit variable for which Lambda was chosen in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stick with Serverless?
&lt;/h2&gt;

&lt;p&gt;Despite these challenges, we remain loyal to serverless infrastructure and putting product development ahead of server management. As one of the fastest-growing tech startups in e-commerce this year, serverless has served us well in supporting new customers while enabling fast iterations of new commerce services like &lt;a href="https://fabric.inc/subscriptions" rel="noopener noreferrer"&gt;Subscriptions&lt;/a&gt; and &lt;a href="https://fabric.inc/member" rel="noopener noreferrer"&gt;Loyalty Management&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While AWS Lambda is not yet perfect, we have noticed that, as fabric grows, so too does Lambda in terms of capacity. This gives us breathing room to test iterations of Lambda and other serverless offerings from AWS while continuing conversations and experimentation around matching the right architecture with the right infrastructure.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>architecture</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Hardening E-Commerce APIs to Secure Billion-Dollar Retailers</title>
      <dc:creator>Niloufar Heidari</dc:creator>
      <pubDate>Sun, 12 Sep 2021 20:02:36 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/hardening-e-commerce-apis-to-secure-billion-dollar-retailers-21l4</link>
      <guid>https://forem.com/fabric_commerce/hardening-e-commerce-apis-to-secure-billion-dollar-retailers-21l4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhubfs%2Fretail-ecommerce-api-security.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhubfs%2Fretail-ecommerce-api-security.png" alt="Alt text of image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At fabric we are building a &lt;a href="https://resources.fabric.inc/blog/glossary/modular-commerce" rel="noopener noreferrer"&gt;modular&lt;/a&gt; and &lt;a href="https://resources.fabric.inc/blog/headless-commerce" rel="noopener noreferrer"&gt;headless&lt;/a&gt; commerce platform with the vision of becoming for commerce services what AWS is for web services, and due to the headless nature of our platform, APIs run the show. So much so that a multi-billion dollar equipment supplier just signed a multi-million dollar contract with us to consume our commerce APIs.&lt;/p&gt;

&lt;p&gt;API security was a concern before I joined fabric in January 2021, but as we attract more billion-dollar retailers such as Restoration Hardware, GNC, and Staples—including more general market interest with our recent $100M Series B—API security is now a high priority.&lt;/p&gt;

&lt;p&gt;In this post, I will show you our general approach for securing APIs to support these major retailers. But first, let’s briefly review why API security matters.&lt;/p&gt;

&lt;h1&gt;
  
  
  Why is API Security Important in Retail?
&lt;/h1&gt;

&lt;p&gt;At fabric we use APIs to connect internal platform services such as cart, checkout, and pricing, and external services such as Stripe (payments), Alavara (tax), and Algolia (search). These connections mean data transfer and compromised APIs are behind &lt;a href="https://www.cloudvector.com/api-data-breaches-in-2020/" rel="noopener noreferrer"&gt;major data breaches&lt;/a&gt;. With mainstream retail, personally identifiable and payment information is widely required to conduct trade and, as e-commerce grows, the attack surface grows with it.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://owasp.org/www-project-api-security/" rel="noopener noreferrer"&gt;API Security project by OWASP&lt;/a&gt; supports this:&lt;/p&gt;

&lt;p&gt;“A foundational element of innovation in today’s app-driven world is the API. From banks, retail and transportation to IoT, autonomous vehicles and smart cities, APIs can be found in customer-facing, partner-facing and internal applications. By nature, APIs expose application logic and sensitive data such as Personally Identifiable Information (PII) and because of this have increasingly become a target for attackers. Without secure APIs, rapid innovation would be impossible.”&lt;/p&gt;

&lt;p&gt;Below I will describe the tactics we use to secure our APIs. With these tactics, the &lt;a href="https://owasp.org/www-project-api-security/" rel="noopener noreferrer"&gt;top ten API security threats&lt;/a&gt; top ten API security threats identified by OWASP are directed. &lt;strong&gt;Note&lt;/strong&gt;: The OWASP API security project is nascent and needs contributors!&lt;/p&gt;

&lt;h1&gt;
  
  
  How We Secure APIs
&lt;/h1&gt;

&lt;p&gt;These are the different &lt;a href="https://api.fabric.inc/" rel="noopener noreferrer"&gt;RESTful APIs we use&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customer storefront APIs:&lt;/strong&gt; Our Storefront API protects e-commerce store frontends (including mobile apps). It is a modular, customizable, and secure API gateway that provides a single data source for all your UIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third-party APIs:&lt;/strong&gt; These are APIs provided by fabric to third-party vendors like Zendesk or RevCascade to access order and inventory modules. For example, mapping APIs are used to update inventory with new products from merchants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Merchant application APIs:&lt;/strong&gt; This is a customer API that is unique for each customer.&lt;/p&gt;

&lt;p&gt;All of our API traffic is securely transmitted using HTTPS and modern TLS protocols. In addition to applying security best practices for data in transit via APIs, we take these security measurements:&lt;/p&gt;

&lt;h1&gt;
  
  
  Internal Vulnerability Testing
&lt;/h1&gt;

&lt;p&gt;Using vulnerability assessment tools (e.g. &lt;a href="https://www.ibm.com/security/security-intelligence/qradar" rel="noopener noreferrer"&gt;QRadar&lt;/a&gt;, &lt;a href="//qualys.com"&gt;Qualys&lt;/a&gt;, and &lt;a href="https://www.tenable.com/products/nessus" rel="noopener noreferrer"&gt;Nessus&lt;/a&gt;) and considering new security enhancements throughout the software development life cycle (SDLC) is essential for keeping APIs secure. At fabric, our continuous vulnerability management process makes security a key aspect of API development.&lt;/p&gt;

&lt;p&gt;Security tooling is part of our CI/CD pipeline and automated security-focused unit tests run against every deployment. Additionally, we run monthly vulnerability scans to identify and categorize API security issues for all of our customers. If we identify any critical security vulnerabilities, they’re patched within a week.&lt;/p&gt;

&lt;h1&gt;
  
  
  Third-Party Pen Tests
&lt;/h1&gt;

&lt;p&gt;Third-party penetration tests reputable firms (e.g. &lt;a href="https://www.trustwave.com/en-us/company/about-us/spiderlabs/" rel="noopener noreferrer"&gt;SpiderLabs&lt;/a&gt;, &lt;a href="https://cobalt.io/" rel="noopener noreferrer"&gt;Cobalt&lt;/a&gt;, and &lt;a href="https://www.fireeye.com/" rel="noopener noreferrer"&gt;FireEye&lt;/a&gt;) provide an objective expert analysis of a system’s security. A third-party pen test can expose vulnerabilities an internal audit and automated testing alone can miss.&lt;/p&gt;

&lt;p&gt;In addition to leveraging automated scanning tools, third-party pen testers provide the human expertise necessary to identify misconfigurations and exploits that could otherwise go unnoticed. &lt;/p&gt;

&lt;p&gt;For example, automated tooling is great at identifying common vulnerabilities and exposures (CVEs), but an attack that exploits business logic in an e-commerce site’s frontend APIs may go undetected. Simply put: third-party testing manipulates and attempts to hack an API in the same ways a real attacker would. This human perspective makes it possible to detect and correct misconfigurations and logic flaws before an attacker exploits them.&lt;/p&gt;

&lt;p&gt;At fabric, we conduct third-party pen tests for our entire API annually and before every major release.&lt;/p&gt;

&lt;h1&gt;
  
  
  Authentication and Authorization
&lt;/h1&gt;

&lt;p&gt;Validating users are who they say they are (authentication) and only allowing access to resources they have permissions for (authorization) is fundamental to API security. fabric authenticates users and then provides them with a &lt;a href="https://jwt.io/introduction" rel="noopener noreferrer"&gt;JSON Web Token (JWT)&lt;/a&gt;.  Authorization of those requests is secured using Okta’s implementation of the industry-standard &lt;a href="https://developer.okta.com/docs/reference/api/oidc/" rel="noopener noreferrer"&gt;OAuth 2.0 protocol&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;End-to-end, the process works like this:&lt;/p&gt;

&lt;p&gt;A client sends credentials (username and password) to the fabric login API.&lt;/p&gt;

&lt;p&gt;The credentials are verified by comparing what the client provides to a salted hash. (Credentials are encrypted using a robust hashing algorithm.) &lt;/p&gt;

&lt;p&gt;If the credentials are valid, the API signs and returns a JWT. If the credentials are invalid, the login request is rejected. Rate-limiting on the login API prevents brute force attacks.&lt;/p&gt;

&lt;p&gt;The client verifies the token and sends the signed token with every subsequent request. This eliminates the need for the client to include credentials for any other requests in the session.&lt;/p&gt;

&lt;p&gt;OAuth 2.0 authorization ensures that the client can only access API endpoints they have adequate permissions for. &lt;/p&gt;

&lt;h1&gt;
  
  
  API Throttling
&lt;/h1&gt;

&lt;p&gt;DDoS attacks can prevent an e-commerce site from processing legitimate orders and are one of the &lt;a href="https://www.infosecurity-magazine.com/news/ddos-online-four/" rel="noopener noreferrer"&gt;biggest threats facing large retailers&lt;/a&gt;. API throttling allows us to limit the number of API requests per second and prevent DDoS from bringing a site down. &lt;/p&gt;

&lt;p&gt;Of course, with any throttling, there is the risk of false positives. To mitigate this risk, we use automation to optimize the throttling of APIs and reduce false positives while still providing protection from malicious attacks. Additionally, limits are based on both steady-state rates and bursts to account for different behaviour patterns. &lt;/p&gt;

&lt;p&gt;To implement API throttling, we use &lt;a href="https://aws.amazon.com/api-gateway/" rel="noopener noreferrer"&gt;AWS API Gateway&lt;/a&gt;. At a high level, the throttling process works like this:&lt;/p&gt;

&lt;p&gt;Clients call an API.&lt;/p&gt;

&lt;p&gt;If the number of requests is less than the throttling limit, the request is processed normally.&lt;/p&gt;

&lt;p&gt;If the number of requests exceeds the throttling limit, the user receives an error and must wait to send additional requests.&lt;/p&gt;

&lt;h1&gt;
  
  
  API Keys
&lt;/h1&gt;

&lt;p&gt;Like API throttling, API keys help limit abuse of our API and protect e-commerce sites that depend on it. API keys include a unique identifier (key ID) that allows us to meter access and prevent attacks. &lt;/p&gt;

&lt;p&gt;Keys are created for each fabric customer and tied to specific entities. Clients must include a key ID and secret key in their requests. By tracking key IDs, we can hone in on malicious behaviour and block it at the source. &lt;/p&gt;

&lt;h1&gt;
  
  
  CORS Support
&lt;/h1&gt;

&lt;p&gt;By default, modern web clients only allow servers to execute scripts from their own &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Origin" rel="noopener noreferrer"&gt;origin&lt;/a&gt; (an origin is a domain, scheme, or port). This is known as the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy" rel="noopener noreferrer"&gt;same-origin policy&lt;/a&gt;. From a security perspective, the same-origin policy has obvious benefits. For example, it prevents a malicious site from executing JavaScript that reads data from another webpage a user is logged into. &lt;/p&gt;

&lt;p&gt;Of course, there are plenty of legitimate reasons a site or API may need to call resources with a different origin. &lt;a href="https://blog.stackpath.com/glossary-cross-origin-resource-sharing/" rel="noopener noreferrer"&gt;Cross-Origin Resource Sharing (CORS)&lt;/a&gt; solves this problem and allows servers to securely access resources from specific, pre-defined domains.&lt;/p&gt;

&lt;p&gt;To implement CORS, we use the &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/example-function-add-cors-header-response.html" rel="noopener noreferrer"&gt;AWS CloudFront CDN&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html" rel="noopener noreferrer"&gt;AWS CORS&lt;/a&gt; for our REST APIs. Our implementation ensures only authorized cross-origin scripts can be executed.&lt;/p&gt;

&lt;p&gt;Here’s a simple example of how we use CORS in practice:&lt;/p&gt;

&lt;p&gt;A client uses the fabric Commerce API gateway to load their website from an S3 Bucket at example.website.s3.us-east-1.amazonaws.com.&lt;/p&gt;

&lt;p&gt;To load resources and allow users to interact with the online store and shop, the site uses JavaScript to make authenticated HTTP GET and PUT requests against the same example.website.s3.us-east-1.amazonaws.com bucket.&lt;/p&gt;

&lt;p&gt;Typically, a modern web browser would block the requests to example.website.s3.us-east-1.amazonaws.com because they’re from a different origin. However, with CORS, we can explicitly allow specific cross-origin requests (in this case, example.website.s3.us-east-1.amazonaws.com), and the site will work as intended.  &lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;What we’ve discussed here covers a majority of the API attack surface. Still, we also perform regular code security audits; maintain compliance with standards including &lt;a href="https://resources.fabric.inc/blog/ecommerce-pci-compliance" rel="noopener noreferrer"&gt;PCI DSS&lt;/a&gt;, SOC2 Type II, NIST 800, and OWASP Top 10; and implement robust identity and access management to secure our APIs.&lt;/p&gt;

&lt;p&gt;In addition to directing common API security issues, &lt;a href="https://fabric.inc/knowledgebase/start/security-compliance" rel="noopener noreferrer"&gt;we document our security approach&lt;/a&gt; to help customers understand how their data and the data of their customers is protected when using our commerce platform.&lt;/p&gt;

&lt;p&gt;If you’re developing an API-based platform for retailers (or for users within another industry), implementing the tactics described in this blog post will harden the platform instances you deploy for your customers. It will also secure shopping-related data at scale and help your customers earn trust among shoppers in this evolving digital landscape.&lt;/p&gt;

</description>
      <category>apisecurity</category>
      <category>ecommerce</category>
      <category>b2b</category>
      <category>onlineshopping</category>
    </item>
    <item>
      <title>E-Commerce Frontend Vs Backend: What's the Difference?</title>
      <dc:creator>Indraneil Khedekar</dc:creator>
      <pubDate>Tue, 07 Sep 2021 15:52:57 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/e-commerce-frontend-vs-backend-what-s-the-difference-487a</link>
      <guid>https://forem.com/fabric_commerce/e-commerce-frontend-vs-backend-what-s-the-difference-487a</guid>
      <description>&lt;p&gt;The frontend of an e-commerce website is the part that online shoppers see and interact with. This is also referred to as the &lt;a href="https://resources.fabric.inc/blog/answers/digital-storefronts" rel="noopener noreferrer"&gt;digital storefront&lt;/a&gt;. The backend of an e-commerce website is the part that handles all the data such as prices, promotions, product images, order details, and fulfillment.&lt;/p&gt;

&lt;p&gt;In short, the frontend defines how the online shopping experience feels, and the backend defines how it functions.&lt;/p&gt;

&lt;p&gt;As the touchpoints between buyers and sellers grow, the need for consistent shopping experiences across e-commerce websites and other sales channels grows as well. A &lt;a href="https://www.thinkwithgoogle.com/consumer-insights/consumer-trends/meeting-shoppers-needs-omnichannel-drives-instore/" rel="noopener noreferrer"&gt;2017 study by Google&lt;/a&gt; found that retailers implementing multi-channel strategies saw 80% more store visits.&lt;/p&gt;

&lt;p&gt;Understanding the difference between the e-commerce backend and frontend and how they work together can help you design a seamless &lt;a href="https://resources.fabric.inc/blog/omnichannel-commerce" rel="noopener noreferrer"&gt;omnichannel shopping experience&lt;/a&gt; for your customers. Understanding how separating them in a “headless commerce” setup can then help with scaling that experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend vs Backend
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;The e-commerce frontend, or client-side, is what people (i.e. clients) see when they visit your site. It’s the part of your site that shoppers interact with directly and includes features like fonts, colors, drop-down menus, image sliders, shopping carts, search bars, and &lt;a href="https://resources.fabric.inc/blog/answers/product-detail-page" rel="noopener noreferrer"&gt;product detail pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Frontend development ensures that an e-commerce website (or other digital sales channel) is functional and visually appealing by prioritizing the user experience. Frontend developers use programming languages like JavaScript, HTML, and CSS to create and manage a website’s frontend.&lt;/p&gt;

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

&lt;p&gt;The e-commerce backend, or server-side, is the data access layer that holds products, orders, and customer information. It helps websites operate by processing, storing, and transferring their data to and from the customer-facing side. These actions are carried out by backend components like the web server, application server, and database which make the frontend interactive. They make it so customers can view products, place orders, and manage their purchases using their own devices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional Frontend and Backend in E-Commerce
&lt;/h2&gt;

&lt;p&gt;Traditional e-commerce platforms such as &lt;a href="https://resources.fabric.inc/blog/oracle-atg-to-microservices" rel="noopener noreferrer"&gt;Oracle ATG&lt;/a&gt;, &lt;a href="https://resources.fabric.inc/blog/salesforce-commerce-to-microservices" rel="noopener noreferrer"&gt;Salesforce Commerce Cloud&lt;/a&gt;, and &lt;a href="https://resources.fabric.inc/blog/shopify-plus-to-microservices" rel="noopener noreferrer"&gt;Shopify Plus&lt;/a&gt; bring the front and back ends together into &lt;a href="https://resources.fabric.inc/blog/answers/monolithic-software" rel="noopener noreferrer"&gt;tightly coupled systems&lt;/a&gt;. This approach makes it easy for merchants to deploy online stores but has several downsides.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fv19ngemr9yecj8s1o0y5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fv19ngemr9yecj8s1o0y5.png" alt="frontend vs backend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These coupled, monolithic platforms lack flexibility. Adding new applications to such systems can compromise their integrity due to the dependencies between their front and back ends. &lt;/p&gt;

&lt;p&gt;For instance, Shopify merchants that use apps to add functionality to their stores often struggle with site performance issues. Something as simple as adding a small popup widget can decrease page speed, introduce vulnerabilities, and cause JavaScript and CSS conflicts that can potentially “break” the frontend.&lt;/p&gt;

&lt;p&gt;The good news is there's an alternative that overcomes the rigidity of &lt;a href="https://resources.fabric.inc/blog/answers/enterprise-ecommerce-platforms" rel="noopener noreferrer"&gt;legacy e-commerce systems&lt;/a&gt;. The need for better functionality, easier integrations, and consistent shopping experiences across channels has fueled the rise of a new approach to building e-commerce systems called &lt;a href="https://resources.fabric.inc/blog/headless-commerce" rel="noopener noreferrer"&gt;headless commerce&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This approach separates the front and back ends of an e-commerce solution. It allows all the different frontends and the backend to exist independently, resulting in fewer dependencies so brands and retailers can scale to match varying business needs across channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Headless Frontend and Backend in E-Commerce
&lt;/h2&gt;

&lt;p&gt;In a headless architecture, the front and back end &lt;a href="https://resources.fabric.inc/blog/rest-apis" rel="noopener noreferrer"&gt;communicate using APIs&lt;/a&gt;. This allows the backend to connect with multiple frontends across varying touchpoints, which is important since online touchpoints exist far beyond the web browser. They include every device used to make a purchase or a purchase decision.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F5hfjtz55aolm3e5jan6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F5hfjtz55aolm3e5jan6z.png" alt="backend-api-gateway-frontend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Headless systems can connect with a diverse range of digital touchpoints such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smartwatches&lt;/li&gt;
&lt;li&gt;Smart refrigerators&lt;/li&gt;
&lt;li&gt;Smart speakers and &lt;a href="https://resources.fabric.inc/blog/answers/voice-commerce" rel="noopener noreferrer"&gt;voice assistants&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In-store kiosks&lt;/li&gt;
&lt;li&gt;Digital signage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s not all. The e-commerce backend in a headless system can be built differently as well. Unlike a tightly coupled system that holds the commerce, cart, and order management functionality in a single structure, the backend system can be &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-microservices-architecture" rel="noopener noreferrer"&gt;constructed using modules&lt;/a&gt;. This approach gets rid of complex dependencies and helps websites adapt to changing needs without interruptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of a headless frontend and backend
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Safer upgrades
&lt;/h4&gt;

&lt;p&gt;Separating the content (frontend) and delivery (backend) systems gives you more control over both aspects. You’re able to adjust each part independently without jeopardizing the entire system. You can add and remove components and test new technologies with little to no downtime.&lt;/p&gt;

&lt;h4&gt;
  
  
  Better personalization
&lt;/h4&gt;

&lt;p&gt;Independent frontends allow you to experiment with design changes easily. They also help you offer personalized shopping experiences. You can modify store designs to suit individual customer preferences and display tailored content on the fly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Easier omnichannel
&lt;/h4&gt;

&lt;p&gt;A headless approach makes it easy for you to &lt;a href="https://resources.fabric.inc/blog/multichannel-ecommerce" rel="noopener noreferrer"&gt;sell across different touchpoints&lt;/a&gt;. With an independent front and back end, you’re able to design unique shopping experiences across all of your sales channels. You can do it without slowing down your digital storefront.&lt;/p&gt;

&lt;h4&gt;
  
  
  More freedom
&lt;/h4&gt;

&lt;p&gt;An &lt;a href="https://fabric.inc/ecommerce-apis" rel="noopener noreferrer"&gt;API-based approach&lt;/a&gt; lets you experiment with platforms and technologies. Don’t like your store design? Slap on a responsive, Vue-based storefront. Battling a buggy product management system? Move your catalog to &lt;a href="https://fabric.inc/pim" rel="noopener noreferrer"&gt;fabric PIM&lt;/a&gt;. You can explore different options until you find what works for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The front and back ends are two parts of the &lt;a href="https://resources.fabric.inc/blog/glossary/mach" rel="noopener noreferrer"&gt;e-commerce architecture&lt;/a&gt; that define its design and functionality.&lt;/li&gt;
&lt;li&gt;The outdated approach of coupling the front and back end lacks the flexibility needed for a successful omnichannel commerce strategy.&lt;/li&gt;
&lt;li&gt;A decoupled front and back end makes it easier to sell across channels, improves site performance, and gives you more freedom to make design changes.&lt;/li&gt;
&lt;li&gt;You can use frontend solutions for e-commerce such as &lt;a href="https://fabric.inc/xm" rel="noopener noreferrer"&gt;fabric XM&lt;/a&gt; and backend solutions such as &lt;a href="https://fabric.inc/pim" rel="noopener noreferrer"&gt;fabric PIM&lt;/a&gt; to facilitate a seamless omnichannel experience.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Making E-Commerce More Accessible: 6 Tips for Developers</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Tue, 07 Sep 2021 13:26:29 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/making-e-commerce-more-accessible-6-tips-for-developers-82n</link>
      <guid>https://forem.com/fabric_commerce/making-e-commerce-more-accessible-6-tips-for-developers-82n</guid>
      <description>&lt;p&gt;&lt;a href="https://media.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%2Ffxndbjfe3qtskw265gng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffxndbjfe3qtskw265gng.png" alt="Making E-Commerce More Accessible: 6 Tips for Developers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ignoring accessibility is a way to drive customers away from your e-commerce site. While it’s easy for developers to focus on new features and bug fixing, putting effort into inclusive, accessible sites will have huge benefits.&lt;/p&gt;

&lt;p&gt;Accessibility impairment is more common than you might think. According to &lt;a href="https://www.shopify.com/partners/blog/developing-shopify-themes-with-accessibility-in-mind" rel="noopener noreferrer"&gt;Shopify data&lt;/a&gt;, 2.3 percent of people live with a reading disorder, 8 percent of men have a form of color blindness, and 7 percent of people live with a severe dexterity disability. &lt;/p&gt;

&lt;p&gt;In this article, I’ll highlight six areas where developers can make e-commerce sites more accessible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Current Accessibility Standards
&lt;/h2&gt;

&lt;p&gt;Accessibility standards exist to outline what to work toward clearly. The &lt;a href="https://www.w3.org/WAI/standards-guidelines/wcag/" rel="noopener noreferrer"&gt;Web Content Accessibility Guidelines&lt;/a&gt; is a great resource for web content accessibility. It provides a single, shared global standard to meet the needs of individuals, organizations, and governments. &lt;/p&gt;

&lt;p&gt;In some cases, accessibility standards are &lt;a href="https://www.boia.org/blog/is-there-a-legal-requirement-to-implement-wcag" rel="noopener noreferrer"&gt;legally required&lt;/a&gt;. Applicable rules depend on your location, the products you sell, and the size of your business.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Implement Accessibility
&lt;/h2&gt;

&lt;p&gt;If you’re just beginning to implement accessibility, &lt;a href="https://a11y-101.com/" rel="noopener noreferrer"&gt;a11y-101&lt;/a&gt; is a great starting point. After implementation, ensure the product works well on screen readers and can be used via keyboard navigation. User testing, although pricier, is also an effective option.&lt;/p&gt;

&lt;p&gt;Automatic audit tools, like the &lt;a href="https://addyosmani.com/a11y/" rel="noopener noreferrer"&gt;a11y command line tool&lt;/a&gt;, identify issues quickly and easily. The &lt;a href="http://squizlabs.github.io/HTML_CodeSniffer/" rel="noopener noreferrer"&gt;HTML_CodeSniffer&lt;/a&gt; is useful when testing for specific compliance guidelines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffcz1jkl3d26c6mszvrx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffcz1jkl3d26c6mszvrx9.png" alt="Screenshot showing the a11y command line tool giving fabric’s site a full audit pass"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the result of using the a11y command-line tool on &lt;a href="https://fabric.inc/" rel="noopener noreferrer"&gt;fabric’s site&lt;/a&gt;. Installing took thirty seconds, and running the tool is even quicker. Tools like this can significantly improve your accessibility without sacrificing time. &lt;/p&gt;

&lt;p&gt;Let’s take a look at six specific tips for addressing problem areas to improve the accessibility of your e-commerce channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Improve Product Carousels
&lt;/h2&gt;

&lt;p&gt;A carousel is a visually appealing way to show off products. This love, however, is not &lt;a href="https://shouldiuseacarousel.com/" rel="noopener noreferrer"&gt;universal&lt;/a&gt;. They have several &lt;a href="https://a11y-101.com/development/carousels" rel="noopener noreferrer"&gt;accessibility problems&lt;/a&gt;. First, their controls are unclear, particularly for the visually or cognitively impaired. Second, a screen reader may not associate controls with the required action. A control system that is obvious to a designer may not be intuitive to users.&lt;/p&gt;

&lt;p&gt;Carousels that autoplay are an issue for those who &lt;a href="https://www.creativebloq.com/accessibility-expert-warns-stop-using-carousels-7133778" rel="noopener noreferrer"&gt;use a keyboard&lt;/a&gt; to select screen elements. Users may not reach the control they want in time. Those who need more time to read are also frustrated when content changes automatically. Furthermore, the element chosen may also revert to the first available one when the carousel updates, making the whole site difficult to use. &lt;/p&gt;

&lt;p&gt;If your client insists on using a carousel, you can still take steps to improve its accessibility. For example, see &lt;a href="https://www.w3.org/WAI/tutorials/carousels/working-example/" rel="noopener noreferrer"&gt;this sample code&lt;/a&gt; from the W3C Web Accessibility Initiative (WAI) under &lt;a href="https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document" rel="noopener noreferrer"&gt;this license&lt;/a&gt;. It features readable text, optimizes for keyboard focus, and communicates changes to all users.&lt;/p&gt;

&lt;p&gt;Although carousels are not ideal, you can still improve your site’s accessibility with them. In the below snippet, a live region is being created and then used later in the code. Doing so announces to users with visual impairments changes to the highlighted item.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
    &lt;span class="c1"&gt;// In the init function, we add a live region to announce the slide number when using the previous/next buttons&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//…… other code here&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;liveregion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;liveregion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-live&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;polite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;liveregion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-atomic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;liveregion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;liveregion visuallyhidden&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;liveregion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//…… further code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// later in the setSlides function, we decide what happens when the slide is updated&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setSlides&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//…… other code here&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;announceItem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;carousel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.liveregion&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;new_current&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; of &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;slides&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//…… further code&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Make Visual Elements Accessible
&lt;/h2&gt;

&lt;p&gt;Using only visual elements to present your product information excludes potential customers who cannot see them. Making information available to everyone is critical for accessibility. For images, that means including an &lt;a href="https://www.w3schools.com/tags/att_img_alt.asp" rel="noopener noreferrer"&gt;alt tag&lt;/a&gt;, as seen in the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"coffee-maker.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"blue coffee maker with glass mug and simple control panel"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Video presents challenges to many users. But, with the &lt;a href="https://www.vidyard.com/blog/accessible-video/" rel="noopener noreferrer"&gt;right tweaks&lt;/a&gt;., you can make them available to everyone. Here are some changes to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Captions:&lt;/strong&gt; Captions make videos easier to follow, especially for the hard of hearing. Open captions are included in the actual video, while closed captions use a separate text file for screen readers and the visually impaired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transcripts:&lt;/strong&gt; Providing a video’s full text as a &lt;a href="https://www.washington.edu/accessibility/videos/" rel="noopener noreferrer"&gt;separate transcript&lt;/a&gt; is an excellent way to increase accessibility. Transcripts also benefit those who prefer skimming through text, as opposed to a strictly visual format. Some media players, such as &lt;a href="https://ableplayer.github.io/ableplayer/" rel="noopener noreferrer"&gt;Able Player&lt;/a&gt;, automatically generate transcripts from closed captions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Audio descriptions:&lt;/strong&gt; Spoken audio describing a video helps visually impaired users understand what is happening. This can be presented as a separate, optional file or played alongside the video.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessible video players:&lt;/strong&gt; If your frontend channels utilize a video player, make these more accessible too. Look to include supporting captions and audio descriptions, allow videos to be paused, have clear controls, and use high-contrast colors.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Replace or Improve Captchas
&lt;/h2&gt;

&lt;p&gt;Captchas are designed to prevent bots and AI from accessing websites. However, AI is &lt;a href="https://security.googleblog.com/2014/12/are-you-robot-introducing-no-captcha.html" rel="noopener noreferrer"&gt;pretty good at them&lt;/a&gt;, scoring 98.4 percent on distorted text problems. In response, captchas are becoming harder, but this added complexity is causing difficulties for those with impairments.&lt;/p&gt;

&lt;p&gt;Captchas are the biggest problem &lt;a href="https://webaim.org/projects/screenreadersurvey7/" rel="noopener noreferrer"&gt;cited by screen reader users&lt;/a&gt;. Many visually impaired people cannot solve a visual captcha, leaving them unable to access the protected content. Although an &lt;a href="https://captcha.com/articles/audio-captcha.html" rel="noopener noreferrer"&gt;audio captcha&lt;/a&gt; is a good alternative, they can also have accessibility problems. Furthermore, not all systems have audio available.&lt;/p&gt;

&lt;p&gt;There are alternative ways to identify bots beyond captchas, so you can &lt;a href="https://a11y-guidelines.orange.com/en/articles/captcha-accessibility" rel="noopener noreferrer"&gt;avoid using them&lt;/a&gt; altogether. One solution is to time how long a form on your e-commerce site takes to complete. Spambots can fill and submit forms instantly. By excluding any messages completed in under ten milliseconds, you can filter most of these bots out.&lt;/p&gt;

&lt;p&gt;Another solution is to use server-side AI to analyze messages and filter IP addresses. For example, the &lt;a href="https://www.experienceux.co.uk/ux-blog/5-alternatives-to-captcha-that-wont-baffle-or-frustrate-users/" rel="noopener noreferrer"&gt;honeypot&lt;/a&gt; involves hiding a form field so users cannot see it, but spambots still attempt to fill it in. It lets you identify spambots and filter out their responses accordingly. &lt;/p&gt;

&lt;p&gt;See how to make a form field hidden:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"name_bot_trap"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not all spambots will fall for this, however. Check out other techniques &lt;a href="https://www.araweb.co.uk/Safe_Contact_Form_with_Honeypot_840" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://dev.to/felipperegazio/how-to-create-a-simple-honeypot-to-protect-your-web-forms-from-spammers--25n8"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Captchas don’t just stop bots; they prevent real people from using your site. Thus, replacing or improving captchas removes another barrier to user accessibility.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Use High-Contrast Themes
&lt;/h3&gt;

&lt;p&gt;For users with visual impairments, some visual elements don’t stand out, affecting the UI. One way to improve accessibility for color-blind users is to use contrasting colors. For instance, selecting colors &lt;a href="https://www.colormatters.com/color-and-design/basic-color-theory" rel="noopener noreferrer"&gt;on opposite sides of the color wheel&lt;/a&gt; contrasts nicely for everyone.&lt;/p&gt;

&lt;p&gt;Some users also find excess brightness difficult to look at and prefer darker themes. Thus, some sites allow users to enable Dark Mode. You can offer this with CSS and JavaScript. Browser extensions, like &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/darkreader/" rel="noopener noreferrer"&gt;Dark Reader&lt;/a&gt;, offer solutions. This &lt;a href="https://inclusive-components.design/a-theme-switcher/" rel="noopener noreferrer"&gt;extended tutorial&lt;/a&gt; explains writing a theme switcher in React.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fcqygwsbbw5l1ozvktd8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fcqygwsbbw5l1ozvktd8l.png" alt="Screenshot showing fabric’s storefront page displayed in a color blindness simulator, with controls for different types of tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are several types of color blindness, and a color scheme that works for one user may not work for another. Thus, you can also conduct testing with color-blind users. Alternatively, you can take a screenshot of your site and test it in a &lt;a href="https://www.color-blindness.com/coblis-color-blindness-simulator/" rel="noopener noreferrer"&gt;color blindness simulator&lt;/a&gt; to see how your site looks and identify any issues to fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Provide Input Assistance
&lt;/h2&gt;

&lt;p&gt;Form inputs need to be clear and understandable. They should alert users to any errors but also offer solutions. For example, making a field “required” is &lt;a href="https://a11y-101.com/development/required" rel="noopener noreferrer"&gt;impairs accessibility&lt;/a&gt;. Using an asterisk to indicate a required field confuses screen reader users, who just read out “asterisk.” If you mark a field as required in HTML, screen readers will pick up on it but still read out the asterisk.&lt;/p&gt;

&lt;p&gt;Adding the text “required” is a good compromise. You can use the &lt;code&gt;&amp;lt;aria-hidden&amp;gt;&lt;/code&gt; tag to mask the asterisk. This displays the asterisk while making sure readers ignore it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"input_four"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;First Name &lt;span class="nt"&gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;aria-hidden=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;*&lt;span class="nt"&gt;&amp;lt;/i&amp;gt;&amp;lt;i&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"visible-hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;required&lt;span class="nt"&gt;&amp;lt;/i&amp;gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"input_four"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;visible-hidden&lt;/code&gt; is a CSS class to hide the “required” text from visual rendering. See &lt;a href="https://a11y-101.com/development/skip-link" rel="noopener noreferrer"&gt;a11y-101’s approach&lt;/a&gt; to hiding text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;
&lt;span class="nc"&gt;.visible-hidden&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;white-space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;nowrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.visible-hidden&lt;/span&gt;&lt;span class="nd"&gt;:focus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;clip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although that’s a good start, older readers may not support the &lt;code&gt;&amp;lt;aria-hidden&amp;gt;&lt;/code&gt; tag. &lt;/p&gt;

&lt;p&gt;Another aspect to consider is where to place an indication of “errors” on forms. Readers should be able to find it. For example, a small line of text at the top or bottom of your form can easily be cut off from the user’s screen. Providing text that explains how to fix specific errors automatically read by screen readers is ideal. Like carousels, you should aim to prevent screen updates resetting keyboard navigation.&lt;/p&gt;

&lt;p&gt;By handling &lt;a href="https://webaim.org/techniques/formvalidation/#error" rel="noopener noreferrer"&gt;errors sensibly&lt;/a&gt;, you ensure users will continue to use your e-commerce site.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Keep Customers On-Site
&lt;/h3&gt;

&lt;p&gt;Affiliate links can confuse users by taking them away from your site to a different one. For instance, driving users to a commercially driven, flashy site can be stressful.&lt;br&gt;
To improve accessibility, ensure it’s clear &lt;a href="https://easyaffiliate.com/blog/3-ways-you-can-make-your-affiliate-program-more-accessible/" rel="noopener noreferrer"&gt;where links lead&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Those using screen readers navigate using the tab key to move around the page. They must tab through affiliate links, making this process slow. Allowing users to &lt;a href="https://www.w3schools.com/accessibility/accessibility_skip_links.php" rel="noopener noreferrer"&gt;skip links&lt;/a&gt; helps speed up the process. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://fabric.inc/xm" rel="noopener noreferrer"&gt;fabric’s Experience Manager&lt;/a&gt; lets you build a headless CMS that keeps data and backend services separate from the presentation layer. This allows you to deliver a consistent, accessible experience across multiple channels, ensuring users don’t get confused as they move between channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;In an increasingly diverse, complex e-commerce landscape, it’s more important than ever to consider the differing needs of your users. This is particularly true for the millions of users who have difficulties with site usability. Therefore, improving your site’s accessibility is essential.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fabric.inc/" rel="noopener noreferrer"&gt;fabric&lt;/a&gt; can help build an e-commerce site to meet user accessibility needs and deliver a great experience for everyone.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Scaling Multi-Channel E-Commerce with Microservices and a Headless CMS</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Fri, 30 Jul 2021 20:43:56 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/scaling-multi-channel-e-commerce-with-microservices-and-a-headless-cms-4327</link>
      <guid>https://forem.com/fabric_commerce/scaling-multi-channel-e-commerce-with-microservices-and-a-headless-cms-4327</guid>
      <description>&lt;p&gt;Having a multi-channel e-commerce solution helps you reach new customers by giving you distribution on a variety of channels. Brands and retailers can now sell through traditional catalogs and POS, online stores, third-party sellers, and even social media.&lt;/p&gt;

&lt;p&gt;From a technical perspective, supporting a multi-channel e-commerce workflow isn’t easy. Doing it well demands you take the right technical approach and design an architecture that can handle rapid change without limiting your potential for growth.&lt;/p&gt;

&lt;p&gt;Microservices, APIs, and a headless CMS can form the basis for solving this problem. In this guide, I’ll explain the benefits of using this kind of architecture, and I’ll share some examples of how such a system works in practice, with workflows and code samples.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Multi-Channel E-Commerce?
&lt;/h2&gt;

&lt;p&gt;Multi-channel e-commerce is selling your products in more than one place online. We usually think of online stores when considering e-commerce, but there are plenty of other ways to reach customers.&lt;/p&gt;

&lt;p&gt;Apps, social media, and marketplaces such as Amazon that allow third-party sellers are all good places to sell goods online. Tablets in physical locations, such as stores or trade events, are also popular.&lt;/p&gt;

&lt;p&gt;Selling in multiple channels brings new challenges. Your backend infrastructure needs to support everything it’s connected to, and your developers need to be ready to handle the extra work of building and supporting these channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Headless CMS?
&lt;/h2&gt;

&lt;p&gt;A headless CMS is a content management system that keeps the &lt;a href="https://resources.fabric.inc/blog/glossary/headless-cms" rel="noopener noreferrer"&gt;backend independent&lt;/a&gt; from frontend delivery channels.&lt;/p&gt;

&lt;p&gt;The backend makes its services available to these channels via APIs. These all use the same underlying data, so things like product or customer information can stay the same across all of them.&lt;/p&gt;

&lt;p&gt;For example, if you have a product available on both Amazon and Google Shopping, your headless API can route its pricing data from a common source like a PIM, meaning the price, product descriptions, and images are identical on both channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Microservices?
&lt;/h2&gt;

&lt;p&gt;Microservices are encapsulated services that each have their own interface. They can be updated and modified without affecting other services. If the interface stays consistent, internal changes shouldn’t affect other components.&lt;/p&gt;

&lt;p&gt;For example, if you want to upgrade the security on your orders, that’s easier if your orders are handled by a set of microservices. If you were tied into a monolith, such as Oracle ATG, you’d have to upgrade the whole platform.&lt;/p&gt;

&lt;p&gt;With microservices, each individual service can be deployed and scaled on its own container. With AWS, for example, you pay for what you use, and if one service is suddenly in demand, Amazon’s cloud can manage the upsurge without problems and without affecting the rest of your backend.&lt;/p&gt;

&lt;p&gt;That’s useful if some part of your infrastructure sees a spike in traffic. Perhaps you have a holiday product that gets mentioned in an article. A lot of people will look at your catalog. A few days later (hopefully), a lot of them will come back and buy the product. Amazon can let you ride the wave of traffic to your catalog and then handle the increased demand on your ordering system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building vs. Buying
&lt;/h2&gt;

&lt;p&gt;Once you understand the requirements of multi-channel e-commerce, it becomes clear that you need some sort of headless, API-driven solution, and microservices offer clear benefits when it comes to scaling and modifying features.&lt;/p&gt;

&lt;p&gt;The hard question is whether you should build these services yourself or use a third-party solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building multi-channel e-commerce microservices
&lt;/h3&gt;

&lt;p&gt;Here’s an example of how data might flow through a microservices-based setup, with an API gateway receiving calls and a service mesh routing calls from your checkout service to the packing and accounts services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fadm9mzkbwyvh1awy1zup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fadm9mzkbwyvh1awy1zup.png" alt="API Gateway"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To set up an architecture like this, you first need to decide what services you want it to provide and how they will connect. Once the essentials are in place, you can build from there. Let’s look at a couple of the key components you’ll need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Order management system (OMS)
&lt;/h3&gt;

&lt;p&gt;An order management system deals with taking orders and handling different payment methods, as well as updating inventory, invoicing, and passing information to your delivery and accounting teams.&lt;/p&gt;

&lt;p&gt;When an order is placed, data flows from a frontend application to your backend infrastructure, which is responsible for distributing it among the other services that need it. Your product database will be updated, as will your accounts, and the warehouse will need to know what to deliver.&lt;/p&gt;

&lt;p&gt;As orders involve the interaction of multiple services, they are a good test of your architecture, as well as being essential to get right.&lt;/p&gt;

&lt;h3&gt;
  
  
  Product information manager (PIM)
&lt;/h3&gt;

&lt;p&gt;Storing product information is a key component of any e-commerce business with large and growing volumes of data to manage. The fields and relationships between them may evolve as new sales channels provide new ways to present them.&lt;/p&gt;

&lt;p&gt;The PIM provides information on products to your customers and allows for manual updates by staff, as well as automatic updates via other services, such as inventory.&lt;/p&gt;

&lt;p&gt;With a headless architecture, you can keep all this in one place so that updates will be reflected everywhere. You can add fields and redefine existing ones as required, and also expand your range of services to support new kinds of queries.&lt;/p&gt;

&lt;h3&gt;
  
  
  API gateway and service mesh
&lt;/h3&gt;

&lt;p&gt;Another key component to this architecture is your API gateway. It routes API calls to the correct services from the various frontend channels. You can change the routing, which allows you to easily switch between different services or versions of them.&lt;/p&gt;

&lt;p&gt;For example, you could swap in a newer version of a service for testing or swap it out if you need to roll back to an earlier version. You can also route services from existing monoliths to newer microservices during a migration.&lt;/p&gt;

&lt;p&gt;A service mesh acts as an intermediary between your services and controls the data flow between them. A service mesh can handle logging, load balancing, and encryption.&lt;/p&gt;

&lt;p&gt;It can also enforce call limits on your services and provide a layer of security, letting you choose what data services are allowed to send to others. You may want to track which of your channels are calling particular services to help you identify issues or usage spikes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other services
&lt;/h3&gt;

&lt;p&gt;Aside from the core services and gateway layers, there are many other supporting services that make up a headless, e-commerce microservice platform.&lt;/p&gt;

&lt;p&gt;A personalization service can bring together the information you collect across all your channels and use it to customize the user experience on each one. A promotions and loyalty service can apply discounts to all your channels or specific ones. You could allow users to collect points or earn rewards from social media shares and then spend them on your web store, for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Processing Orders from Multiple Channels
&lt;/h2&gt;

&lt;p&gt;Let’s look at an example of how a microservice might deal with a call to its API. I’ll describe a workflow for processing orders using a prebuilt API, but if you build your own, it should be similar.&lt;/p&gt;

&lt;p&gt;When the customer has selected their items and verified their order details, the order is sent via the checkout service as a post request to the checkout endpoint.&lt;/p&gt;

&lt;p&gt;All channels can send the same request, regardless of their platform or UI. We can add or remove new channels without changing the backend, provided they send requests in the same format.&lt;/p&gt;

&lt;p&gt;The post request is sent to:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;POST /api-order/checkout&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;To send it in JQuery (assuming you have a web frontend), you can do something similar to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;$.ajax(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;contentType:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;url:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api-order-checkout"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;data:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JSON.stringify(data)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;dataType:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;success:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(data)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;formatted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;section&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;below&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;//let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;know&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;has&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;completed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;successfully&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(e)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;//let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;know&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;has&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;gone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;wrong&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request is formatted like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cartId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5f1b4158bb24210008b9a3f0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customerEmail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@fabric.inc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"customerPhoneNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"07780811973"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mobile"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"paymentDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"transactionDetails"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"paymentType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CARD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"cardNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4111111111111111"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"expDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1122"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"cvv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"999"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"cardHolderFullName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Joe Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"paymentIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"cardIdentifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1111"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"paymentMethod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Visa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"paymentKind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fabric User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"11.27"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"currency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"conversion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"billToAddress"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"last"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Demo"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"demo@fabric.inc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"07780811973"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Mobile"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"street1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"600 CONGRESS AVE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"street2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AUSTIN"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"zipCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1003"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"estimatedTax"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"itemsTaxes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"lineItemId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"lineItemId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"shipToTaxes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"shipToId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"5f1b41892e8f1c0008fc20e8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"shipFrom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"street1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"888 Broadway"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"street2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"New York"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"zipCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"46282"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API gateway will route this data to the relevant service. If the request is received and processed correctly, the backend will send a response formatted as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"checkoutComplete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4679-1016-66250"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the frontend can present a confirmation message to the user, and of course, this will vary depending on the sales channel you’re using.&lt;/p&gt;

&lt;p&gt;The backend can send further requests to other services, as determined by you and managed by your service mesh. As shown in the application diagram above, these could include calls to the shipping or promotions services, but the options are endless. To users, the interface is simple, while the backend implementation can be as complex as it needs to be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Headless, microservices-based architectures have several advantages. Their modular nature makes them easy to change and gives you the flexibility to evolve your systems over time. They are also scalable, allowing you to allocate resources efficiently as you grow.&lt;/p&gt;

&lt;p&gt;Building them yourself is time-consuming and expensive, so using a prebuilt solution can give you a headstart. These building blocks can get you up and running quickly and keep you ahead of the competition. With your architecture in place, you can add features and support new services, confident that your setup can handle their requirements.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Design Patterns for Modern Day Commerce Using Microservices</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Fri, 30 Jul 2021 20:07:33 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/design-patterns-for-modern-day-commerce-using-microservices-3fg5</link>
      <guid>https://forem.com/fabric_commerce/design-patterns-for-modern-day-commerce-using-microservices-3fg5</guid>
      <description>&lt;p&gt;E-commerce businesses are using microservices to build a set of reusable components for their stores. These services make it easier to deliver your content to multiple channels at scale by operating independently from the frontend.&lt;/p&gt;

&lt;p&gt;In this post, I’ll talk about several design patterns you can implement and explain what they offer. I’ll also mention common use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Software Design Patterns
&lt;/h2&gt;

&lt;p&gt;Software design patterns are defined ways to solve common problems. They help developers understand how the components of a system relate to each other and interact. There’s no “perfect” design pattern—each has pros and cons and is helpful in specific situations. &lt;/p&gt;

&lt;p&gt;Most developers spend years of practice getting these patterns right. However, by applying them properly, you can achieve results. There are five design patterns for modern e-commerce architectures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The strangler pattern:&lt;/strong&gt;  A useful way to migrate from legacy software to a more modern approach. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The ambassador pattern:&lt;/strong&gt; This gives you an encapsulated approach to handling network issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The sidecar pattern:&lt;/strong&gt; This helps you add functionality without getting too tightly coupled to the rest of your software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API interfaces:&lt;/strong&gt; These help software services and components communicate. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function chains:&lt;/strong&gt; These help code to handle sequential tasks. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While implementation is the most difficult part, knowing the names and intentions of each pattern is an essential first step. At the end of this guide, you will have a starting point for deciding when each is right for your e-commerce platform.&lt;/p&gt;

&lt;h3&gt;
  
  
  The strangler pattern
&lt;/h3&gt;

&lt;p&gt;Named after the &lt;a href="https://www.overops.com/blog/strangler-pattern-how-to-keep-sane-with-legacy-monolith-applications/" rel="noopener noreferrer"&gt;strangler fig tree&lt;/a&gt;, the strangler pattern is moving from one platform to another gradually. You do this by replacing parts of your software one by one until eventually the old system is fully strangled. In practice, you can break it down into &lt;a href="https://blogs.sap.com/2017/09/25/strangler-applications-monolith-to-microservices/" rel="noopener noreferrer"&gt;three steps&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transformation: you create new versions of your services, replacing them one at a time&lt;/li&gt;
&lt;li&gt;Co-existence: where you run the new services and older services together&lt;/li&gt;
&lt;li&gt;Elimination: you replace everything you need and can retire the old system &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using the strangler pattern allows continuous delivery of new features and high code coverage. It also facilitates a modular, test-driven approach enabling you to isolate issues and ensure each service you deliver works well.&lt;/p&gt;

&lt;p&gt;It’s a great way to shift to a new software setup, such as from a &lt;a href="https://resources.fabric.inc/blog/magento-to-microservices" rel="noopener noreferrer"&gt;monolith to microservices&lt;/a&gt;. It lets you break the work down into manageable chunks, driving results quickly. Furthermore, you can distribute tasks to different teams to increase buy-in and accountability across your engineering organization.&lt;/p&gt;

&lt;p&gt;On the other hand, it can take time. However, you can mitigate that by having teams work in parallel. Setting up your team right is as important as &lt;a href="https://developer.ibm.com/depmodels/microservices/articles/cl-strangler-application-pattern-microservices-apps-trs/" rel="noopener noreferrer"&gt;nailing the technical side&lt;/a&gt; of things.&lt;/p&gt;

&lt;h3&gt;
  
  
  The ambassador pattern
&lt;/h3&gt;

&lt;p&gt;In the ambassador pattern, the ‘ambassador’ service is dedicated to communication. You create a proxy process or service that handles network requests for the rest of your application. &lt;/p&gt;

&lt;p&gt;With an ambassador service in place, you can add features like monitoring, logging, and call rerouting. It’s useful to translate requests from one format to another—for example, multi-channel e-commerce, where you distribute products to many different frontend consumers. &lt;/p&gt;

&lt;p&gt;If you’re using a mix of legacy and modern software, it can help bridge the gap, ensuring your network meets modern security and accountability standards. From an organizational viewpoint, it lets you &lt;a href="https://docs.microsoft.com/en-us/azure/architecture/patterns/ambassador" rel="noopener noreferrer"&gt;assign a team&lt;/a&gt; to the proxy service itself, allowing you to divide responsibility.&lt;/p&gt;

&lt;p&gt;While the ambassador pattern can quickly tie disparate systems together, it isn’t ideal if network latency is a concern. It can increase inter-service communication and higher memory and CPU usage.&lt;/p&gt;

&lt;p&gt;If you have issues moving away from your monolith or legacy software you’re stuck maintaining, the ambassador can be a great way to circumvent those weaknesses. It allows you to add features to old software without having to rewrite everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  The sidecar pattern
&lt;/h3&gt;

&lt;p&gt;In the sidecar pattern, you move a specified set of functionality into a separate component. This component exists alongside the primary application, generally sharing the same lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fyesbuj9wwvf0svnzzv1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fyesbuj9wwvf0svnzzv1c.png" alt="diagram showing sidecar pattern. The main application and sidecar both exchange information and have access to data on the shared host. The sidecar writes to the shared data when logging.)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The sidecar is hosted together with its parent and can even run in the same process. That means there is little to no latency when the sidecar communicates with the parent, and it has access to the same resources.&lt;/p&gt;

&lt;p&gt;It can, however, use a different programming language or framework than the primary service, and multiple sidecars can use different languages. That means you can use the right tool for the job when adding extra functionality or cater to the strengths and preferences of various team members.&lt;/p&gt;

&lt;p&gt;Often the sidecar process can handle peripheral functions such as logging or network connectivity, while the main application handles core functions. Thus, if you need to move or reconfigure the application, teams can focus on the sidecar without having to change the main application.&lt;/p&gt;

&lt;p&gt;It’s a simple pattern with many potential applications. For example, in an e-commerce setting, you could use it to log financial transactions. As detailed records are vital in e-commerce, you can have an independent one to add to and build on over time.&lt;/p&gt;

&lt;p&gt;You can also use the sidecar pattern for handling network operations like adding modern encryption to a legacy service. This can let you partially modernize old e-commerce systems without resorting to a complete rewrite.&lt;/p&gt;

&lt;h3&gt;
  
  
  API interfaces
&lt;/h3&gt;

&lt;p&gt;An application programming interface, or API, is a way for software components to communicate with each other using a defined set of calls. Web services or microservices commonly use APIs. &lt;/p&gt;

&lt;p&gt;In addition to their use over networked communication, you can also use them for communication between microservices on the same host. There are several patterns commonly seen in API interfaces.&lt;/p&gt;

&lt;p&gt;REST is the most recognizable. It’s a staple of computer science courses and standard for a vast number of websites and services. It includes a set of verbs, which implement the CRUD pattern. &lt;a href="https://resources.fabric.inc/blog/rest-apis" rel="noopener noreferrer"&gt;RESTful services&lt;/a&gt; are stateless and cacheable, making them ideal for the web.&lt;/p&gt;

&lt;p&gt;In headless commerce, APIs allow multiple frontend applications to communicate with your backend services. Websites, apps, and software deployed on any other platform can send API requests to the same location. This lets you work on each component separately, making improvements and additions without worrying about the effect on the whole ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Chain
&lt;/h3&gt;

&lt;p&gt;You can build serverless functions on the cloud that are self-contained and stateless and can execute on demand. Services like Amazon Web Services, Microsoft Azure, and Google Cloud let you create these, so you don’t have to worry about hardware issues.&lt;/p&gt;

&lt;p&gt;You can organize serverless functions into a &lt;a href="https://dashbird.io/knowledge-base/well-architected/serverless-functions-composition-strategies/" rel="noopener noreferrer"&gt;function chain&lt;/a&gt;. In this pattern, each function invokes the next when it completes. This pattern is ideal if a user action kicks off a series of tasks that are slow to process. The first function can respond to the user, so they aren’t left waiting.&lt;/p&gt;

&lt;p&gt;There are a few issues to consider when applying this pattern. Ideally, functions are independent and replaceable, but here the functions are dependent on each other. This breaks object-oriented design principles, but it’s necessary for certain applications. You can use a queuing system to call the functions in sequence, making them more independently operable and scalable.&lt;/p&gt;

&lt;p&gt;Function chains are useful to implement sequential tasks that are well defined. For example, you may want to call a function chain after a user places an order to process data through different microservices and push it into each subsequent data store. &lt;/p&gt;

&lt;p&gt;These tasks can each happen independently and in the background. This way, your e-commerce store’s UI stays snappy while the backend functions might take minutes to complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;The more you know about software patterns and how to apply them to e-commerce microservices, the better you can leverage this existing knowledge to solve problems.&lt;/p&gt;

</description>
      <category>microservices</category>
    </item>
    <item>
      <title>Using the Strangler Pattern to Break Down Your E-Commerce Monolith</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Wed, 30 Jun 2021 19:24:10 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/using-the-strangler-pattern-to-break-down-your-e-commerce-monolith-aem</link>
      <guid>https://forem.com/fabric_commerce/using-the-strangler-pattern-to-break-down-your-e-commerce-monolith-aem</guid>
      <description>&lt;p&gt;Monolithic platforms like &lt;a href="https://resources.fabric.inc/blog/shopify-plus-to-microservices" rel="noopener noreferrer"&gt;Shopify&lt;/a&gt;, &lt;a href="https://resources.fabric.inc/blog/oracle-atg-to-microservices" rel="noopener noreferrer"&gt;Oracle ATG&lt;/a&gt;, and &lt;a href="https://resources.fabric.inc/blog/bigcommerce-to-microservices" rel="noopener noreferrer"&gt;BigCommerce&lt;/a&gt; are easy to get up and running. However, they lock you into various platform-specific limitations. As a result, you're subject to each platform’s constraints and may feel stuck using one-size-fits-all software.&lt;/p&gt;

&lt;p&gt;You face similar challenges if you’ve built your own e-commerce monolith. When more components of the application are intertwined, it is harder to modify features, scale components, or divide the work. After years of using one of these systems, technical debt builds up and changes are hard to implement.&lt;/p&gt;

&lt;p&gt;Microservices solve such problems. You can modularize your e-commerce business. Adapting quickly to the wealth of new opportunities to engage with your customers is a competitive advantage. That's why modern tech companies like &lt;a href="https://blog.dreamfactory.com/microservices-examples/" rel="noopener noreferrer"&gt;Netflix, Amazon, and Etsy&lt;/a&gt; have all switched to microservices.&lt;/p&gt;

&lt;p&gt;Migrating from monolith to microservices provides many technical and business challenges. One approach that helps to replace your monolith is the &lt;a href="https://martinfowler.com/bliki/StranglerFigApplication.html" rel="noopener noreferrer"&gt;strangler pattern&lt;/a&gt;. It does so one service at a time.&lt;/p&gt;

&lt;p&gt;In this post, you’ll learn how to use the strangler pattern to break down each piece of your e-commerce monolith until you’ve replaced it with discrete, scalable microservices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Microservices?
&lt;/h2&gt;

&lt;p&gt;Microservices have several advantages over a monolithic approach:&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical flexibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;One-size-fits-all platforms are fast and convenient when you get started, but as your business develops, issues start to arise. &lt;/li&gt;
&lt;li&gt;With microservices, you are free to implement the programming languages and third-party services that are best for each piece of your application. 
Because they’re scalable and modular, your decisions don’t tie you down.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Flexibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Microservices are independent and decoupled from your frontend. That means you can easily build new ways to reach your customers and wire them up to your services without having to reinvent the wheel each time. &lt;/li&gt;
&lt;li&gt;With your own services, you can ensure each service matches your needs, defining the data format, and functionality. You can also control how user access is structured. 
Flexibility also prevents bottlenecks as your teams are not &lt;a href="(https://dzone.com/articles/monolith-to-microservices-using-the-strangler-patt)"&gt;dependent&lt;/a&gt; on each other.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Attackers that &lt;a href="https://resources.fabric.inc/blog/ecommerce-security" rel="noopener noreferrer"&gt;gain access&lt;/a&gt; to your monolithic platform often gain access to &lt;em&gt;everything&lt;/em&gt; - customer, product, and order data. Microservices can create silos between services, keeping them more secure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Scalability and the ability to focus resources on your more heavily trafficked services dynamically mean you can improve performance. 
For example, Best Buy improved its catalog API &lt;a href="https://blog.runscope.com/posts/monolith-microservices-transforming-real-world-ecommerce-platform-using-strangler-pattern" rel="noopener noreferrer"&gt;sync time&lt;/a&gt; from 24 hours to under 15 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is the Strangler Pattern?
&lt;/h2&gt;

&lt;p&gt;The strangler pattern takes its name from the &lt;a href="https://en.wikipedia.org/wiki/Strangler_fig" rel="noopener noreferrer"&gt;strangler fig&lt;/a&gt; tree. Like the tree, you use your existing application as a base. Then, you build a new service that replaces one specific element of it. When it’s done you retire the old part of the application.&lt;/p&gt;

&lt;p&gt;You continue this service by service until the new microservices replace your entire monolith. You ‘strangled’ the old code and thus can abandon it completely. &lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://blogs.sap.com/2017/09/25/strangler-applications-monolith-to-microservices/" rel="noopener noreferrer"&gt;three phases in the strangler lifecycle&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Transform&lt;/strong&gt; the application by creating new versions of existing services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Co-exist&lt;/strong&gt; with the old application running alongside an ever-increasing number of microservices.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eliminate&lt;/strong&gt; the old when the new services completely replace the old system.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Strangler vs. waterfall approach
&lt;/h3&gt;

&lt;p&gt;Besides the strangler pattern there is also the waterfall replacement pattern, the more common approach to migrating microservices. The waterfall pattern requires you to commit to a long development and deployment cycle, which &lt;a href="https://insidenow.deloitte.lu/is-waterfall-only-option/article/" rel="noopener noreferrer"&gt;increases the risk of bugs and lowers your velocity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The waterfall method can take &lt;a href="https://paulhammant.com/2013/02/16/misapplying-bayes-theorem-to-agile-versus-waterfall/" rel="noopener noreferrer"&gt;well over a year to deliver results&lt;/a&gt;, but you can make progress in bursts of six months or less by using the more agile strangler method. It naturally divides work into attainable targets, which means &lt;a href="https://federalnewsnetwork.com/cloud-computing/2016/02/cloud-potential-strangle-outdated-programs-not-post/" rel="noopener noreferrer"&gt;developers are motivated&lt;/a&gt; to complete tasks that deliver visible results.&lt;/p&gt;

&lt;p&gt;With the strangler pattern, you can use each new microservice as soon as it is ready. There’s no need to build a completely new system. &lt;a href="https://www.kiuwan.com/strangle-pattern-legacy-apps/" rel="noopener noreferrer"&gt;Some recommend&lt;/a&gt; rolling out changes monthly. For one, you can enjoy the advantages quickly. Secondly, it also lets your developers move on to the next project. If issues occur, they can roll pieces of the system back more easily than the whole thing.&lt;/p&gt;

&lt;p&gt;The strangler pattern is often the better option. It allows you to migrate each piece of your infrastructure step-by-step in a manageable, low-risk way and deliver business value faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  The downside to the strangler pattern
&lt;/h3&gt;

&lt;p&gt;There are some caveats. Migrating a complete application one step takes a while. Analyzing &lt;a href="https://www.leadingagile.com/2018/10/the-urge-to-stranglethe-strangler-pattern/" rel="noopener noreferrer"&gt;successful projects&lt;/a&gt; using the strangler pattern suggests to remaining consistent and ensuring your management team commits to the long-term project.&lt;/p&gt;

&lt;p&gt;Microservices benefit from robust development practices (like continuous integration and deployment) and having engineers that are familiar with them. Finding the right team is just as important as picking the right languages and frameworks. It’s important to make sure your developers are on board with the new processe. If they understand the advantages of the changes, &lt;a href="https://hmh.engineering/why-strangler-applications-are-not-completely-mad-8835c0abd612" rel="noopener noreferrer"&gt;buy-in will be higher&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One way to mitigate the risks of migrating to microservices is to use &lt;a href="http://fabric.inc/" rel="noopener noreferrer"&gt;an established e-commerce platform like fabric&lt;/a&gt;. We've built fabric on microservices and can work with your team to ensure a smooth migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Using the Strangler Pattern in E-Commerce
&lt;/h2&gt;

&lt;p&gt;Let’s look at how to implement the strangler pattern. I use the monolith provided billing service feature and move it to a new microservice. Then, I'll show you how to migrate important data and features without breaking your existing application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Decide where to start the migration
&lt;/h3&gt;

&lt;p&gt;The service you choose to start with depends on your need and the platform you’re using. There are two common approaches. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Critical features that you need to upgrade:&lt;/strong&gt; If it's impossible to update your legacy codebase or you’re facing performance issues that cost you customers (like a slow checkout experience), starting here might be best. Ensure everything is watertight before deploying. It takes more time but has more impact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick something less critical, to test the process:&lt;/strong&gt; It's a great idea if your developers are implementing microservices for the first time as it’s less risky. However, it will drive less value for the business.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s look at moving an e-commerce billing address service from a monolithic platform like Oracle ATG to a microservice hosted on AWS. Billing services that are slow or prone to errors might be preventing you from collecting revenue from customers. Thus, they’re often mission-critical in online stores. &lt;/p&gt;

&lt;p&gt;I’ll only include a couple of attributes, but you can replicate this general pattern with whatever data you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Build a middle layer
&lt;/h3&gt;

&lt;p&gt;An API gateway can manage service calls and filter them to either your existing monolith or new services. AWS includes &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started.html" rel="noopener noreferrer"&gt;a guide&lt;/a&gt; on how to do it. A &lt;a href="https://resources.fabric.inc/blog/ecommerce-service-mesh" rel="noopener noreferrer"&gt;service mesh&lt;/a&gt; is also useful for load balancing and routing to manage data flow between your services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqdI26Z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqdI26Z3.png" alt="Diagram showing microservice architecture, with multiple services connected to a central service mesh"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the middle layer in place, you can switch between your new and old services seamlessly. You could also theoretically A/B test the old and new path or roll back if something goes wrong during the migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Build a new service and migrate data
&lt;/h3&gt;

&lt;p&gt;Next, replace the old billing portion of your application with a new microservice. Here’s some code based on this example from Amazon’s &lt;a href="https://aws.amazon.com/getting-started/hands-on/break-monolith-app-microservices-ecs-docker-ec2/module-four/" rel="noopener noreferrer"&gt;AWS documentation&lt;/a&gt; that uses EC2 and Docker to deploy a billing microservice. &lt;/p&gt;

&lt;p&gt;This task definition creates a new Docker container running on AWS to replace an Oracle ATG &lt;a href="https://docs.oracle.com/cd/E24152_01/Platform.10-1/ATGCommProgGuide/html/s2607setdefaultbillingaddresswebservi01.html" rel="noopener noreferrer"&gt;billing address service&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"containerDefinitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[billing-address-service]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[account-id].dkr.ecr.[region].amazonaws.com/[service-name]:[tag]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"memoryReservation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"cpu"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"256"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"essential"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"portMappings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"hostPort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"containerPort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"volumes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"networkMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bridge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"placementConstraints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"family"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[billing-address-service]"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;You’ll need to transfer data from your existing monolith’s database to your new microservice’s backend database in most cases. &lt;/p&gt;

&lt;p&gt;For example, the Oracle ATG billing address service described above uses profile data. You can copy this from your Oracle application’s backend to AWS, as demonstrated below.&lt;/p&gt;

&lt;p&gt;This sample code uses Amazon SQS to queue up a series of data transfer jobs. This is critical if you have lots of data to move. Because the process may take a long time, you don’t want a single failed transfer to break the whole process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SendMessageCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-sqs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-west-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//replace with your region&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="na"&gt;DelaySeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MessageAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// add other fields if you need them, remove what you don’t.&lt;/span&gt;
    &lt;span class="na"&gt;profileId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;543&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;29 Acacia Road, Springfield&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;MessageBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Clothing Store Product Data.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;QueueUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SQS_QUEUE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// your queue URL&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendMessageCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Success, product sent. MessageID:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MessageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Once you’ve queued up each row, you need a service to receive and process the data. It will add each row to your new database and delete messages from the queue as they are successfully processed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SQSClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-sqs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-west-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//replace with your region&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqsClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sqsClient&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ReceiveMessageCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;DeleteMessageCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-sqs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sqsClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./libs/sqsClient.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Set the parameters&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queueURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SQS_QUEUE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//Your queue URL&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;AttributeNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SentTimestamp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;MaxNumberOfMessages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MessageAttributeNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;All&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;QueueUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queueURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;VisibilityTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;WaitTimeSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sqsClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ReceiveMessageCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;deleteParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;QueueUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;queueURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;ReceiptHandle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;ReceiptHandle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// TODO: Save your data here&lt;/span&gt;
        &lt;span class="nx"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Then delete the queued message&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sqsClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DeleteMessageCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;deleteParams&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Message deleted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;No messages to delete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// For unit tests.&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Receive Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once your data is transferred into the new microservice, and you’ve verified it is correct, you can begin testing the new service. If everything works correctly, you can retire part of your monolith and repeat the process with each part of your application.&lt;/p&gt;

&lt;p&gt;Obviously, this migration process varies widely depending on the monolithic e-commerce platform you’re using. Still, hopefully, this gives you a sense of how you can apply the strangler pattern in your application.&lt;/p&gt;

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

&lt;p&gt;The strangler pattern can help move away from your legacy software platform in a structured, low-risk way. It helps make meaningful improvements quickly without breaking your existing e-commerce store.&lt;/p&gt;

&lt;p&gt;You can thus roll out new features and turn your platform into scalable, robust services that form the core of your e-commerce business. The decoupled nature of microservices lets you use them across multiple channels. &lt;/p&gt;

&lt;p&gt;If you’d like to avoid doing a complete migration yourself, &lt;a href="http://fabric.inc/" rel="noopener noreferrer"&gt;fabric&lt;/a&gt; can help. With industry-leading expertise in e-commerce microservices, they can help you migrate to their suite of e-commerce microservices using a secure, scalable method like the strangler pattern.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Moving from BigCommerce to Microservices-Based E-Commerce</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Fri, 25 Jun 2021 01:53:34 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/moving-from-bigcommerce-to-microservices-based-e-commerce-467j</link>
      <guid>https://forem.com/fabric_commerce/moving-from-bigcommerce-to-microservices-based-e-commerce-467j</guid>
      <description>&lt;p&gt;BigCommerce includes many features and services, but if you want to take every opportunity to engage with your customers, you need a solution of which you’re in complete control.&lt;/p&gt;

&lt;p&gt;There’s no better way to do that than replacing it with microservices. After all, this is &lt;a href="https://resources.fabric.inc/blog/answers/amazon-ecommerce-platform" rel="noopener noreferrer"&gt;the approach Amazon took&lt;/a&gt; to scale and become so successful. You can move one step at a time, adding reusable core components that act as a foundation for multiple frontend sales channels.&lt;/p&gt;

&lt;p&gt;In this post, we’ll discuss replacing BigCommerce with a microservices-based alternative, looking at the reasons for making the change. Then we'll discuss the specifics, along with a few examples of what to do code-wise. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We've written before about migrating away from &lt;a href="https://resources.fabric.inc/blog/answers/enterprise-ecommerce-platforms" rel="noopener noreferrer"&gt;classic e-commerce monoliths&lt;/a&gt; like &lt;a href="https://resources.fabric.inc/blog/salesforce-commerce-to-microservices" rel="noopener noreferrer"&gt;Salesforce Demandware&lt;/a&gt;. As you'll see, many of the same concepts and migration practices apply to modern monoliths like Shopify Plus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Microservices?
&lt;/h2&gt;

&lt;p&gt;Microservices have several advantages over a pre-built, one-size-fits-all solution. &lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Microservices are modular and interchangeable by design. That means your developers can work on them without affecting other parts of your system. It also means you can quickly make and test changes and slot in older or alternate versions of your code. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Being able to respond fast and hone in on potential problem areas are key advantages of microservices. By contrast, a large platform may take time to fix holes, and the process of upgrading might be out of your control. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Flexibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;BigCommerce offers you several templates and has plenty of features, but you are also at the mercy of any changes it makes. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;With your own microservices, you can update them when you like. You can choose the fields and data format to work with and decide how your services connect and share information. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can make every decision related to your business yourself. That may seem daunting, but specialists can help, even if you’re using your own solution.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Costs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;While BigCommerce is extendable, many of the upgrades aren’t cheap. Even one can significantly add to your costs, and the more you have, the bigger the hit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://thenewstack.io/microservices-pricing-whats-it-all-going-to-cost/" rel="noopener noreferrer"&gt;Estimates suggest&lt;/a&gt; ongoing costs for microservices can drop by up to 90%, and that’s before you factor in the productivity gains for your developers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Replacing BigCommerce
&lt;/h2&gt;

&lt;p&gt;BigCommerce’s headless architecture is ideal when shifting to microservices as you can pick and choose what you replace relatively quickly. Furthermore, by taking a modular approach and focusing on one service at a time, you can gradually transition. &lt;/p&gt;

&lt;p&gt;Moving one service at a time makes it easy to identify any issues and roll back any mistakes. If you have trouble with any of your new services, just swap the old one back in, then test and improve the new one until it does what you expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Decide where to start with the migration
&lt;/h3&gt;

&lt;p&gt;There isn’t a fixed approach to migrating from one platform to another, and you might take several valid routes. Let’s look at some of BigCommerce’s services and decide what to implement using microservices.&lt;/p&gt;

&lt;h4&gt;
  
  
  Product information management (PIM)
&lt;/h4&gt;

&lt;p&gt;Product Information Management is one of the most important tasks in e-commerce, and being able to update and access this data is crucial. BigCommerce has &lt;a href="https://www.bigcommerce.com/apps/product-information-management-pim/" rel="noopener noreferrer"&gt;several apps available&lt;/a&gt; to help with it.&lt;/p&gt;

&lt;p&gt;With microservices, though, you can customize everything from storing the data you need in the format of your choice to making it available to every channel you use. So you aren’t limited to finding the closest fit from a range of options.&lt;/p&gt;

&lt;p&gt;fabric’s &lt;a href="https://resources.fabric.inc/blog/pim-software" rel="noopener noreferrer"&gt;PIM system&lt;/a&gt; gives you a ready-made solution, allowing you to make changes using an intuitive UI and supporting features like multiple product hierarchies, auditing, and one-click migration.&lt;/p&gt;

&lt;h4&gt;
  
  
  Order management system (OMS)
&lt;/h4&gt;

&lt;p&gt;Your order management system needs to handle payments, store the user’s order, and make sure it gets dealt with. In addition, logistical issues, like stock management, need it to run flawlessly.&lt;/p&gt;

&lt;p&gt;BigCommerce has its own OMS with a &lt;a href="https://support.bigcommerce.com/s/article/Order-Management-in-BigCommerce" rel="noopener noreferrer"&gt;defined workflow&lt;/a&gt; and several extensions available in its marketplace.&lt;/p&gt;

&lt;p&gt;Your own OMS will be a crucial component of your business. It will take time to build and to get everything right. But a customized system built to your specifications can make the rest of your business run smoothly and efficiently.&lt;/p&gt;

&lt;p&gt;fabric &lt;a href="https://fabric.inc/oms" rel="noopener noreferrer"&gt;has its own OMS&lt;/a&gt;, and using this as a starting point for your system can save you a lot of time and ensure you nail the basics.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other supporting services
&lt;/h4&gt;

&lt;p&gt;PIM and OMS are essential to nearly all e-commerce businesses. The other services you pick will depend on which of BigCommerce’s capabilities you currently use and want to improve or replace. &lt;/p&gt;

&lt;p&gt;BigCommerce &lt;a href="https://www.websitebuilderexpert.com/ecommerce-website-builders/comparisons/bigcommerce-vs-shopify/" rel="noopener noreferrer"&gt;offers many features&lt;/a&gt; out of the box. You might want to replicate its customer review system or perhaps control user access for your staff.&lt;/p&gt;

&lt;p&gt;If you want to take things slowly, starting with a small, non-essential service can be a great way to get going.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Build a middle layer
&lt;/h3&gt;

&lt;p&gt;As you switch from BigCommerce to your new microservices, you need to make sure the system sends requests to the right place. You can do this with an API Gateway. &lt;a href="https://medium.com/bigcommerce-developer-blog/how-i-built-a-serverless-bigcommerce-app-on-aws-4efe21446bea" rel="noopener noreferrer"&gt;Setting one up&lt;/a&gt; lets you choose which services deal with requests, so you can pick and choose what your new services handle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqdI26Z3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FqdI26Z3.png" alt="ECommerce microservice architecture diagram, showing services surrounding central service mesh"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Swap out legacy services
&lt;/h4&gt;

&lt;p&gt;Once the middle layer is in place, you can retire old services and add your new ones. You can also swap things back and forth between new and existing services for testing or even filter requests so that some are dealt with by BigCommerce, and some go to your new setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Migrate data from BigCommerce to microservices
&lt;/h3&gt;

&lt;p&gt;When switching over, you’ll need to get your data out of BigCommerce and into your new backend database. It’s easy to export data from BigCommerce: you can &lt;a href="https://support.bigcommerce.com/s/article/Importing-Exporting-Products" rel="noopener noreferrer"&gt;generate a CSV&lt;/a&gt; file that contains everything, or you can pick and choose the fields to export.&lt;/p&gt;

&lt;p&gt;As well as getting the fields out, you need to decide on your new data structure. Will you use identical field names for the fields you want, or will you change them? You may want to allow for additional fields too.&lt;/p&gt;

&lt;p&gt;If you want to extract data from BigCommerce dynamically, you can do that &lt;a href="https://developer.bigcommerce.com/api-reference" rel="noopener noreferrer"&gt;via its APIs&lt;/a&gt;. The latest version of its REST API is three, faster and more efficient, though it doesn’t yet include everything in the older version two. &lt;/p&gt;

&lt;p&gt;There’s also a GraphQL API, though this is &lt;a href="https://developer.bigcommerce.com/api-docs/storefront/graphql/graphql-storefront-api-samples" rel="noopener noreferrer"&gt;still in early access&lt;/a&gt; and feature-incomplete. Being able to build your own full-featured API in any language is one advantage of microservices.&lt;/p&gt;

&lt;p&gt;Let’s look at the data format for &lt;a href="https://developer.bigcommerce.com/api-reference/storefront/carts/cart-items/addcartlineitem" rel="noopener noreferrer"&gt;shopping cart items&lt;/a&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;** Field Name  **&lt;/th&gt;
&lt;th&gt;** Data Type **&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customerId&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;email&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;currency&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;isTaxIncluded&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;baseAmount&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;discountAmount&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cartAmount&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;coupons&lt;/td&gt;
&lt;td&gt;array[object]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;discounts&lt;/td&gt;
&lt;td&gt;array[object]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lineItems&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdTime&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedTime&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;locale&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here’s the JavaScript for adding this code to a message queue, adapted from the &lt;a href="https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/sqs-examples-send-receive-messages.html" rel="noopener noreferrer"&gt;AWS documentation&lt;/a&gt;. You can also find code there to receive the data, which doesn’t need much adaptation.&lt;/p&gt;

&lt;p&gt;I’ve picked out a few attributes from the list above. You can add more, using the same format, or remove any you don’t want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Imports for AWS&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SendMessageCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-sqs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Set this to your region&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// The parameters, swap in what you need, and out what you don’t&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DelaySeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MessageAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;475&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;562567&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;baseAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;79.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="na"&gt;discountAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;59.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;MessageBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Shopping cart information.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;QueueUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SQS_QUEUE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Your queue URL, e.g. 'https://sqs.REGION.amazonaws.com/ACCOUNT-ID/QUEUE-NAME'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendMessageCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Success, message sent. MessageID:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MessageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Test and repeat
&lt;/h3&gt;

&lt;p&gt;As you replace each service, you should test thoroughly, making sure everything works correctly. That makes it easier to fix issues, as you can be reasonably sure that they relate to your recent changes. &lt;/p&gt;

&lt;p&gt;Once everything is working, move onto the next service and repeat the process. This iterative, step-by-step approach lets you stay focused and get the right balance between working on new services and putting them through their paces in the real world.&lt;/p&gt;

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

&lt;p&gt;Developing a new system yourself allows you to tune everything to your liking. It also lets your developers build the system the way they want and learn how it works as they put it together.&lt;/p&gt;

&lt;p&gt;Taking advantage of existing solutions like BigCommerce also has benefits. It’s cheaper, quicker and many have tested the solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://fabric.inc/" rel="noopener noreferrer"&gt;fabric&lt;/a&gt; specializes in microservices, and its solutions can help you make the switch easily. Its products are API-driven, allowing you to extend fabric core features easily and grow your services as your business expands.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Moving from Shopify Plus to Microservices-Based Commerce</title>
      <dc:creator>James Konik</dc:creator>
      <pubDate>Thu, 13 May 2021 22:01:27 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/moving-from-shopify-plus-to-microservices-based-commerce-ccd</link>
      <guid>https://forem.com/fabric_commerce/moving-from-shopify-plus-to-microservices-based-commerce-ccd</guid>
      <description>&lt;p&gt;If you’re selling products online, there’s a good chance you’re using a one-size-fits-all platform. These platforms offer many advantages but they also have limitations. If you want to move beyond these limitations, &lt;a href="https://resources.fabric.inc/blog/answers/ecommerce-microservices-architecture" rel="noopener noreferrer"&gt;microservices&lt;/a&gt; can help.&lt;/p&gt;

&lt;p&gt;Shopify Plus is a one-size-fits-all platform that allows you to use headless systems while retaining most of its features. So if you already have a Shopify Plus setup, you can keep the frontend and migrate the backend to a microservices-based alternative for more flexibility.&lt;/p&gt;

&lt;p&gt;In this post, we'll explain why businesses are moving away from monolithic e-commerce platforms like Shopify Plus and how they are doing it from a high level.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We've written before about migrating away from &lt;a href="https://resources.fabric.inc/blog/answers/enterprise-ecommerce-platforms" rel="noopener noreferrer"&gt;classic e-commerce monoliths&lt;/a&gt; like &lt;a href="https://resources.fabric.inc/blog/salesforce-commerce-to-microservices" rel="noopener noreferrer"&gt;Salesforce Demandware&lt;/a&gt;. As you'll see, many of the same concepts and migration practices apply to modern monoliths like Shopify Plus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Microservices?
&lt;/h2&gt;

&lt;p&gt;Shopify is a fantastic system in many ways, but if you use it exclusively you have to accept its limitations. Moving all or part of your system away from it can avoid these problems. Let’s look at some of the areas microservices can improve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Shopify has &lt;a href="https://techcrunch.com/2020/09/23/shopify-data-merchant-breach/" rel="noopener noreferrer"&gt;been in the news&lt;/a&gt; regarding data theft before. Managing your services means you’re free to address those concerns and implement additional security.&lt;/li&gt;
&lt;li&gt;  Its fraud protections aren’t as comprehensive as some services, so moving to a different payment system that matches your requirements can give you and your customers peace of mind.&lt;/li&gt;
&lt;li&gt;  Working with APIs means you can control the data flow in and out of your backend. It also means you can develop it incrementally while building on what you already have. That means you don’t have to reinvent the wheel when you want to offer something new on the frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technical Limitations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  One issue with Shopify Plus is its &lt;a href="https://paulnrogers.com/shopify-plus-international-multi-store/" rel="noopener noreferrer"&gt;lack of multi-store architecture&lt;/a&gt;, though this feature has been promised in the future and some plugins may help with it. If you can’t wait, you can build a backend that can handle data across all your outlets.&lt;/li&gt;
&lt;li&gt;  Shopify Plus's SEO approach is good but hard to modify. Using a custom frontend can allow you to change the URL structure, the robots.txt file, and give you better control over your subdomains.&lt;/li&gt;
&lt;li&gt;  It’s a similar situation with Shopify’s checkout. It’s hard to customize, leaving you with a fixed approach. What’s there isn’t bad; it’s just that you can’t deviate from it significantly or add specific features easily.&lt;/li&gt;
&lt;li&gt;  Shopify Plus can also slow down as you add features; its &lt;a href="https://weareuv.com/shopify-vs-salesforce-commerce-cloud-which-one-should-i-choose/" rel="noopener noreferrer"&gt;plugins don’t have to be certified&lt;/a&gt;. Handling services independently means you can ensure they continue to perform at the level you require.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Flexibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Shopify allows you to get up and running quickly, but you’re tied into the way it does things. With microservices, you can take a &lt;a href="https://resources.fabric.inc/blog/glossary/modular-commerce" rel="noopener noreferrer"&gt;modular approach&lt;/a&gt;, get the essentials in place, and add whatever you need on top.&lt;/li&gt;
&lt;li&gt;  Shopify apps aren’t always geared to work well internationally and can cost a lot if you have multiple local versions of your store. Data for multiple stores is also tricky to combine.&lt;/li&gt;
&lt;li&gt;  Shopify payments can have restrictions for products, as well as countries and currencies. You need a local business and bank account in each territory you have a store. That makes changing and expanding difficult.&lt;/li&gt;
&lt;li&gt;  With microservices, you can add an API query doing whatever it is you need—you aren’t limited to what Shopify offers. If you need to support a new feature, you can do that.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Replacing Shopify Plus
&lt;/h2&gt;

&lt;p&gt;You can take advantage of the modularity of microservices to move from Shopify bit by bit. Identify what you can benefit most from replacing and build it. If you do that repeatedly, you can move away from Shopify step by step, improving your service with minimal disruption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Decide Where to Start the Migration
&lt;/h3&gt;

&lt;p&gt;Let’s look at some of Shopify Plus’s services and decide what to implement using microservices.&lt;/p&gt;

&lt;h4&gt;
  
  
  Product Information Management (PIM)
&lt;/h4&gt;

&lt;p&gt;Your Shopify installation will include lots of product-specific data. Moving this to a separate backend, with an API letting you retrieve, modify, and create new products, is a great place to start.&lt;/p&gt;

&lt;p&gt;Decoupling this data from Shopify means you can use it on any of the new channels you create. It gives you complete control over what’s shared, and the formatting and structure can be defined however you like.&lt;/p&gt;

&lt;p&gt;Fabric has a &lt;a href="https://fabric.inc/pim" rel="noopener noreferrer"&gt;prebuilt PIM system&lt;/a&gt; that will help you make the transition quickly and easily and offers you plenty of flexibility. As well as helping you get set up, Fabric can also help with data migration.&lt;/p&gt;

&lt;h4&gt;
  
  
  Order Management System (OMS)
&lt;/h4&gt;

&lt;p&gt;Your order management system includes your user’s shopping cart as well as payments. You have to smoothly pass the data on to your payment handler and delivery setup while allowing users to track and potentially cancel the whole process. There’s a lot involved, and everything needs to run like clockwork.&lt;/p&gt;

&lt;p&gt;Taking control of this area means you can evolve it over time and perfect everything, adding features for the various frontend services you want to use while ensuring the core functionality is rock-solid.&lt;/p&gt;

&lt;p&gt;Fabric can help with this, too. Its &lt;a href="https://fabric.inc/oms" rel="noopener noreferrer"&gt;OMS&lt;/a&gt; promises a friction-free experience that can drive customer satisfaction and make life easier for everyone involved in your order and delivery chain.&lt;/p&gt;

&lt;h4&gt;
  
  
  Other Supporting Services
&lt;/h4&gt;

&lt;p&gt;Shopify Plus offers a whole suite of features and services. Some of these will matter to you more than others—priorities differ from business to business. When picking a feature to include, you should consider what you’d like to make available to channels other than Shopify and which areas have the most scope for improvement.&lt;/p&gt;

&lt;p&gt;These might include store management, customer personalization, or analytics. Take a look at the features &lt;a href="https://fabric.inc/products" rel="noopener noreferrer"&gt;Fabric offers&lt;/a&gt; to see what it can do for you in those areas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Build a Middle Layer
&lt;/h3&gt;

&lt;p&gt;To integrate your new services with your Shopify installation, you can set up an &lt;a href="https://www.shopify.com/partners/blog/shopify-webhooks-how-to-prep-your-app-this-black-friday-cyber-monday" rel="noopener noreferrer"&gt;API gateway&lt;/a&gt;. That will let you reroute requests to your new backend.&lt;/p&gt;

&lt;p&gt;You could also adopt a &lt;a href="https://resources.fabric.inc/blog/ecommerce-service-mesh" rel="noopener noreferrer"&gt;service mesh&lt;/a&gt; model, which handles communication between your application components and lets you manage data flow between your existing application and external microservices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FE-commerce%2520microservice%2520architecture%2520with%2520service%2520mesh.png%3Fwidth%3D886%26name%3DE-commerce%2520microservice%2520architecture%2520with%2520service%2520mesh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FE-commerce%2520microservice%2520architecture%2520with%2520service%2520mesh.png%3Fwidth%3D886%26name%3DE-commerce%2520microservice%2520architecture%2520with%2520service%2520mesh.png" alt="E-commerce microservice architecture with service mesh"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With a new layer in place, you can look at replacing services one by one, thoroughly testing at each stage, and ensuring the new process is fully integrated before moving on to the next.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Migrate Data from Shopify Plus to Microservices
&lt;/h3&gt;

&lt;p&gt;To move data from your old system, you can export it to a CSV file, then use JavaScript to shift it across to your new microservice. You can do this as you go, create a service, copy your data into it, and then adjust your API gateway to handle future requests from Shopify.&lt;/p&gt;

&lt;h4&gt;
  
  
  Exporting Data from Shopify Plus
&lt;/h4&gt;

&lt;p&gt;Shopify Plus has a simple export system, letting you easily create a CSV file. Its &lt;a href="https://help.shopify.com/en/manual/shopify-admin/duplicate-store" rel="noopener noreferrer"&gt;documentation explains&lt;/a&gt; how to do this for a product, customer, and order data, among other things. You can find an &lt;a href="https://help.shopify.com/en/manual/products/import-export/using-csv" rel="noopener noreferrer"&gt;example file here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Shopify product data includes the following fields:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Required but can be blank&lt;/th&gt;
&lt;th&gt;Optional&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Handle&lt;/td&gt;
&lt;td&gt;Body&lt;/td&gt;
&lt;td&gt;SEO Title&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Title&lt;/td&gt;
&lt;td&gt;Vendor&lt;/td&gt;
&lt;td&gt;SEO Description&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Published&lt;/td&gt;
&lt;td&gt;Type&lt;/td&gt;
&lt;td&gt;Google shopping metafields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Status&lt;/td&gt;
&lt;td&gt;Tags&lt;/td&gt;
&lt;td&gt;Cost per item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Image Src&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Image Position&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Image Alt Text&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;Gift Card&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There are more fields for products that have additional options and variants. &lt;a href="https://help.shopify.com/en/manual/products/import-export/using-csv" rel="noopener noreferrer"&gt;Consult the documentation for details&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Your new system won’t have to use the same fields, so you can pick and choose which are relevant to you and which, if any, are required in your system. That kind of flexibility is one of the advantages of working with microservices. You can have a compact, faster system or one that contains whatever extra information you need.&lt;/p&gt;

&lt;h4&gt;
  
  
  Importing Data into Microservices
&lt;/h4&gt;

&lt;p&gt;You can use JavaScript to transfer your data into your new system. Here’s an example showing how to import data using the latest version of &lt;a href="https://aws.amazon.com/sqs/" rel="noopener noreferrer"&gt;Amazon SQS&lt;/a&gt;. You can find more details in &lt;a href="https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/sqs-examples-send-receive-messages.html" rel="noopener noreferrer"&gt;Amazon’s documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SendMessageCommand&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-sdk/client-sqs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;//or whatever your region is&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="na"&gt;DelaySeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;MessageAttributes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Sneakers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;Vendor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;String&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Comfy Sneakers Inc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;InventoryQty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;146&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;StringValue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;79.99&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;MessageBody&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Product Data.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;QueueUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SQS_QUEUE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//replace this with your queue URL&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SQSClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;REGION&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sqs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SendMessageCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Success, product sent. MessageID:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MessageId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Test and Repeat
&lt;/h3&gt;

&lt;p&gt;As you expand your microservices and move functionality away from Shopify, it’s essential to test thoroughly. This should be done at every stage. You need to have a rigorous testing system to ensure everything is still working smoothly, including the area being moved and everything else.&lt;/p&gt;

&lt;h4&gt;
  
  
  Advantages of the Iterative Approach
&lt;/h4&gt;

&lt;p&gt;Taking a section by section approach means you can focus on a particular service and know where to look should any problems arise. That makes issues easier to fix and the overall adjustment smoother.&lt;/p&gt;

&lt;p&gt;In addition to finding errors, it’s helpful to have metrics that measure the speed of transactions. If you can connect these to sales and customer retention, all the better. &lt;/p&gt;

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

&lt;p&gt;Shopify Plus is an excellent platform with much to like about it, but the world is moving away from one-size-fits-all software toward more flexible, customized solutions.&lt;/p&gt;

&lt;p&gt;Building services yourself is very achievable, but there is plenty of support available so you don’t have to go it alone entirely. An existing solution can save you time and money, and, as these services mature, the argument for that route gets stronger.&lt;/p&gt;

&lt;p&gt;Consider taking advantage of prebuilt or customized microservices with &lt;a href="http://fabric.inc/" rel="noopener noreferrer"&gt;Fabric&lt;/a&gt; to quickly build a system that offers adaptability for new challenges and opportunities based on solid, reusable foundations.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Hybrid SQL + NoSQL E-Commerce Data Model</title>
      <dc:creator>John G</dc:creator>
      <pubDate>Tue, 20 Apr 2021 15:52:33 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/building-a-hybrid-sql-nosql-e-commerce-data-model-3fc3</link>
      <guid>https://forem.com/fabric_commerce/building-a-hybrid-sql-nosql-e-commerce-data-model-3fc3</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FFSkeOvN.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FFSkeOvN.jpg" alt="Image by Mike Petrucci"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E-commerce databases track unpredictable human actors across a complicated monetary system: at the end of the day, you want to deliver a product to a person you never see after getting a payment authorized by a third party. Processing payments, adding products, tracking orders, and handling rebates are all complicated features your e-commerce database has to handle in order to reach that goal.&lt;/p&gt;

&lt;p&gt;This article will build on previous articles, talking about a &lt;a href="https://resources.fabric.inc/blog/e-commerce-data-model" rel="noopener noreferrer"&gt;scalable SQL data model&lt;/a&gt; and a &lt;a href="https://resources.fabric.inc/blog/nosql-e-commerce-data-model" rel="noopener noreferrer"&gt;NoSQL data model&lt;/a&gt;, to show how you can build a hybrid data model. You’ll learn how to utilize the strengths of various database engines specifically to handle more complicated e-commerce interactions. &lt;/p&gt;

&lt;p&gt;Imagine a user returning one item out of a dozen that were discounted after being purchased in bulk. The user has forgotten their password, and the returned package has arrived at the wrong supplier warehouse. When this return arrives, your database model has to handle a complicated web of working relationships to put everything back in the right place. You might also need to trace the chain of events that led to this outcome so you can send the customer a satisfaction survey.&lt;/p&gt;

&lt;p&gt;This article will make a database that can shine in this situation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Modeling Your Users
&lt;/h2&gt;

&lt;p&gt;The foundation of any e-commerce site are its users. They perform every action, and each one is a complicated, out-of-your-control person. Users move, change payment methods, forget to inform the businesses they frequent, then request a refund.&lt;/p&gt;

&lt;p&gt;Fortunately, you only need to know a very fixed set of facts about users. There are rarely new types of things you need to know about people, but they are queried in a variety of ways. Some common access patterns for user data are adding new addresses or updating email addresses or passwords.&lt;/p&gt;

&lt;p&gt;Because they feature a fixed set of data with a wide variety of access patterns, user data is a great candidate for a structured SQL data store. Also, user information is one of the best sources of analytical data for your business. For example, you’re likely to want to perform ad hoc queries about the users buying your products, further cementing the suitability of SQL for your user data.&lt;/p&gt;

&lt;p&gt;The following user model implements some complicated patterns that an e-commerce site has to support, like resetting a password, adding multiple shipping and billing addresses, as well as tracking how long users spend on various pages and what they clicked to get there.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FbGaRNsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FbGaRNsc.png" alt="Users model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you’re building out your model, be aware that you don’t need to collect all the information up front. You don’t need to collect a user’s shipping or billing address when they first sign up for your application. For example, &lt;a href="https://api.fabric.inc/users/create-a-local-user" rel="noopener noreferrer"&gt;Fabric&lt;/a&gt; keeps the onboarding process simple, only asking for an email, name, and password at sign up. However, as we’ve seen in our &lt;a href="https://resources.fabric.inc/blog/bjs-wholesale-ecommerce-breakdown" rel="noopener noreferrer"&gt;e-commerce site breakdowns&lt;/a&gt;, many businesses complexify this step, making it hard for people to checkout online.&lt;/p&gt;

&lt;p&gt;Next, let’s look at what you’ll show users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Product Catalog
&lt;/h2&gt;

&lt;p&gt;A product catalog represents every item that’s available for your users to purchase: objects, subscriptions, or donation tiers. All of these options have different structures and need to keep track of slightly different things. Subscriptions have features or access levels, while objects have sizes, colors, and images. There’s a lot of flexibility and variety as to what can live in a product catalog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mixing in NoSQL
&lt;/h3&gt;

&lt;p&gt;Unlike SQL data, which is structured, normalized, and optimized to save on storage, NoSQL data is denormalized and optimized to save on CPU. This means it’s a bad choice for data analysis applications (like tracking users on a page) but a great candidate for high throughput applications when you fully understand the access patterns.&lt;/p&gt;

&lt;p&gt;NoSQL can be perfect for hosting product information. Most of the time, product information is simply displayed to a user, and the stock available might be updated if an item is purchased. NoSQL databases are great at creating instantiated views populated with data from a single round trip query.&lt;/p&gt;

&lt;p&gt;With NoSQL, your goal is to store all the data that your application uses for a page inside a single document. Here’s an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FtuRzOtw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FtuRzOtw.png" alt="A NoSQL data model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this data model, when a customer requests a product page, your application requests and receives everything it needs to render the page in a single round trip. Images, prices, options, and dimensions for every variant that a customer can inspect are all stored in a single document. This means the data layer doesn’t spend CPU time finding and mashing together various tables, making NoSQL requests very horizontally scalable.&lt;/p&gt;

&lt;p&gt;One of the other benefits of NoSQL is that data is returned in a format the web understands (JSON), which can save you the trouble of writing a custom Object Relationship Mapper (ORM) for your products.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Cache
&lt;/h2&gt;

&lt;p&gt;One of the data storage options available to developers is in-memory storage, like &lt;a href="https://redislabs.com/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;. With any caching strategy, the goal is to preserve CPU and disk I/O by moving transactions formerly performed in your data layer into faster access hardware like RAM.&lt;/p&gt;

&lt;p&gt;The features that make the product catalog a good candidate for a NoSQL data store also make it a good candidate for caching in an in-memory data store. The data is read heavy and rarely changes, so caches will save disk time while maintaining accuracy.&lt;/p&gt;

&lt;p&gt;Caching is also a good solution for session management, and in the e-commerce context, storing a user’s current cart. Rather than looking up a cookie in your database or returning all the items in their cart every time a user makes a request, you can push that workload to your caching layer and achieve a request response time that would require significantly more resources if handled by your database.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment Models
&lt;/h2&gt;

&lt;p&gt;Payment systems allow users to purchase and receive your products by linking your website to various services that enable payment. This is a vital moving part of any e-commerce website, and it has to function well to ensure customer satisfaction. A broken checkout flow is often a dealbreaker.&lt;/p&gt;

&lt;p&gt;This step also has the most stringent security requirements for what kinds of data are stored and how. In general, don’t store much credit card information, and be sure you encrypt any identifiable payment information you do save, like the card identifier. The less data your payment model stores, the better. It reduces your legal liability and helps you stay in compliance with &lt;a href="https://resources.fabric.inc/blog/ecommerce-pci-compliance" rel="noopener noreferrer"&gt;Payment Card Industry-Data Security Standards (PCI-DSS)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FEisVQzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2FEisVQzc.png" alt="Payments data model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ideal payments table does not contain much information. When a user finally clicks &lt;em&gt;Buy&lt;/em&gt; after entering their payment information, your application can mostly bypass your data layer. Instead, it will pass the request to a payment processor, which will handle it and return the result.&lt;/p&gt;

&lt;p&gt;If you think you need to store payment information for future use, your payment processor very likely has an option for storing that data and will provide you a unique, not personally identifiable token to use next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending Your Product to a Customer
&lt;/h2&gt;

&lt;p&gt;Order models are the part of your database that tracks the process of getting a product to a customer, from the moment they first express interest all the way through getting the item into their hands. An order can involve ongoing access to a website or handling a discrete event, like sending a product to a client.&lt;/p&gt;

&lt;p&gt;A smooth order flow is vital for creating a user experience that people are willing to repeat. The order is where all our other database schemas get put to use.&lt;/p&gt;

&lt;p&gt;Here’s an order for a product: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2Fen6WAVI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2Fen6WAVI.png" alt="Orders"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll notice that discount and price information have been duplicated from our NoSQL data model into the &lt;code&gt;cart_item&lt;/code&gt; table. The NoSQL model represents the discounts that are shown to a customer when they enter a page, and the saved price and discount are the discounts that were actually applied to the item.&lt;/p&gt;

&lt;p&gt;If a price or discount changes, you’ll want to be sure to keep a record of what prices were actually paid. Be aware of fault lines like this between your NoSQL and SQL components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Revisiting the initial scenario presented in this article, let’s see how the model fares all stitched together. The user has forgotten their password, but our user’s model handles updating it. The returned package has arrived at the wrong supplier warehouse, but we tracked the original source in the order, so we can forward it to the correct destination. Calculating the refund is tricky, but because we tracked discount information on an order level, we can run an ad hoc query to figure out the appropriate rebate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2F9vuynE2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgur.com%2F9vuynE2.png" alt="All the schema"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When planning your data model, remember that SQL is optimized for efficiently storing structured data and performing arbitrary queries on data, while NoSQL is optimized for efficiently delivering unstructured data.&lt;/p&gt;

&lt;p&gt;There are dozens of challenges that an e-commerce website can face that aren’t covered by this model, like &lt;a href="https://fabric.inc/subscriptions" rel="noopener noreferrer"&gt;handling subscriptions&lt;/a&gt;, applying a &lt;a href="https://fabric.inc/offers" rel="noopener noreferrer"&gt;discount to an item&lt;/a&gt; based on user behavior, and &lt;a href="https://fabric.inc/oms" rel="noopener noreferrer"&gt;tracking inventory&lt;/a&gt;. &lt;a href="https://fabric.inc/" rel="noopener noreferrer"&gt;Fabric&lt;/a&gt; has a team of experts who’ve built e-commerce data models and websites for years, offering simple solutions to these complicated problems.&lt;/p&gt;

</description>
      <category>database</category>
      <category>mongodb</category>
      <category>sql</category>
    </item>
    <item>
      <title>What’s an Example of Good E-Commerce Database Design?</title>
      <dc:creator>Shanika Wickramasinghe</dc:creator>
      <pubDate>Sun, 18 Apr 2021 18:02:06 +0000</pubDate>
      <link>https://forem.com/fabric_commerce/what-s-an-example-of-good-e-commerce-database-design-3e9l</link>
      <guid>https://forem.com/fabric_commerce/what-s-an-example-of-good-e-commerce-database-design-3e9l</guid>
      <description>&lt;h1&gt;
  
  
  What's an Example of Good E-Commerce Database Design?
&lt;/h1&gt;

&lt;p&gt;Databases are vital tools for storing, managing and retrieving information, and they are critical for building an e-commerce system. A well-structured database is the heart of a good e-commerce system that manages all the interactions of the system.&lt;/p&gt;

&lt;p&gt;A good e-commerce database design should include the following characteristics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple and Functional Database Structure&lt;/strong&gt;&lt;br&gt;
The database table structure should be relatively simple but needs to cover all the required functionality without compromising the user experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High Performance&lt;/strong&gt;&lt;br&gt;
The database queries should execute fastly and efficiently to facilitate live customer interactions and provide a satisfactory shopping experience. Therefore, the selected database should consist of good indexing and performance optimization options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High Availability and Scalability&lt;/strong&gt;&lt;br&gt;
A good database design should be highly available with automatic snapshots and enable automatic scaling to support future platform growth as well as sudden traffic spikes.&lt;/p&gt;

&lt;p&gt;Based on the above characteristics, an e-commerce database design boils down into three major aspects as the following.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; The Scope of the Database.&lt;/li&gt;
&lt;li&gt; Type of the Database.&lt;/li&gt;
&lt;li&gt; Database Infrastructure.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The scope refers to the planned functionality of the database. The underlying table structure of the database, its relationships, and indexes all depend on the functionality of the e-commerce platform. The database type can vary from a relational database to a NoSQL database or a hybrid approach depending on the requirements and the underlying data structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scope of the Database.
&lt;/h2&gt;

&lt;p&gt;The main consideration when designing the database is identifying the functionalities offered by the e-commerce platform. These functionalities can be further divided as core-functions and extra-functions (additional-functions).&lt;/p&gt;

&lt;p&gt;Core-functions are the functions that are necessary for facilitating the day-to-day operations of the e-commerce platform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  User Management&lt;/li&gt;
&lt;li&gt;  Product/Inventory Management&lt;/li&gt;
&lt;li&gt;  Shopping Cart Function &lt;/li&gt;
&lt;li&gt;  Payment Management
&lt;/li&gt;
&lt;li&gt;  Shipping/Logistics Management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Extra/Additional functions are the nice-to-have functions for the e-commerce platform that will enhance the user experience for both end-users (customers) and administrators (business). Following are some functions that come under this category.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Marketing Functions&lt;/li&gt;
&lt;li&gt;  Help Desk/Support&lt;/li&gt;
&lt;li&gt;  Advanced Analytics
&lt;/li&gt;
&lt;li&gt;  Third-Party Integrations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Database Structure for Core-Functions
&lt;/h2&gt;

&lt;p&gt;In this section, let's see how to structure the database to facilitate the core functions. The below table structure is an example of a database design that covers the core functionality of an e-commerce platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fecommerce-platform-data-1.png%3Fwidth%3D1331%26name%3Decommerce-platform-data-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fecommerce-platform-data-1.png%3Fwidth%3D1331%26name%3Decommerce-platform-data-1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This example covers all the basics of an e-commerce platform. There, the table fields and indexes depend on the design of the overall platform, and it contains three separate sections for user management, product management, and shopping process. Let's have a closer look at each section.&lt;/p&gt;

&lt;h3&gt;
  
  
  User Management
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fuser-table-ecommerce-2.png%3Fwidth%3D561%26name%3Duser-table-ecommerce-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fuser-table-ecommerce-2.png%3Fwidth%3D561%26name%3Duser-table-ecommerce-2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have created a user table that contains all the user details along with user_payment and user_address tables to store multiple addresses and payment details of users. This structure offers more granular control over data while eliminating duplicate records.&lt;/p&gt;

&lt;p&gt;Another way to manage users is by creating two separate user tables for end-users and administrators and assigning relationships according to their requirements, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fuser-administrator-ecommerce-table-3.png%3Fwidth%3D1157%26name%3Duser-administrator-ecommerce-table-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fuser-administrator-ecommerce-table-3.png%3Fwidth%3D1157%26name%3Duser-administrator-ecommerce-table-3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Product Management
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fproduct-management-ecommerce-table-4.png%3Fwidth%3D618%26name%3Dproduct-management-ecommerce-table-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fproduct-management-ecommerce-table-4.png%3Fwidth%3D618%26name%3Dproduct-management-ecommerce-table-4.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing products is not simply about maintaining a list of products. You also have to manage the inventory, discounts, categories, and other attributes of the products. So, always focus on simplifying the data structure while reducing duplicates. In the above table structure, the main product table contains information about the products.&lt;/p&gt;

&lt;p&gt;There are two other separate tables called discount, product_inventory, and product_category that are connected to it through database relationships. This approach provides the greatest level of flexibility to the database. For instance, we can simply query the product_inventory table to check for inventory without going through all the data associated with other related tables. This is also a good place to utilize indexes to increase the performance of the database.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shopping Process
&lt;/h3&gt;

&lt;p&gt;This is the most critical and complex part when it comes to designing the database. The shopping process will guide a user to search the products, add the desired products to the shopping cart, and finally complete the transaction using a payment provider.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fshopping-process-ecomerce-data-table-5.png%3Fwidth%3D1100%26name%3Dshopping-process-ecomerce-data-table-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2Fshopping-process-ecomerce-data-table-5.png%3Fwidth%3D1100%26name%3Dshopping-process-ecomerce-data-table-5.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The heart of the e-commerce process connects users with products. A good chunk of design effort should be exhausted to streamline the shopping process. In the above example, there are shopping_session and cart_item as temporary data stores that only store the shopping session information of the current user until the order is confirmed and the data is moved to permanent storage tables with the payment details. (order_details, order_items, and payment details.). You can check out this article for a detailed explanation of how to design a shopping cart database.&lt;/p&gt;

&lt;p&gt;As shown in this section, the scope of the database structure is determined by the overall functionality of the platform. Therefore, it is paramount that you properly define the required functionality before diving into designing the database. This way, you can create a clearly defined data structure with enough flexibility to support future expansions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Type of the Database
&lt;/h2&gt;

&lt;p&gt;The next consideration is to determine the type of database. To have the best e-commerce database design, you must first consider two main database types: RDBMS or NoSQL databases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relational database:&lt;/strong&gt; This is similar to spreadsheets and uses tables, columns, and rows to organize and retrieve data. It is built using the standard query language (SQL), and all the data is related to each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; MySQL, PostgreSQL, MariaDB, Microsoft SQL, Amazon RDS, Azure SQL Database&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-relational or NoSQL database:&lt;/strong&gt; This is a nontabular database with a flexible schema that works well for storing unstructured data. Contrary to its name, a non-relational database can store related data. It does so by nesting related data within a single data structure instead of splitting them between tables. There are various NoSQL databases, and the most popular ones are document stores and key stores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; MongoDB, Apache Cassandra, Amazon DynamoDB, Azure CosmosDB, Couchbase.&lt;/p&gt;

&lt;p&gt;Both these database types are solid options for any e-commerce platform, and the choice is up to the designer and depends on the requirements of the platform. A relational database will provide a simple and robust platform to create the database, while NoSQL offers better data flexibility, scalability, and slightly better performance. In the coming section, we'll explore an example of e-commerce database design for each type.&lt;/p&gt;

&lt;h3&gt;
  
  
  E-Commerce Database Design Examples
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Relational Database Design
&lt;/h4&gt;

&lt;p&gt;Many e-commerce sellers use a relational database design centered around the following tables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Products table&lt;/li&gt;
&lt;li&gt;  Customers/Users table&lt;/li&gt;
&lt;li&gt;  Orders table&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additional tables can be added as required to support shipping, categories, product reviews, etc. We have covered the database structure in the previous section, where the scope of the database was defined.&lt;/p&gt;

&lt;p&gt;Below, you can see a diagram of a simple e-commerce database design built using MySQL.&lt;/p&gt;

&lt;p&gt;MySQL e-commerce database design&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FMySQL%2520e-commerce%2520database%2520design%25206%2520.png%3Fwidth%3D753%26name%3DMySQL%2520e-commerce%2520database%2520design%25206%2520.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FMySQL%2520e-commerce%2520database%2520design%25206%2520.png%3Fwidth%3D753%26name%3DMySQL%2520e-commerce%2520database%2520design%25206%2520.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While a standard relational database design will work for many e-commerce stores, there are situations where it is advantageous for retailers to follow another approach.&lt;/p&gt;

&lt;h4&gt;
  
  
  NoSQL database design
&lt;/h4&gt;

&lt;p&gt;Most of the world's largest online retailers, including Walmart and eBay, use NoSQL databases to power their e-commerce systems. The reason is NoSQL databases providing the required performance and scalability to effectively manage large catalogs and unstructured data like user data and images.&lt;/p&gt;

&lt;p&gt;A good example of an e-commerce database built using NoSQL technology is CouchBase, which uses a document store as its database type. With a document database, data is simpler and easier to access as an entire product can be stored in a single document instead of storing across multiple tables.&lt;/p&gt;

&lt;p&gt;Below, you can see an example of data modeling for different products with CouchBase's NoSQL database.&lt;/p&gt;

&lt;p&gt;CouchBase NoSQL data structure&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FCouchBase%2520NoSQL%2520data%2520structure%25207.png%3Fwidth%3D784%26name%3DCouchBase%2520NoSQL%2520data%2520structure%25207.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FCouchBase%2520NoSQL%2520data%2520structure%25207.png%3Fwidth%3D784%26name%3DCouchBase%2520NoSQL%2520data%2520structure%25207.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://info.couchbase.com/rs/302-GJY-034/images/Database_design_retail_inventory_product_catalogs.pdf" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Hybrid Database
&lt;/h3&gt;

&lt;p&gt;Another exciting option is to use a combined solution utilizing an RDBMS for structured data such as user details, order details, payment details, and a NoSQL database for unstructured data such as product details or marketing information.&lt;/p&gt;

&lt;p&gt;Hybrid database structure&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FHybrid%2520ecommerce%2520database%2520structure%25208%2520.png%3Fwidth%3D394%26name%3DHybrid%2520ecommerce%2520database%2520structure%25208%2520.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fresources.fabric.inc%2Fhs-fs%2Fhubfs%2FHybrid%2520ecommerce%2520database%2520structure%25208%2520.png%3Fwidth%3D394%26name%3DHybrid%2520ecommerce%2520database%2520structure%25208%2520.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creating a Hybrid database structure is relatively more complex than using traditional database types (RDBMS or NoSQL) as a hybrid approach will utilize the application to combine data from both sources. This allows the developer to combine the strengths of both database types. However, this kind of approach is only suitable for truly complex application architectures that offer users a myriad of functions. For instance, if your purpose is to speed up an RDBMS, it's easier to configure a caching server such as Memcached rather than going for a hybrid approach.&lt;/p&gt;

&lt;h1&gt;
  
  
  Database Infrastructure
&lt;/h1&gt;

&lt;p&gt;It is possible to select a database type and design the data structure, but we also need infrastructure to run the database. It depends on the deployment of the e-commerce platform. One option is to provision a server, install the database software and then manage all the aspects from security to maintenance. The other option is to use a managed database service like Amazon RDS, Azure SQL for RDBMS, Amazon DynamoDB, or Azure CosmosDB for NoSQL. Among these two options, the managed approach saves time and does not require any maintenance as these are SaaS offerings.&lt;/p&gt;

&lt;p&gt;Suppose you need complete control over your data, database configurations, and server security policies or deploy the database on a private network. In that case, the only option is to configure and maintain the database manually. However, with more and more businesses utilizing cloud providers nowadays, the best option would be to use a managed database. It is more applicable for an e-commerce platform where scalability and availability play a vital role in the success of the platform. So, it's almost always advisable to use a SaaS database.&lt;/p&gt;

&lt;p&gt;A managed database will offer peace of mind for any developer as it is backed by a reputed cloud provider with a service level agreement to provide maximum uptime. It will also enable the developer/administrators to focus more on creating and optimizing the database without dealing with server or database maintenance. A slight downside of a managed platform would be the higher cost associated with it when compared to managing own servers. However, when considering the total cost of ownership (TCO) and operational expenditure (OpEx), a SaaS solution is the ideal option for a growing e-commerce database.&lt;/p&gt;

&lt;h2&gt;
  
  
  PIM Software for Multichannel Sellers
&lt;/h2&gt;

&lt;p&gt;Product Information Management (PIM) is a critical component of the core functionality of any good e-commerce platform. It provides a flexible solution for managing all your product data inside a single database in the cloud. Moreover, PIM is an excellent option for retailers looking to sell on multiple channels. Having a centralized database in the cloud, PIM allows easy management and delivery of product information to other marketplaces.&lt;/p&gt;

&lt;p&gt;Another main advantage of PIM is the ability to collect and organize data in a variety of formats. Different platforms have their own catalog structure, and PIM automatically sends data to these channels in the proper format.&lt;/p&gt;

&lt;p&gt;Fabric's PIM is one of the best examples of e-commerce database design using PIM software. It serves as a single source for centralizing all your data in the cloud, allowing businesses to benefit from increased productivity while ensuring all information is accurate and up to date across various channels.&lt;/p&gt;

</description>
      <category>ecommerce</category>
      <category>database</category>
      <category>sql</category>
      <category>nosql</category>
    </item>
  </channel>
</rss>
