{"id":26938745,"url":"https://github.com/saadaouialaeddine/ecommerce-cloud-platform","last_synced_at":"2026-05-03T16:31:31.407Z","repository":{"id":275863494,"uuid":"927429191","full_name":"SaadaouiAlaeddine/ecommerce-cloud-platform","owner":"SaadaouiAlaeddine","description":"A Repo for a Smart AI-based Order Management Platform Prototype","archived":false,"fork":false,"pushed_at":"2025-03-31T23:56:16.000Z","size":96,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"dev","last_synced_at":"2025-04-01T00:28:57.056Z","etag":null,"topics":["ai","consul","kafka","keycloak","kubernetes","prototype","python","security","spark","streaming","vae-pytorch","vault"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SaadaouiAlaeddine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-04T23:58:12.000Z","updated_at":"2025-03-31T23:56:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"3ebfb385-e550-4854-a185-b403770241d7","html_url":"https://github.com/SaadaouiAlaeddine/ecommerce-cloud-platform","commit_stats":null,"previous_names":["saadaouialaeddine/ecommerce-cloud-platform"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SaadaouiAlaeddine%2Fecommerce-cloud-platform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SaadaouiAlaeddine%2Fecommerce-cloud-platform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SaadaouiAlaeddine%2Fecommerce-cloud-platform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SaadaouiAlaeddine%2Fecommerce-cloud-platform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SaadaouiAlaeddine","download_url":"https://codeload.github.com/SaadaouiAlaeddine/ecommerce-cloud-platform/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246828507,"owners_count":20840474,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","consul","kafka","keycloak","kubernetes","prototype","python","security","spark","streaming","vae-pytorch","vault"],"created_at":"2025-04-02T14:13:43.704Z","updated_at":"2026-05-03T16:31:31.361Z","avatar_url":"https://github.com/SaadaouiAlaeddine.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Smart AI-based Order Management Platform\n\nThis project is a prototype using Kubernetes as platform to integrate and orchestrate all the required components to speed up order processing and filter orders for validations using AI jobs.\n## Architecture\nThe Lucidchart diagram is a high level picture of the different Kubernetes components organised by namespaces to separate concerns, management and enable required network policies and RBAC roles\n- [@Lucidchart Diagram](https://lucid.app/publicSegments/view/dea8c52d-a918-4d66-a2ba-acd018dfdea7/image.jpeg) \u003cbr/\u003e\nClick on the image to open it in new tab and zoom in\n![ecommerce diagram (2)](https://github.com/user-attachments/assets/8bd35352-e029-483e-b139-d5e4127e047a)\n## Installation\n**k is an alias for kubectl**\u003cbr/\u003e\n1) **install kind:**\u003cbr/\u003e\n   kind create cluster --config /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/kind/clusters-def.yaml\n2) **install metallb**\u003cbr/\u003e\n  k create namespacemetallb-system\u003cbr/\u003e \n  helm install metallb metallb/metallb -n metallb-system\u003cbr/\u003e \n  **use the range from this output:**\u003cbr/\u003e\n  docker network inspect kind | grep Subnet\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/metallb/metallb-config.yaml\u003cbr/\u003e\n  **verify installation**\u003cbr/\u003e\n  kubectl get ipaddresspool -n metallb-system\u003cbr/\u003e\n  kubectl get l2advertisement -n metallb-system\u003cbr/\u003e\n3) **install nginx**\n  k create namespace nginx\u003cbr/\u003e\n  k create deployment nginx --image=nginx -n nginx\u003cbr/\u003e\n  kubectl expose deployment nginx --type=LoadBalancer --port=80 --target-port=80 -n nginx\u003cbr/\u003e\n\n4) **install prometheus + grafana**\n  k create namespace prometheus\u003cbr/\u003e\n  helm install prometheus prometheus-community/kube-prometheus-stack --namespace prometheus --set prometheus.prometheusSpec.service.type=LoadBalancer\u003cbr/\u003e\n  k patch svc prometheus-kube-prometheus-prometheus -n prometheus --type='json' -p '[{\"op\": \"replace\", \"path\": \"/spec/type\", \"value\": \"LoadBalancer\"}]'\u003cbr/\u003e\n\n5) **install  rabbitmq**\u003cbr/\u003e\n  helm install my-rabbitmq bitnami/rabbitmq \\                                                                                                      \n    --set persistence.existingClaim=rabbitmq-pvc \\\n    --set persistence.size=1Gi \\\n    --set auth.username=admin \\\n    --set auth.password=adminpassword \\\n    --set service.type=LoadBalancer \\\n    --set metrics.enabled=true \\\n    --set metrics.serviceMonitor.enabled=true \\\n    -n rabbitmq\n\n6) **install cert-manager**\u003cbr/\u003e\nhelm install cert-manager jetstack/cert-manager \\\n  --namespace cert-manager \\\n  --create-namespace \\\n  --set installCRDs=true\n\n7) **install consul**\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/consul/pv.yaml   \n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/consul/pvc.yaml  \n  helm upgrade --install consul hashicorp/consul -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/consul/values.yaml -n consul \n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/consul/consul-mesh-gateway.yaml \n\n8) **install mongo**\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/mongodb\n  kubectl exec -it mongodb-0 -n mongo -- mongosh\n  rs.reconfig({\n    _id: \"rs0\",\n    members: [\n      { _id: 0, host: \"192.168.97.206:27017\" },\n      { _id: 1, host: \"192.168.97.207:27017\" }\n    ]\n  }, {force: true})\n\n9) **install postgres**\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/postgres\n\n10) **install vault**\u003cbr/\u003e\n  helm install vault hashicorp/vault \\\n    --namespace vault \\\n    --set \"server.service.type=LoadBalancer\" \\\n    --set \"server.ha.enabled=false\" \\\n    --set \"server.ha.raft.enabled=false\" \\\n    --set \"server.dataStorage.enabled=true\" \\\n    --set \"server.dataStorage.size=1Gi\" \\\n    --set \"server.dataStorage.storageClass=standard\" \\\n    --set \"server.dataStorage.persistentVolumeReclaimPolicy=Delete\"\n  k cp key1.asc vault-0:/tmp/key1.asc -n vault\n  k exec -it vault-0 -n vault -- vault operator init -key-shares=1 -key-threshold=1 -pgp-keys=\"/tmp/key1.asc\"\n  echo \"encrypted unsealed key \" | base64 --decode | keybase pgp decrypt\n  update the bach file with VAULT_TOKEN and VAULT_ADDR\n  vault operator unseal unseal_key\n\n11) **install registry**\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/registry\n\n12) **install redis**\u003cbr/\u003e\n  k apply -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/redis/redis-deployment.yaml\n\n13) **install kafka**\u003cbr/\u003e\n   helm install kafka bitnami/kafka --namespace kafka \\\n    --set persistence.enabled=true \\\n    --set persistence.size=1Gi \\\n    --set persistence.storageClass=manual \\\n    --set replicaCount=1 \\\n    --set service.type=LoadBalancer \\\n    --set externalAccess.enabled=true \\\n    --set externalAccess.service.type=LoadBalancer \\\n    --set externalAccess.service.port=9094 \\\n    --set externalAccess.autoDiscovery.enabled=true \\\n    --set rbac.create=true \\\n    --set controller.automountServiceAccountToken=true \\\n    --set broker.automountServiceAccountToken=true\n  **install kafka ui:**\u003cbr/\u003e\n  docker compose up -d path-to-file\n\n14) **install spark**\u003cbr/\u003e\n  helm install spark bitnami/spark --set service.type=LoadBalancer --namespace spark                   \n  k edit statefulset spark-worker -n spark to increase cores, mem….\n  retrieve the password: \"$(kubectl get secret kafka-user-passwords --namespace kafka -o jsonpath='{.data.client-passwords}' | base64 -d | cut -d , -f 1)\";\n\n15) **install keycloak**\u003cbr/\u003e\n  helm install keycloak bitnami/keycloak -f /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/keycloak/values.yaml -n keycloak\n  get user passsword: kubectl get secret --namespace keycloak keycloak -o jsonpath=\"{.data.admin-password}\" | base64 --decode\n  postgress passwords: kubectl get secret keycloak-postgresql -n keycloak -o yaml\n\n16) **install install airflow**\u003cbr/\u003e\n  helm install airflow apache-airflow/airflow \\\n    --namespace airflow \\\n    --values /Users/alaeddinesaadaoui/PycharmProjects/ecommerce-cloud-platform/config/airflow/values.yaml\n## Components\n\n### $${\\color{red}Consul}$$ \u003cbr/\u003e\n- Consul is deployed to enable service discoverability\n\u003cimg width=\"1231\" alt=\"Screenshot 2025-03-19 at 7 37 27 AM\" src=\"https://github.com/user-attachments/assets/ea7ef003-e50b-49b0-bdc6-2c31554ca0a3\" /\u003e\u003cbr/\u003e\n- Intentions are created to define access between microservices\n\u003cimg width=\"1237\" alt=\"Screenshot 2025-03-19 at 7 42 23 AM\" src=\"https://github.com/user-attachments/assets/f18b2221-c65b-430d-916b-2e661b176080\" /\u003e\n\n### $${\\color{red}Keycloak}$$ \u003cbr/\u003e\n- Keycloak is installed to define an identity layer for microservices to enable authentication and authorization features\n\u003cimg width=\"1249\" alt=\"Screenshot 2025-03-19 at 8 09 41 AM\" src=\"https://github.com/user-attachments/assets/b6e069a6-5ddf-40ed-8d3a-b19146f776c1\" /\u003e\n\u003cimg width=\"1046\" alt=\"Screenshot 2025-03-19 at 8 09 49 AM\" src=\"https://github.com/user-attachments/assets/e838bd33-dbfc-445e-b1aa-812185d4a440\" /\u003e\u003cbr/\u003e\n\n- Scopes are required to define the required jwt entries, in this case the audience and roles are required to connect later on with vault\n\u003cimg width=\"1255\" alt=\"Screenshot 2025-03-19 at 8 10 18 AM\" src=\"https://github.com/user-attachments/assets/0005ab62-f14f-45d9-a792-d8a146313557\" /\u003e\n\u003cimg width=\"1271\" alt=\"Screenshot 2025-03-19 at 8 10 30 AM\" src=\"https://github.com/user-attachments/assets/3995d5a2-fd62-4f1c-8a5e-7d0f09311d1e\" /\u003e\u003cbr/\u003e\n\n- Realm Roles with associated Client Roles are required to define the resource_access section in jwt\n\u003cimg width=\"1271\" alt=\"Screenshot 2025-03-19 at 8 10 56 AM\" src=\"https://github.com/user-attachments/assets/5e5295ec-a2b7-4eae-b897-0fa58d4f0827\" /\u003e\n\u003cimg width=\"1258\" alt=\"Screenshot 2025-03-19 at 8 11 04 AM\" src=\"https://github.com/user-attachments/assets/ff0a8b1d-8763-4abc-b488-5cc5036c827c\" /\u003e\u003cbr/\u003e\n\n- The generated JWT contains the client scope and access_token using the client's credentials\n\u003cimg width=\"936\" alt=\"Screenshot 2025-03-19 at 8 12 10 AM\" src=\"https://github.com/user-attachments/assets/252f98c1-4c7b-4f3b-977b-a1a12a21fbaa\" /\u003e\u003cbr/\u003e\n\n- The decoded access token contains aud, resources_access and scope entries passed to vault to access microservice secrets\n\u003cimg width=\"579\" alt=\"Screenshot 2025-03-19 at 10 15 32 AM\" src=\"https://github.com/user-attachments/assets/90156fbf-f839-4a58-b21d-3c9d5b410b72\" /\u003e\u003cbr/\u003e\n\n- The generated JWT is signed using R256 algorithm, the kid entry will be used to fetch the public key from the keycloak certification entries\u003cbr/\u003e\n\u003cimg width=\"569\" alt=\"Screenshot 2025-03-19 at 10 16 11 AM\" src=\"https://github.com/user-attachments/assets/fd894148-612d-4584-ac14-8d29efa61038\" /\u003e\u003cbr/\u003e\n\n- To enable JWT signature, a provided was added to the Keycloak realm with a generated certificate and private key\n\u003cimg width=\"1254\" alt=\"Screenshot 2025-03-19 at 8 24 52 AM\" src=\"https://github.com/user-attachments/assets/db8d0831-4103-4e41-baeb-7ec3aa1743dd\" /\u003e\u003cbr/\u003e\n\n- Using the same certificate and private key, we can verify the signature of JWT using jwt.io\n\u003cimg width=\"1224\" alt=\"Screenshot 2025-03-19 at 8 27 12 AM\" src=\"https://github.com/user-attachments/assets/7b95fa7b-3510-4100-95f8-1afd811f74ee\" /\u003e\u003cbr/\u003e\n\n- At the code level, the kid entry will be used to fetch the public key from the Keycloak certs page\n\u003cimg width=\"565\" alt=\"Screenshot 2025-03-19 at 8 40 43 AM\" src=\"https://github.com/user-attachments/assets/32c3f2ce-6c35-4fd1-92f7-720e1ca54fdf\" /\u003e\n\u003cimg width=\"1559\" alt=\"Screenshot 2025-03-19 at 8 43 13 AM\" src=\"https://github.com/user-attachments/assets/84cea0b6-2662-429e-a1d0-af8d1f6558e7\" /\u003e\u003cbr/\u003e\n\n### $${\\color{red}Vault}$$ \u003cbr/\u003e\n- Vault is deployed to store the microservices secrets. Kubernetes allows the secrets creation and encoding using Base64 but it doesn't secure it.\n\u003cimg width=\"1093\" alt=\"Screenshot 2025-03-19 at 3 10 35 PM\" src=\"https://github.com/user-attachments/assets/21a5c8c9-8623-4305-928d-ad4b2678e7c4\" /\u003e\u003cbr/\u003e\n- To use Keycloak as identity provider, JWT is enabled in vault and JWT Authentication Method is defined using Keycloak\n\u003cimg width=\"726\" alt=\"Screenshot 2025-03-19 at 3 14 29 PM\" src=\"https://github.com/user-attachments/assets/ad0df7c0-fa95-48bf-a7c8-041f6c79b26d\" /\u003e\u003cbr/\u003e\n- A role is created to connect to vault using the JWT of the Keycloak client\n\u003cimg width=\"1292\" alt=\"Screenshot 2025-03-19 at 3 15 58 PM\" src=\"https://github.com/user-attachments/assets/79f172fb-8f73-40d6-8815-11362b28abce\" /\u003e\u003cbr/\u003e\n- To enable the secrets access, the Vault policy vault-reader-scope is need to be created\u003cbr/\u003e\n\u003cimg width=\"358\" alt=\"Screenshot 2025-03-19 at 3 18 51 PM\" src=\"https://github.com/user-attachments/assets/898a2268-9d09-4421-a490-2e3bcc59e507\" /\u003e\u003cbr/\u003e\n- At the code level, post request will be made to /v1/auth/jwt/login using the role name and the Keycloak JAWT to retrieve client token to access the microservice secretrs\u003cbr/\u003e\n\u003cimg width=\"924\" alt=\"Screenshot 2025-03-19 at 3 22 24 PM\" src=\"https://github.com/user-attachments/assets/efa37a91-cf56-4b7c-9a8e-6a71164fc52c\" /\u003e\u003cbr/\u003e\n\n### $${\\color{red}Rabbitmq}$$ \u003cbr/\u003e\n- RabbitMQ is deployed to create the required exchanges and queues for orders processing.\n\u003cimg width=\"1484\" alt=\"Screenshot 2025-03-19 at 3 29 26 PM\" src=\"https://github.com/user-attachments/assets/96bc0809-ecea-438e-923f-40dda2272cf3\" /\u003e\u003cbr/\u003e\n- To simplify the messages flows, all the orders will be sent to a central exchange: order-exchange. Three queues and one exchange are bound to order-exchange\n\u003cimg width=\"1514\" alt=\"Screenshot 2025-03-19 at 3 32 33 PM\" src=\"https://github.com/user-attachments/assets/d49957fe-7535-49d3-8c1d-1ed1d04084cb\" /\u003e\n- The created queues are durable and priority-orders queue is a priority queue to prioritize the incoming orders based on their priority values\n\u003cimg width=\"1014\" alt=\"Screenshot 2025-03-19 at 3 36 15 PM\" src=\"https://github.com/user-attachments/assets/cb19a84d-8e57-4189-9ef2-ac761ec9e457\" /\u003e\n- The digital orders are separated and have their own exchange\n\u003cimg width=\"951\" alt=\"Screenshot 2025-03-19 at 3 37 08 PM\" src=\"https://github.com/user-attachments/assets/2cde25d1-e75b-4d42-98e9-15f00c70b415\" /\u003e\n\n### $${\\color{red}MongoDB}$$ \u003cbr/\u003e\n- The regular orders come in different formats with different user/product attributes. So for fast storage and post-processing, a Mongo database will be used for storage. To enable Kafka streaming, replication has to be enabled. So the Mongo database is created with two replicas.\n\u003cimg width=\"690\" alt=\"Screenshot 2025-03-19 at 4 00 26 PM\" src=\"https://github.com/user-attachments/assets/19b3987b-ef2e-48c4-a23b-672bcc0c884f\" /\u003e\n\n### $${\\color{red}Kafka}$$ \u003cbr/\u003e\nKafka is deployed to enable realtime validation and processing of regular orders. The orders-topics will be a bridge between Mongo orders database and Spark jobs.\n\u003cimg width=\"1355\" alt=\"Screenshot 2025-03-19 at 4 24 38 PM\" src=\"https://github.com/user-attachments/assets/51d5c2ee-4138-45b2-899b-90ce9b7adbef\" /\u003e\u003cbr/\u003e\n\n### $${\\color{red} API Authorization}$$ \u003cbr/\u003e\n- To validate the jwt used for all the sensitive incomning requests, a decorator pattern is used to call a validation function validate_jwt. \u003cbr/\u003e\n\u003cimg width=\"664\" alt=\"Screenshot 2025-03-31 at 4 09 24 PM\" src=\"https://github.com/user-attachments/assets/8f096400-f93b-468b-92ad-474a89072309\" /\u003e\u003cbr/\u003e\n\n- The validation function will fetch the authorization token to validate it. In case there is any issue, an error is raised.\u003cbr/\u003e\n\u003cimg width=\"588\" alt=\"Screenshot 2025-03-31 at 4 09 43 PM\" src=\"https://github.com/user-attachments/assets/b19e211d-6633-4f66-b11c-022bb8a8f0f5\" /\u003e\u003cbr/\u003e\n\n- For non sensitive calls like healthcheck requests, the decorator is not used\u003cbr/\u003e\n\u003cimg width=\"672\" alt=\"Screenshot 2025-03-31 at 4 09 17 PM\" src=\"https://github.com/user-attachments/assets/4ab49b33-c4b5-471e-93f2-572529701558\" /\u003e\u003cbr/\u003e\n\n- To automate token generation for test calls using postman, a pre-request script is added to generate the token and update the dev environment variable.\u003cbr/\u003e\n\u003cimg width=\"1297\" alt=\"Screenshot 2025-03-31 at 4 54 39 PM\" src=\"https://github.com/user-attachments/assets/3c3c3bec-ff47-497c-b8f4-eb3135f2dfd3\" /\u003e\u003cbr/\u003e\n\n### $${\\color{red} Blue/Green Deployment}$$ \u003cbr/\u003e\n\n- To enable B/G deployment, a second kind cluster is created with consul deployed and a mesh-gateway enabled.\u003cbr/\u003e\n\u003cimg width=\"1164\" alt=\"Screenshot 2025-04-01 at 12 31 52 PM\" src=\"https://github.com/user-attachments/assets/8c88b2cf-2fd5-4d90-9fd7-26aff705c3ec\" /\u003e\n\n- A peering connection should be established between the two clusters\n\u003cimg width=\"1165\" alt=\"Screenshot 2025-04-01 at 12 12 52 PM\" src=\"https://github.com/user-attachments/assets/42cadf6b-e584-4517-aa8b-18340dbc2c65\" /\u003e\n\n\n- The service should be exported in the second cluster with indicating the main cluster(dc2) as a consumer.\u003cbr/\u003e\n\u003cimg width=\"499\" alt=\"Screenshot 2025-04-01 at 12 25 39 PM\" src=\"https://github.com/user-attachments/assets/b78b6449-1209-43dd-88c9-381be0283950\" /\u003e\u003cbr/\u003e\n\u003cimg width=\"1148\" alt=\"Screenshot 2025-04-01 at 12 39 19 PM\" src=\"https://github.com/user-attachments/assets/9dc18504-6524-4186-85e5-4304968547c8\" /\u003e\u003cbr/\u003e\n\n- On the main cluster (dc2) side, the peer (dc1) and the imported service should be shown.\u003cbr/\u003e\n\u003cimg width=\"1166\" alt=\"Screenshot 2025-04-01 at 12 13 09 PM\" src=\"https://github.com/user-attachments/assets/9ad0257a-da51-4504-89ab-f55197669440\" /\u003e\u003cbr/\u003e\n\n- Now, we can see the two instances of the stock-service. The instance deployed in the main cluster and the exported instance from the peer cluster.\u003cbr/\u003e\n\u003cimg width=\"1152\" alt=\"Screenshot 2025-04-01 at 12 13 31 PM\" src=\"https://github.com/user-attachments/assets/b61daffb-075f-4328-b58c-b710d557eab3\" /\u003e\u003cbr/\u003e\n\n- A failover should be enabled from the main cluster with the peer cluster (dc1) as a failover target.\u003cbr/\u003e\n\u003cimg width=\"472\" alt=\"Screenshot 2025-04-01 at 12 25 10 PM\" src=\"https://github.com/user-attachments/assets/848821c8-0f23-4acb-8cdb-f559d6bd8cf1\" /\u003e\u003cbr/\u003e\n\n- Finally, to get a fully functional B/G deployment. All the services should be deployed in both clusters and the previous steps should be implemented symmetrically on both sides.\u003cbr/\u003e\n\n## Authors\n\n- [@alaeddine saadaoui](https://github.com/SaadaouiAlaeddine)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaadaouialaeddine%2Fecommerce-cloud-platform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsaadaouialaeddine%2Fecommerce-cloud-platform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsaadaouialaeddine%2Fecommerce-cloud-platform/lists"}