{"id":10556,"date":"2021-03-02T08:00:25","date_gmt":"2021-03-02T16:00:25","guid":{"rendered":"http:\/\/softwareengineeringdaily.com\/?p=10556"},"modified":"2021-03-03T10:24:22","modified_gmt":"2021-03-03T18:24:22","slug":"is-your-microservice-a-distributed-monolith","status":"publish","type":"post","link":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/","title":{"rendered":"Is Your Microservice a Distributed Monolith?"},"content":{"rendered":"<p><span style=\"font-weight: 400;\">Your team has decided to migrate your monolithic application to a microservices architecture. You\u2019ve modularized your business logic, containerized your codebase, allowed your developers to do <\/span><a href=\"https:\/\/en.wikipedia.org\/wiki\/Polyglot_(computing)\"><span style=\"font-weight: 400;\">polyglot programming<\/span><\/a><span style=\"font-weight: 400;\">, replaced function calls with API calls, built a Kubernetes environment, and fine-tuned your deployment strategy. But soon after hitting deploy, you start noticing problems. Services take a long time to start, failures cascade from one container to the next, and small changes involve redeploying the entire application. Weren\u2019t microservices supposed to solve these problems?<\/span><\/p>\n<p><span style=\"font-weight: 400;\">If this sounds familiar, you might have fallen into a common microservice anti-pattern: the distributed monolith. In this article, we\u2019ll explain what a distributed monolith is, why you should avoid them, and how you can use <\/span><a href=\"https:\/\/www.gremlin.com\/community\/tutorials\/chaos-engineering-the-history-principles-and-practice\/\"><span style=\"font-weight: 400;\">Chaos Engineering<\/span><\/a><span style=\"font-weight: 400;\"> to validate whether your application falls under this anti-pattern.<\/span><\/p>\n<h2><b>What is a distributed monolith, and why is it bad?<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">A distributed monolith is an application that\u2019s deployed like a microservice but is built like a monolith. It leverages platforms like Kubernetes and a distributed systems architecture but isn\u2019t designed to do so efficiently or reliably.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In a monolithic architecture, the entire application is bundled into a single package that includes source code, libraries, configurations, and all other dependencies required for it to run. Monoliths aren\u2019t inherently bad, but they have limitations:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Deployment artifacts are typically large, slow to start, and use a significant chunk of resources.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Changing one part of the application means rebuilding and redeploying the entire application, slowing developer productivity.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Scaling horizontally is inefficient, as monoliths aren\u2019t inherently designed for distributed systems.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">In comparison, microservices split an application into discrete units that have clearly defined service boundaries, are less resource-intensive, and are more readily scalable. These benefits come at the cost of deployment complexity, managerial overhead, and observability challenges. Besides managing our application, we now need to manage images and containers, orchestration tools, networking and security policies, distributed data, and more.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">With a distributed monolith, we have the heaviness and inflexibility of monoliths, the complexity of microservices, and few of the benefits of either architecture. We still have slow deployments and poor scalability, but now we\u2019ve added operational complexity and removed isolation between services. Our engineers need to learn the new architecture, adopt new tooling, and rebuild their applications to tolerate the dynamic and transient world of containers, adding tons of time and labor.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">How can you tell whether your microservice is a distributed monolith, and what does this mean for your development strategy and application reliability? We\u2019ll list some common characteristics of this anti-pattern and show you how you can test for them by using Chaos Engineering.<\/span><\/p>\n<h2><b>Sign #1: Services are tightly coupled<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Coupling refers to the degree of separability between two functions. In a monolith, different functions are tightly coupled due to sharing a common code base and running within the same process space. Tight coupling can take different forms, such as:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Requiring a dependency to be available to complete a task (behavioral coupling).<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Requiring fast, low-latency communication with other services (temporal coupling).<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Having to change multiple services as a consequence of changing a single service (implementation coupling).<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Think of an e-commerce application. When a customer views a product page, we need to:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Query the database for information about the product.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Process that information on the backend.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Render it on the page.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Using a traditional monolithic application, we might create a model-view-controller (MVC) framework to logically separate our backend logic (retrieving product details) from our frontend logic (rendering the web page). These are two different functions developed by two different development teams, but they\u2019re part of the same monolithic codebase. We can\u2019t deploy or modify one without doing the same to the other.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Now let\u2019s restructure this application as a microservice. We\u2019ll create two services: one for the frontend and another for the product catalog. We\u2019ll replace direct function calls with API calls and connect the services over the network. Everything looks and works great, but then our product catalog service crashes. What happens to the frontend? Does it continue working despite the failure, or are our services so tightly coupled that the frontend also fails? If our backend team deploys a fix to the product catalog, do we also need to deploy a fix to the frontend? Most importantly, what does the customer experience when this happens?<\/span><\/p>\n<h3><b>How do you test for tight coupling?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">When testing for tight coupling, we need to determine whether changing the state of one service affects another service. To demonstrate this, we\u2019ll use an open-source microservice-based e-commerce website called <\/span><a href=\"https:\/\/github.com\/GoogleCloudPlatform\/microservices-demo\"><span style=\"font-weight: 400;\">Online Boutique<\/span><\/a><span style=\"font-weight: 400;\">. Online Boutique uses ten distinct services to provide features such as the frontend, payment processing, and shopping cart management. We want to validate whether the product catalog is decoupled from the frontend.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We\u2019ll perform this test using <\/span><a href=\"https:\/\/www.gremlin.com\"><span style=\"font-weight: 400;\">Gremlin<\/span><\/a><span style=\"font-weight: 400;\">, an enterprise SaaS Chaos Engineering platform. We\u2019ll create a chaos experiment, which is an intentional, proactive injection of harm into a working system to test its resilience with the goal of improvement. By deliberately causing failure in the product catalog service and observing the impact on the frontend, we\u2019ll know how tightly coupled or loosely coupled these services are.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Chaos experiments have four components: a hypothesis (what we think will happen during the experiment), an attack (the method of injecting harm), abort conditions (when to halt the test to avoid unintended harm), and a conclusion based on our hypothesis. Our hypothesis is this: if the product catalog is unavailable, the frontend displays an error message to the user. We\u2019ll use a <\/span><a href=\"https:\/\/www.gremlin.com\/docs\/infrastructure-layer\/attacks\/blackhole\"><span style=\"font-weight: 400;\">blackhole attack<\/span><\/a><span style=\"font-weight: 400;\"> to drop all network traffic between the frontend and product catalog services. While the attack is running, we\u2019ll refresh the web page in a browser. We\u2019ll abort the test if the website crashes or takes more than 60 seconds to load.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s run the attack in the Gremlin web app:<\/span><\/p>\n<p><img data-attachment-id=\"10561\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/gremlin_1_blackhole-productcatalog\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?fit=1736%2C1635&amp;ssl=1\" data-orig-size=\"1736,1635\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Gremlin_1_blackhole-productcatalog\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?fit=300%2C283&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?fit=1024%2C964&amp;ssl=1\" decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-10561\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?resize=500%2C471\" alt=\"\" width=\"500\" height=\"471\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?resize=300%2C283&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?resize=1024%2C964&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?resize=768%2C723&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?resize=1536%2C1447&amp;ssl=1 1536w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_1_blackhole-productcatalog.png?w=1736&amp;ssl=1 1736w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/p>\n<p><span style=\"font-weight: 400;\">When we refresh the product page, we see that it gets stuck in a loading state. Looking at the <\/span><a href=\"https:\/\/github.com\/GoogleCloudPlatform\/microservices-demo\/blob\/18a78e2817f4e3ff597fae0b3a1791aaaa1c42d9\/src\/frontend\/main.go#L268\"><span style=\"font-weight: 400;\">source code<\/span><\/a><span style=\"font-weight: 400;\"> shows a timeout period of 3 seconds, but our observations prove otherwise. We&#8217;ve just discovered an unintended temporal coupling and should focus on decoupling these services.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We can take quick steps to mitigate this by lowering the timeout threshold or by making our API calls asynchronous so that our frontend doesn\u2019t have to wait on the product catalog before responding to the user. We can reduce the risk of tight coupling in other services by using <\/span><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/architecture\/microservices\/model\/domain-analysis\"><span style=\"font-weight: 400;\">domain-driven design<\/span><\/a><span style=\"font-weight: 400;\"> (DDD) to set well-defined boundaries between microservices (known as bounded contexts). This step is best performed <\/span><i><span style=\"font-weight: 400;\">before<\/span><\/i><span style=\"font-weight: 400;\"> starting a migration to microservices, but it\u2019s still beneficial even after development has started.<\/span><\/p>\n<h2><b>Sign #2: Services don\u2019t scale easily<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Scalability is one of the most important qualities of a microservice. Being able to scale quickly and efficiently lets us handle sudden changes in demand, prevent our systems from being overloaded, and <\/span><a href=\"https:\/\/www.gremlin.com\/blog\/implementing-cost-saving-strategies-on-amazon-ec-2-with-chaos-engineering\/\"><span style=\"font-weight: 400;\">keep our operating costs low<\/span><\/a><span style=\"font-weight: 400;\">. Vertical scaling works up to a certain point, but modern cloud-native applications must also be able to scale horizontally. Cloud platforms and orchestration tools have simplified scaling, but we still need to design our applications with scalability in mind. Distributed monoliths are technically scalable, but only in very inefficient ways.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s say that our website is seeing a surge in traffic, and we need to horizontally scale our frontend to handle the increased number of connections. With a monolith, we need to deploy new instances of the full application and all of its dependencies. Not only is this process complex and prone to failure, but it takes longer and uses resources less efficiently than with a true microservice.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">When testing for a distributed monolith, we want to know how long it takes our application to scale, what the potential failure points are while scaling, and what impact this has on other services (specifically, dependencies).<\/span><\/p>\n<h3><b>How do you test for scalability?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">For this test, we\u2019ll deploy <\/span><a href=\"https:\/\/wordpress.com\/\"><span style=\"font-weight: 400;\">WordPress<\/span><\/a><span style=\"font-weight: 400;\">, an open-source CMS, to a Kubernetes cluster using the <\/span><a href=\"https:\/\/github.com\/bitnami\/charts\/tree\/master\/bitnami\/wordpress\"><span style=\"font-weight: 400;\">Bitnami Helm chart<\/span><\/a><span style=\"font-weight: 400;\">. This chart deploys the WordPress application in one Pod, and its attached MariaDB database in another Pod. We\u2019ll create <\/span><a href=\"https:\/\/kubernetes.io\/docs\/tasks\/run-application\/horizontal-pod-autoscale-walkthrough\/\"><span style=\"font-weight: 400;\">auto-scaling rules<\/span><\/a><span style=\"font-weight: 400;\"> to increase the number of WordPress Pods when CPU usage exceeds 50% utilization across the deployment:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">BASH<\/span>\r\n\r\n<span style=\"font-weight: 400;\">1helm repo <\/span><span style=\"font-weight: 400;\">add<\/span><span style=\"font-weight: 400;\"> bitnami https:\/\/charts.bitnami.com\/bitnami<\/span>\r\n\r\n<span style=\"font-weight: 400;\">2helm <\/span><span style=\"font-weight: 400;\">install<\/span><span style=\"font-weight: 400;\"> wordpress bitnami\/wordpress<\/span>\r\n\r\n<span style=\"font-weight: 400;\">3kubectl autoscale deployment wordpress --cpu-percent<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">50<\/span><span style=\"font-weight: 400;\"> --min<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\"> --max<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">10<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">Note that this only scales the WordPress application, not MariaDB. This means that all of our newly-provisioned Pods will attach to the same data store. When testing scalability, we want to see:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Whether our application can scale and load balance traffic reliably.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">How long it takes for the new Pod to get up and running.<\/span><\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><span style=\"font-weight: 400;\">Whether MariaDB acts as a bottleneck.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">We\u2019ll do this by using a <\/span><a href=\"https:\/\/www.gremlin.com\/docs\/infrastructure-layer\/attacks\/cpu\"><span style=\"font-weight: 400;\">CPU attack<\/span><\/a><span style=\"font-weight: 400;\"> to increase CPU usage on the deployment. We\u2019ll set our target utilization to 60% while monitoring the state of the deployment using <\/span><span style=\"font-weight: 400;\">kubectl<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">BASH<\/span>\r\n\r\n<span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">watch<\/span><span style=\"font-weight: 400;\"> -n <\/span><span style=\"font-weight: 400;\">1<\/span> <span style=\"font-weight: 400;\">'kubectl get hpa wordpress'<\/span>\r\n\r\n<span style=\"font-weight: 400;\">2<\/span>\r\n\r\n\r\n\r\n<span style=\"font-weight: 400;\">3NAME\u00a0 \u00a0 \u00a0 \u00a0 REFERENCE\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 TARGETS \u00a0 \u00a0 \u00a0 \u00a0 MINPODS \u00a0 MAXPODS \u00a0 REPLICAS \u00a0 AGE<\/span>\r\n\r\n<span style=\"font-weight: 400;\">4wordpress \u00a0 Deployment\/wordpress \u00a0 <\/span><span style=\"font-weight: 400;\">&lt;<\/span><span style=\"font-weight: 400;\">unknown<\/span><span style=\"font-weight: 400;\">&gt;<\/span><span style=\"font-weight: 400;\">\/50% \u00a0 <\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\"> \u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">10<\/span><span style=\"font-weight: 400;\"> \u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">1<\/span><span style=\"font-weight: 400;\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3m54s<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">Note how long it takes for the new Pods to deploy. Once traffic is load balanced to the new Pods, monitor the amount of load on your database. Is there a significant enough increase to where you need to scale up your database as well? If so, you may have a distributed monolith.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">This is a useful experiment regardless of whether you think your application is a monolith as it can help you <\/span><a href=\"https:\/\/www.gremlin.com\/webinars\/preparing-for-traffic-spikes-with-chaos-engineering\/\"><span style=\"font-weight: 400;\">prepare for traffic spikes<\/span><\/a><span style=\"font-weight: 400;\"> and maintain high rates of throughput during unexpected load.<\/span><\/p>\n<h2><b>Sign #3: Services are overly chatty<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Sharing data between distributed systems is challenging due to the added latency of network calls. In a monolith, data can flow between functions nearly instantaneously. But in a microservice, extensive communication between services will significantly reduce the application\u2019s throughput, possibly causing timeouts and other unexpected failures.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For example, WordPress uses a MySQL (or MariaDB) database to store data such as user accounts, page contents, configuration settings, and much more. A single page load can generate multiple MySQL queries. As such, WordPress works best with a low-latency (ideally local) database connection, but this creates a temporal dependency between the two services.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In Kubernetes, one option is to deploy WordPress and MySQL together in the same Pod. But this creates a Pod that serves multiple functions, requires significant system resources, has a longer startup time, requires data replication and synchronization, and is owned by both the application and database team. In other words, it&#8217;s a monolith packaged as a microservice.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Networking two services might not seem like a problem until our network becomes saturated or degraded. With Chaos Engineering, we can see the impact that this might have on our application.<\/span><\/p>\n<h3><b>How do you test for chatty services?<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Imagine that a network error is adding 20 ms of delay to all network traffic in our environment. This doesn\u2019t seem like much, and a well-architected microservice should be able to tolerate this with only a minor increase in response time.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Using Gremlin, we\u2019ll use a <\/span><a href=\"https:\/\/www.gremlin.com\/docs\/infrastructure-layer\/attacks\/latency\"><span style=\"font-weight: 400;\">latency attack<\/span><\/a><span style=\"font-weight: 400;\"> to add 20 ms of latency between our WordPress Pod and its MySQL Pod. We\u2019ll use <\/span><a href=\"https:\/\/httpd.apache.org\/docs\/current\/programs\/ab.html\"><span style=\"font-weight: 400;\">Apache Bench<\/span><\/a><span style=\"font-weight: 400;\"> to benchmark response times before and during the attack.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">First, let\u2019s get our baseline metrics before running the attack. We see that each request takes roughly 128 ms to complete:<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">BASH<\/span>\r\n\r\n<span style=\"font-weight: 400;\">1$ ab -t <\/span><span style=\"font-weight: 400;\">30<\/span><span style=\"font-weight: 400;\"> http:\/\/kubernetes-cluster:30003\/<\/span>\r\n\r\n<span style=\"font-weight: 400;\">2Requests per second:\u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">7.78<\/span><span style=\"font-weight: 400;\"> [<\/span><span style=\"font-weight: 400;\">#\/sec] (mean)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">3Time per request: \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">128.549<\/span><span style=\"font-weight: 400;\"> [ms] (mean)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">4Time per request: \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">128.549<\/span><span style=\"font-weight: 400;\"> [ms] (mean, across all concurrent requests)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">5Transfer rate:\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">197.97<\/span><span style=\"font-weight: 400;\"> [Kbytes\/sec] received<\/span>\r\n\r\n<\/pre>\n<p><span style=\"font-weight: 400;\">Now, let\u2019s run the attack. Once the attack enters the Running state, we\u2019ll re-run the benchmark:<\/span><\/p>\n<p><img data-attachment-id=\"10565\" data-permalink=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/gremlin_2_attack-results\/\" data-orig-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?fit=1839%2C1824&amp;ssl=1\" data-orig-size=\"1839,1824\" data-comments-opened=\"0\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"Gremlin_2_attack-results\" data-image-description=\"\" data-image-caption=\"\" data-medium-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?fit=300%2C298&amp;ssl=1\" data-large-file=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?fit=1024%2C1016&amp;ssl=1\" decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-10565\" src=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=500%2C496\" alt=\"\" width=\"500\" height=\"496\" srcset=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=300%2C298&amp;ssl=1 300w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=1024%2C1016&amp;ssl=1 1024w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=768%2C762&amp;ssl=1 768w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=1536%2C1523&amp;ssl=1 1536w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?resize=174%2C174&amp;ssl=1 174w, https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Gremlin_2_attack-results.png?w=1839&amp;ssl=1 1839w\" sizes=\"(max-width: 500px) 100vw, 500px\" data-recalc-dims=\"1\" \/><\/p>\n<pre><span style=\"font-weight: 400;\">BASH<\/span>\r\n\r\n<span style=\"font-weight: 400;\">1$ ab -t <\/span><span style=\"font-weight: 400;\">30<\/span><span style=\"font-weight: 400;\"> http:\/\/kubernetes-cluster:30003\/<\/span>\r\n\r\n<span style=\"font-weight: 400;\">2Requests per second:\u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">1.39<\/span><span style=\"font-weight: 400;\"> [<\/span><span style=\"font-weight: 400;\">#\/sec] (mean)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">3Time per request: \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">718.532<\/span><span style=\"font-weight: 400;\"> [ms] (mean)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">4Time per request: \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">718.532<\/span><span style=\"font-weight: 400;\"> [ms] (mean, across all concurrent requests)<\/span>\r\n\r\n<span style=\"font-weight: 400;\">5Transfer rate:\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <\/span><span style=\"font-weight: 400;\">35.42<\/span><span style=\"font-weight: 400;\"> [Kbytes\/sec] received<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">Just 20 ms of additional latency caused a 5.5x increase in response time, an 82% decrease in transfer rate, and a noticeable delay for users. Almost anything could cause a similar outcome in the real world, from network saturation to a faulty switch to Kubernetes scheduling the MySQL Pod on another node. Imagine if we had a 40 ms delay, or a 100 ms delay!<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To mitigate the effect of latency, reduce the number of round-trip network calls between services. Consider making calls asynchronous, or using a message queue like Apache Kafka to decouple these services. As with tight coupling, this is another good example of why you should use <\/span><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/architecture\/microservices\/model\/domain-analysis\"><span style=\"font-weight: 400;\">domain-driven design<\/span><\/a><span style=\"font-weight: 400;\"> to split your services and data into different domains.<\/span><\/p>\n<h2><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Moving to microservices involves more than just repackaging monolithic applications into containers. There are fundamental differences in architecture that affect everything from how we transfer data to how we recover from failures. Failing to account for these differences can lead to restricted scalability, diminished performance, and unexpected outages.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To determine whether your application is a distributed monolith, <\/span><a href=\"https:\/\/www.gremlin.com\/gremlin-free-software\/\"><span style=\"font-weight: 400;\">sign up for a Gremlin Free<\/span><\/a><span style=\"font-weight: 400;\"> account and start running experiments on your applications within minutes. Use the CPU attack to test your application\u2019s ability to auto-scale, or use a shutdown attack to test for tight coupling between services.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Your team has decided to migrate your monolithic application to a microservices architecture. You\u2019ve modularized your business logic, containerized your codebase, allowed your developers to do polyglot programming, replaced function calls with API calls, built a Kubernetes environment, and fine-tuned your deployment strategy. But soon after hitting deploy, you start noticing problems. Services take a<\/p>\n","protected":false},"author":9,"featured_media":10557,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_newsletter_tier_id":0,"footnotes":"","jetpack_publicize_message":"Is Your Microservice a Distributed Monolith? by Andre Newman @GremlinInc @8bit_buddhist","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[1363,83,2143],"tags":[4445,4447,4446,1849,20,4448],"jetpack_publicize_connections":[],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.4 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Is Your Microservice a Distributed Monolith? - Software Engineering Daily<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Is Your Microservice a Distributed Monolith? - Software Engineering Daily\" \/>\n<meta property=\"og:description\" content=\"Your team has decided to migrate your monolithic application to a microservices architecture. You\u2019ve modularized your business logic, containerized your codebase, allowed your developers to do polyglot programming, replaced function calls with API calls, built a Kubernetes environment, and fine-tuned your deployment strategy. But soon after hitting deploy, you start noticing problems. Services take a\" \/>\n<meta property=\"og:url\" content=\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\" \/>\n<meta property=\"og:site_name\" content=\"Software Engineering Daily\" \/>\n<meta property=\"article:published_time\" content=\"2021-03-02T16:00:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-03T18:24:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Hero_Copy.png?fit=2400%2C1256&ssl=1\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1256\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Abdallah Abu-Ghazaleh\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@software_daily\" \/>\n<meta name=\"twitter:site\" content=\"@software_daily\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Abdallah Abu-Ghazaleh\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\"},\"author\":{\"name\":\"Abdallah Abu-Ghazaleh\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/2946bffdbf2f7790ff2411cf5de7b8e3\"},\"headline\":\"Is Your Microservice a Distributed Monolith?\",\"datePublished\":\"2021-03-02T16:00:25+00:00\",\"dateModified\":\"2021-03-03T18:24:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\"},\"wordCount\":2092,\"publisher\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\"},\"keywords\":[\"Andre Newman\",\"CPU attack\",\"distributed monolith\",\"Gremlin\",\"microservices\",\"shutdown attack\"],\"articleSection\":[\"All Content\",\"Exclusive Articles\",\"Exclusive Content\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\",\"url\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\",\"name\":\"Is Your Microservice a Distributed Monolith? - Software Engineering Daily\",\"isPartOf\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#website\"},\"datePublished\":\"2021-03-02T16:00:25+00:00\",\"dateModified\":\"2021-03-03T18:24:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/softwareengineeringdaily.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Is Your Microservice a Distributed Monolith?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#website\",\"url\":\"https:\/\/softwareengineeringdaily.com\/\",\"name\":\"Software Engineering Daily\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/softwareengineeringdaily.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#organization\",\"name\":\"Software Engineering Daily\",\"url\":\"https:\/\/softwareengineeringdaily.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2022\/01\/cropped-logo-new.png?fit=296%2C139&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2022\/01\/cropped-logo-new.png?fit=296%2C139&ssl=1\",\"width\":296,\"height\":139,\"caption\":\"Software Engineering Daily\"},\"image\":{\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/twitter.com\/software_daily\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/2946bffdbf2f7790ff2411cf5de7b8e3\",\"name\":\"Abdallah Abu-Ghazaleh\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9a20991954278e570b94734af55dfd38?s=96&d=retro&r=pg\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9a20991954278e570b94734af55dfd38?s=96&d=retro&r=pg\",\"caption\":\"Abdallah Abu-Ghazaleh\"},\"sameAs\":[\"http:\/\/GhazStation.com\"],\"url\":\"https:\/\/softwareengineeringdaily.com\/author\/abdallah\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Is Your Microservice a Distributed Monolith? - Software Engineering Daily","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/","og_locale":"en_US","og_type":"article","og_title":"Is Your Microservice a Distributed Monolith? - Software Engineering Daily","og_description":"Your team has decided to migrate your monolithic application to a microservices architecture. You\u2019ve modularized your business logic, containerized your codebase, allowed your developers to do polyglot programming, replaced function calls with API calls, built a Kubernetes environment, and fine-tuned your deployment strategy. But soon after hitting deploy, you start noticing problems. Services take a","og_url":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/","og_site_name":"Software Engineering Daily","article_published_time":"2021-03-02T16:00:25+00:00","article_modified_time":"2021-03-03T18:24:22+00:00","og_image":[{"width":2400,"height":1256,"url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Hero_Copy.png?fit=2400%2C1256&ssl=1","type":"image\/png"}],"author":"Abdallah Abu-Ghazaleh","twitter_card":"summary_large_image","twitter_creator":"@software_daily","twitter_site":"@software_daily","twitter_misc":{"Written by":"Abdallah Abu-Ghazaleh","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#article","isPartOf":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/"},"author":{"name":"Abdallah Abu-Ghazaleh","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/2946bffdbf2f7790ff2411cf5de7b8e3"},"headline":"Is Your Microservice a Distributed Monolith?","datePublished":"2021-03-02T16:00:25+00:00","dateModified":"2021-03-03T18:24:22+00:00","mainEntityOfPage":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/"},"wordCount":2092,"publisher":{"@id":"https:\/\/softwareengineeringdaily.com\/#organization"},"keywords":["Andre Newman","CPU attack","distributed monolith","Gremlin","microservices","shutdown attack"],"articleSection":["All Content","Exclusive Articles","Exclusive Content"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/","url":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/","name":"Is Your Microservice a Distributed Monolith? - Software Engineering Daily","isPartOf":{"@id":"https:\/\/softwareengineeringdaily.com\/#website"},"datePublished":"2021-03-02T16:00:25+00:00","dateModified":"2021-03-03T18:24:22+00:00","breadcrumb":{"@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/softwareengineeringdaily.com\/2021\/03\/02\/is-your-microservice-a-distributed-monolith\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/softwareengineeringdaily.com\/"},{"@type":"ListItem","position":2,"name":"Is Your Microservice a Distributed Monolith?"}]},{"@type":"WebSite","@id":"https:\/\/softwareengineeringdaily.com\/#website","url":"https:\/\/softwareengineeringdaily.com\/","name":"Software Engineering Daily","description":"","publisher":{"@id":"https:\/\/softwareengineeringdaily.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/softwareengineeringdaily.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/softwareengineeringdaily.com\/#organization","name":"Software Engineering Daily","url":"https:\/\/softwareengineeringdaily.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2022\/01\/cropped-logo-new.png?fit=296%2C139&ssl=1","contentUrl":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2022\/01\/cropped-logo-new.png?fit=296%2C139&ssl=1","width":296,"height":139,"caption":"Software Engineering Daily"},"image":{"@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/twitter.com\/software_daily"]},{"@type":"Person","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/2946bffdbf2f7790ff2411cf5de7b8e3","name":"Abdallah Abu-Ghazaleh","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/softwareengineeringdaily.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9a20991954278e570b94734af55dfd38?s=96&d=retro&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9a20991954278e570b94734af55dfd38?s=96&d=retro&r=pg","caption":"Abdallah Abu-Ghazaleh"},"sameAs":["http:\/\/GhazStation.com"],"url":"https:\/\/softwareengineeringdaily.com\/author\/abdallah\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/softwareengineeringdaily.com\/wp-content\/uploads\/2021\/03\/Hero_Copy.png?fit=2400%2C1256&ssl=1","jetpack_shortlink":"https:\/\/wp.me\/p7GuoD-2Kg","_links":{"self":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts\/10556"}],"collection":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/users\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/comments?post=10556"}],"version-history":[{"count":0,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/posts\/10556\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/media\/10557"}],"wp:attachment":[{"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/media?parent=10556"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/categories?post=10556"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/softwareengineeringdaily.com\/wp-json\/wp\/v2\/tags?post=10556"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}