commerscury-logocommerscury-logo
commerscury-logo

The premier community platform for Magento professionals worldwide.

links

  • Questions
  • Articles
  • Leaderboard
  • Category

Platform sections

  • About Us
  • Contact Us
  • FAQ

legal pages

  • Privacy Policy
  • Terms of Service
  • Code of Conduct
  • Cookie Policy

© 2024 Commerscury. Built with ❤️ for the Magento community.

TagsSavedUsers
Question

Magento 2 SSO Login: “login\_redirect” cookie created on first login, forcing repeated login on checkout

I’m integrating a custom SAML-based SSO module wit...

magento2
php
single-sign-on
magento-cli
magento-2-api
1
0
20
Abelardo Harvey
AH
Abelardo H .
05/11/2025

Magento 2 error Current version of RDBMS is not supported. Used Version: 10.1.37-MariaDB. Supported versions: MySQL-8, MySQL-5.7, MariaDB-(10.2-10.4)

✓

I am running a magento 2.4 project but current not...

magento2
graphql
authentication
rest-api
webhooks
19
5
26934
Clement Fadel
CF
Clement F .
06/11/2025

Magento 2.4.2 with Zookeeper lock provider throws ZookeeperNoNodeException(code: -101): no node

We recently switched the lock provider in our Mage...

magento2
magento
docker
apache-zookeeper
php-zookeeper
0
0
14
Janelle Haag
JH
Janelle H .
08/11/2025

How to setup Magento 2 store Switcher?

I want to setup website features for multiple stor...

magento2
magento
graphql
authentication
rest-api
webhooks
1
1
10194
Beryl Predovic
BP
Beryl P .
07/11/2025

Magento - Get Custom Option Value details from Option Value ID

✓

I have some intriguing questions related to Custom...

php
magento
graphql
authentication
rest-api
webhooks
15
4
48064
Marjorie Wilderman
MW
Marjorie W .
06/11/2025

Magento calling a block with getChildHtml

Please follow the code bellow, which is taken from...

magento
graphql
layout
block
authentication
rest-api
webhooks
6
3
16665
Zelda Glover-Breitenberg
ZG
Zelda G .
07/11/2025

Installing Magento 2 after installing Composer: Vendor Autoload Error

I am trying to install Magento 2 multistore and I ...

php
magento
composer-php
redis
varnish
indexing
indexer
cron
1
1
9657
Trace Thiel
TT
Trace T .
07/11/2025

how to get pub/static/frontend/Magento/luma/en\_US/Namespace\_Module/images/image.png

How to get this path? `pub/static/frontend/Magento...

php
graphql
magento2.2
authentication
rest-api
webhooks
-1
2
592
Brock Hagenes
BH
Brock H .
05/11/2025

Magento: The 'community' channel is not installed

I was trying to install a made-by-myself extension...

magento
docker
async
deployment
devops
1
2
865
Lucienne Feeney
LF
Lucienne F .
05/11/2025

Magento 2.4.7 : "An error occurred on the server. Please try to place the order again" while placing the order

I need your help with an issue I'm facing in Magen...

checkout
magento
payment-gateway
magento2.4
nginx
0
0
96
Blaze Kuhlman-Abshire
BK
Blaze K .
07/11/2025

Articles

Need Of Magento Upgrade Service To Do The Smooth Process Of Upgradation

Need Of Magento Upgrade Service To Do The Smooth Process Of Upgradation

Looking for a Magento upgrade service that can introduce new features to your existing store and enhance its performance by increasing customer engagement and boosting sales compared to previous data? Here, you will experience a seamless upgrade process to the latest Magento version. Store owners are usually aware of the improvements they can expect from an upgrade based on their past experiences. With each upgrade, they observe the new features and identify which issues from the current version will be resolved in the next release. To eliminate bugs and problems present in the current version, it is essential to upgrade to the latest Magento version with the assistance of a professional Magento upgrade service provider. There are always significant benefits after upgrading to the latest version. ## Why Choose a Magento Upgrade Service Provider? To upgrade your Magento store effectively, you need to engage a [Magento Upgrade Service](url) provider. Attempting to upgrade on your own can be challenging without in-depth technical knowledge of the Magento platform. Most store owners lack the technical expertise required for a smooth upgrade, which is why they prefer to work with a Magento service provider. These professionals simplify the upgrade process and offer tailored recommendations after thoroughly analyzing your store. Experts understand how to leverage Magento’s features to maximize your store’s performance and output. ## Benefits of Upgrading Magento - **Improved Performance:** Upgrading ensures your store runs faster and more efficiently. - **Enhanced Security:** Latest versions come with critical security patches to protect your store and customer data. - **New Features:** Access to new functionalities that can improve user experience and increase sales. - **Bug Fixes:** Resolution of issues present in previous versions, leading to a more stable store. - **Better Compatibility:** Support for the latest extensions and integrations. ## Conclusion Upgrading your Magento store is a crucial step to stay competitive and provide an excellent shopping experience. Partnering with a reliable Magento upgrade service provider ensures a smooth transition to the latest version, unlocking new features and improving overall store performance.

How to Create a Custom Magento 2 API?

How to Create a Custom Magento 2 API?

Magento 2 is a powerful e-commerce platform with comprehensive API support. While it provides default REST APIs, there are cases where you may need to create a custom REST API. This article guides you through the process of creating a custom REST API in Magento 2. ## What is a Magento 2 Custom REST API? A Custom REST API in Magento 2 is a web service endpoint that you develop to perform specific actions or retrieve particular data from your Magento store. These custom APIs are designed to meet your unique business requirements. They facilitate integration between Magento and external systems, mobile applications, or other software solutions. Custom APIs become essential when the default Magento APIs do not cover certain functionalities or data access needs. **Common Scenarios for Creating a Custom REST API in Magento 2:** - **Integrating with Third-party Systems:** Custom APIs enable seamless data exchange with external platforms such as ERP systems, CRM software, or payment gateways. - **Building Mobile Applications:** These APIs provide the necessary endpoints for mobile apps to interact with your Magento store. - **Implementing Unique Features:** Custom APIs support specialized functionalities like custom loyalty programs or personalized product recommendation engines. ## Steps to Create a Custom Magento 2 REST API ### Step 1: Set Up Your Development Environment Ensure you have a Magento 2 development environment ready. You will also need a code editor and a REST client (such as Postman) to test your API. ### Step 2: Define Your API Endpoints Identify the functionality you want to expose via the API. For this example, we will create an API endpoint to retrieve product details by SKU. ### Step 3: Create a Module Create a custom module to house your API. Replace `Vendor` and `Module` with your own namespace and module names. Create **_app/code/Vendor/Module/etc/module.xml_** with the following content: ```xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Module" setup_version="1.0.0" /> </config> ``` Create **_app/code/Vendor/Module/registration.php_** with the following content: ```php <?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_Module', __DIR__ ); ``` ### Step 4: Create a Web API Schema Define the API endpoint in a `webapi.xml` file. Create **_app/code/Vendor/Module/etc/webapi.xml_** with the following content: ```xml <?xml version="1.0"?> <routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd"> <route method="GET" url="/V1/custom/product/:sku"> <service class="Vendor\Module\Api\ProductInterface" method="getProductBySku"/> <resources> <resource ref="anonymous"/> </resources> </route> </routes> ``` ### Step 5: Create a Dependency Injection Configuration Specify the implementation class for your API interface in a `di.xml` file. Create **_app/code/Vendor/Module/etc/di.xml_** with the following content: ```xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Vendor\Module\Api\ProductInterface" type="Vendor\Module\Model\Product"/> </config> ``` ### Step 6: Create the API Interface Define the interface that declares the methods your API will expose. Create **_app/code/Vendor/Module/Api/ProductInterface.php_** with the following content: ```php <?php namespace Vendor\Module\Api; interface ProductInterface { /** * Retrieve product details by SKU * * @param string $sku * @return \Magento\Catalog\Api\Data\ProductInterface * @throws \Magento\Framework\Exception\NoSuchEntityException If the product with the specified SKU does not exist. */ public function getProductBySku($sku); } ``` ### Step 7: Implement the API Interface Create the class that implements your API interface. Create **_app/code/Vendor/Module/Model/Product.php_** with the following content: ```php <?php namespace Vendor\Module\Model; use Vendor\Module\Api\ProductInterface; use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Framework\Exception\NoSuchEntityException; class Product implements ProductInterface { /** * @var ProductRepositoryInterface */ protected $productRepository; public function __construct( ProductRepositoryInterface $productRepository ) { $this->productRepository = $productRepository; } /** * {@inheritdoc} */ public function getProductBySku($sku) { try { $product = $this->productRepository->get($sku); return $product; } catch (NoSuchEntityException $e) { throw new NoSuchEntityException(__('Product with SKU %1 not found.', $sku)); } } } ``` ### Step 8: Test Your Custom API You can now test your custom API using a REST client like Postman. Make a GET request to the following endpoint: ``` [YourMagentoURL]/rest/V1/custom/product/{SKU} ``` Replace `{SKU}` with the SKU of the product you want to retrieve. You should receive a JSON response containing the product details. --- _**Note:** This article references content from https://meetanshi.com/blog/create-custom-rest-api-in-magento-2/. It may include excerpts from the original author._ If you have any questions or need further clarification, please feel free to leave a comment.

Magento 2 Extensions

Magento 2 Extensions

Do you want to improve the checkout process for your ecommerce store? If so, you should explore our new **_[Magento 2 extensions](https://www.milople.com/magento-2-extensions)_**! These extensions simplify the way your customers enter their payment information and complete their purchase journey. ## What is a Magento 2 Extension? A Magento 2 extension is a modular add-on that enhances the functionality and features of a Magento 2 ecommerce online store. Magento 2 is a widely-used open-source e-commerce platform, and extensions enable users to customize and extend their online stores to meet specific business needs. Typically developed by third-party developers, Magento 2 extensions can be installed on a Magento 2 store to add new features, improve performance, or integrate with external services. ## Benefits Our Magento 2 extension offers several advantages, including: - Reducing the number of steps required in the checkout process - Simplifying the entry of payment information for customers - Enhancing the overall checkout experience for your customers ## Why Choose Magento 2 Extensions? Magento 2 extensions provide flexibility and scalability, allowing your store to adapt as your business grows. They help streamline operations, improve user experience, and can be tailored to fit unique business requirements without extensive custom development. ## How to Install and Use Installing Magento 2 extensions is straightforward. After purchasing or downloading the extension, you can upload it to your Magento 2 store via the admin panel or command line. Once installed, configure the extension settings to align with your store’s checkout process and preferences.

Adobe Commerce CLI commands - or how to create a problem out of nothing

Adobe Commerce CLI commands - or how to create a problem out of nothing

### Table Of Contents - [Intro](#intro) - [The Underlying Problem & Its Roots](#the-underlying-problem--its-roots) - [The Classic "Chicken or the Egg" Dilemma](#the-classic-chicken-or-the-egg-dilemma) - [The Pitfall of CLI Command Constructors](#the-pitfall-of-cli-command-constructors) - [Strategies to Prevent These Errors](#strategies-to-prevent-these-errors) - [Simplify with Automated Proxy Injection](#simplify-with-automated-proxy-injection) - [Summary](#summary) ## Intro Hello everyone, In this article, I'll share practical examples illustrating how unexpected challenges can arise in Magento 2 & Adobe Commerce projects when building or using custom CLI commands from third parties. This issue becomes especially critical when working with CI/CD pipelines, project setups, and test executions. Our main focus will be the "hero" of this article: [ISSUE: magento setup command is throwing magento.flag doesn't exist](https://github.com/alankent/magento2devbox-skeleton/issues/4). We'll explore this issue in depth, understand its origins, and discuss ways to resolve it. **Disclaimer:** _A quick note on terminology — this article covers both Adobe Commerce and Magento 2. After all, Adobe Commerce is Magento. Long Live Magento!_ 😁 ## The Underlying Problem & Its Roots While working on various Magento 2 projects, I often encountered issues when performing a `clean` setup using a freshly created database. This typically occurs during integration or functional test setups in pipelines and local environments. However, this problem is not limited to those scenarios; it can also arise during upgrades, migrations, or deployments. The usual suspects? Here are two common errors you might recognize: ```error The default website isn't defined. Set the website and try again. ``` For Commerce editions, you might also see: ```error SQLSTATE[42S02]: Base table or view not found: 1146 Table 'magento2.flag' doesn't exist, query was: SELECT flag.* FROM flag WHERE (flag.flag_code='staging') ``` When these errors appear during the execution of `php bin/magento setup:install`, they provide little insight into the real cause. After hours of frustrating investigation, you'll find these errors stem from premature access to the database resource, which triggers the initialization of configuration and state entities from the Magento database. Here’s the catch: you cannot fetch data from the database at this point because the tables don’t exist yet. They are created and populated during the installation process, not before. ¯\_(ツ)_/¯ ## The Classic "Chicken or the Egg" Dilemma We’re stuck in a circular problem: trying to install the system but being blocked because it’s not installed yet. Confusing, right? 🤪 This happens because some part of the code is prematurely calling the database connection resource. This should be obvious, and I hope you’ll appreciate this insight as much as Sam Elliott would. ![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t77vk8glx0375v3ge19x.png) This **"someone"** is typically inside `bin/magento` and should be called only after the actual command execution begins. Usually, CLI command constructors are the culprits. Let me explain why. ## The Pitfall of CLI Command Constructors For clarity, consider this code example: ```php class DoSmthing { private ?string $dummyConfigValue; public function __construct(ScopeConfigInterface $storeManager) { $this->dummyConfigValue = $storeManager->getValue('some/dummy/path', ScopeInterface::SCOPE_STORE); } public function getValue(): ?string { return $this->dummyConfigValue; } } class DummyCommand extends Command { ... public function __construct(DoSmthing $model, string $name = null) { $this->model = $model; parent::__construct($name); } ... } ``` The root cause lies in the constructors of both the command and model classes. In the `DoSmthing` class, the constructor attempts to retrieve a config value. This triggers calls to the `store`, `store_website`, and `core_config_data` tables when creating the `DummyCommand` object. And what happens if this code runs before those tables exist? Exactly — errors! #### Let’s recap once more: 1. We execute `php bin/magento setup:install`. 2. The `bin/magento` application creates instances of all CLI commands. 3. The `DummyCommand` instance depends on the `DoSmthing` model, so `DoSmthing` must be instantiated first. 4. The application creates the `DoSmthing` model and executes its `__construct` method. 5. The constructor calls the config manager. 6. The config manager queries tables that are not yet created. 7. **ERROR** ## Strategies to Prevent These Errors Keep this golden rule in mind: every CLI command class is initialized every time you invoke `php bin/magento`. Here’s how to avoid future headaches: ### Rule 1 - Be Wise Avoid calling potentially resource-intensive operations like database or API calls inside `__construct` methods of CLI command classes. These operations will run every time, even if you only want to list available commands. ### Rule 2 - Be Ready Avoid accessing resources in `__construct` that might not be available during runtime, especially since Magento tables don’t exist during `setup:install`. ### Rule 3 - Fix The Problem If you don’t control the problematic code, inject a `Proxy` using dependency injection (DI) configuration. For example, to fix the issue with `DummyCommand`, add the following to `di.xml`: ```xml <type name="AbcTest\DummyConsoleCommand\Console\Command\DummyCommand"> <arguments> <argument name="model" xsi:type="object">\AbcTest\DummyConsoleCommand\Model\DoSmthing\Proxy</argument> </arguments> </type> ``` The Proxy pattern is widely used in Magento to defer object instantiation until it’s actually needed. In this example, the `DoSmthing` object won’t be created until one of its methods is called. No config retrieval during CLI command object creation — no error. Learn more about proxies here: [Proxies](https://developer.adobe.com/commerce/php/development/components/proxies/). ## Simplify with Automated Proxy Injection For projects with only a few extensions, identifying problematic CLI commands is manageable. However, in larger, legacy projects or those with many third-party extensions, pinpointing these issues can be a daunting task. To save time, we developed a solution to automate proxy injection: **[run-as-root/magento-cli-auto-proxy](https://github.com/run-as-root/magento-cli-auto-proxy)**. This package automatically injects `Proxy` classes into all eligible `__construct` arguments of CLI commands. The benefits? No errors from premature resource access and, as a bonus, faster execution of `php bin/magento` and `php bin/magento setup:install`. Check out the README for more details. We welcome your feedback and contributions! ## Summary To summarize: - Poorly designed CLI commands can cause unexpected problems, even if they seem harmless initially. - The core issue often arises from **premature database calls**, creating a classic "chicken or the egg" scenario that stalls system installation. - A major pitfall is the **CLI command constructors** that execute code too early. - To address these challenges, follow three key principles: 1. **Be Wise** — avoid resource-heavy calls in constructors. 2. **Be Ready** — avoid accessing unavailable resources during runtime. 3. **Fix The Problem** — use proxies to defer instantiation of problematic code. - To streamline this process, we introduced **[run-as-root/magento-cli-auto-proxy](https://github.com/run-as-root/magento-cli-auto-proxy)**, a package that automates proxy injection for a smoother, error-free Magento experience. Thank you for reading! I welcome your questions and appreciate any feedback. Happy coding and... **Long Live Magento**! 😁

Payment retries & idempotency patternss

Payment retries & idempotency patternss

# Payment Retries In High Volume Magento 2 / Adobe Commerce Stores In high-volume Magento 2 / Adobe Commerce environments, payment retries are not an edge case — they are a **daily operational reality**. Any store processing thousands of checkouts per hour will inevitably face network latency, browser retries, impatient customers, delayed PSP callbacks, and partial failures across distributed systems. When retries are not handled with strict idempotency and state control, they become one of the **largest sources of revenue leakage, reconciliation overhead, and customer distrust**. This guide expands on the engineering methodologies required to make payment retries *safe by design*. It focuses on preventing double charges, eliminating duplicate orders, synchronizing Magento with PSP callbacks, and ensuring that **each payment attempt results in exactly one order — or none at all**. --- ## 1. Why Payment Retries Are a Major Problem Retries originate from both **human behavior** and **technical uncertainty**. Customers retry checkout when: - The checkout page appears frozen - A redirect to the PSP takes too long - A 3DS challenge loops or times out - Their browser auto-resubmits a request - They refresh the page during payment - The “Place Order” button remains clickable - Mobile networks drop mid-transaction From Magento’s perspective, these retries look like *new requests* unless explicitly controlled. ### Typical Magento-side symptoms - Duplicate orders for a single cart - Authorized or captured payments without any order - Orders stuck in `pending_payment` indefinitely - Multiple payment transactions linked to one quote - “Payment transaction already exists” exceptions - Orphaned quotes that can never be converted - PSP reconciliation mismatches requiring manual audits At scale, even a **0.1% retry failure rate** can translate into hundreds of support tickets and significant revenue risk per month. --- ## 2. Idempotency in Payments **Idempotency** ensures that performing the same operation multiple times produces **the same result**, not additional side effects. In payments, this means: - One customer intent - One PSP transaction - One Magento order ### Why idempotency is non-negotiable - Protects against double charges - Allows safe retries after timeouts - Prevents race conditions between frontend and webhooks - Enables deterministic recovery after partial failures Modern PSPs (Stripe, Adyen, Checkout.com, Braintree, PayPal) already support idempotency via: - Idempotency keys - Merchant reference identifiers - Payment Intent or Session IDs - Transaction-level deduplication However, **Magento does not enforce these by default** — the merchant integration must. --- ## 3. Default Magento Flow Limitations Magento’s native checkout flow was not designed for modern, asynchronous payment systems: - “Place Order” can fire multiple HTTP requests - JS-based checkout does not guarantee single submission - No built-in idempotency enforcement exists - Quotes remain mutable during payment - Webhooks may arrive before or after frontend completion - Order creation and payment authorization are tightly coupled Without intervention, Magento treats retries as **new business events**, even if they refer to the same payment attempt. --- ## 4. Common Idempotency Patterns for PSP Integrations ### 4.1 Frontend-Level Click Locking Immediately disable the “Place Order” button after the first click. **Key enhancements:** - Visual loading state - Hard JS-level debounce - Ignore duplicate submission events This prevents accidental retries but does **not** solve network-level or backend retries. --- ### 4.2 Backend Quote Locking The quote must become **read-only** once a payment attempt begins. Typical implementation: - Add `is_quote_locked = true` - Prevent totals, items, or payment method changes - Reject new order placement attempts This ensures that all retries refer to the *same immutable checkout state*. --- ### 4.3 PSP Idempotency Keys Every payment creation request must include a deterministic idempotency key. Example: ``` MAGENTO-{quote_id}-{attempt_number} ``` Best practices: - Persist the key in Magento - Reuse it on retries - Never generate a new key for the same intent --- ### 4.4 Order-Level Deduplication Magento must enforce: - One PSP transaction → one Magento order - One successful intent → no further order creation This is typically done by storing: - PSP payment ID - Intent ID - Merchant reference And checking them before order creation. --- ### 4.5 Webhook Synchronization Webhooks must be **idempotent and authoritative**. Rules: - Webhook should never create a second payment - Order creation must check existing records - Duplicate webhook deliveries must be ignored --- ## 5. Pattern: Payment Intent Architecture Payment Intents unify retries into a **single logical payment attempt**. Advantages: - Retry-safe by design - Clear state machine (`requires_action`, `processing`, `succeeded`, `failed`) - Supports async authentication flows - PSP-managed deduplication Magento responsibilities: - Create intent once per quote - Store intent ID on the quote - Reuse intent across retries - Never spawn a second intent unless the first is terminally failed --- ## 6. Pattern: Webhook-First Ordering In high-volume systems, **webhooks are more reliable than browsers**. ### Recommended flow 1. Customer submits checkout 2. Magento creates payment intent 3. Customer completes authentication 4. PSP webhook confirms success 5. Magento creates order once 6. Frontend polls for confirmation ### Benefits - Eliminates frontend race conditions - Prevents orders without payments - Handles slow 3DS flows gracefully - Works even if customer closes the browser --- ## 7. Pattern: Database-Level Retry Protection Persistent retry control requires explicit fields. Recommended fields: - `retry_token` - `retry_count` - `last_attempt_at` - `is_payment_pending` - `is_quote_locked` ### Backend logic - First attempt locks the quote - Subsequent attempts validate retry window - Hard-declined payments unlock the quote - Successful payments permanently close it --- ## 8. Pattern: Safe Retry Windows Retries should be **explicitly bounded**. Allow retries only when: - Payment is still pending - Intent is reusable - Retry window (e.g., 5–10 minutes) is valid Block retries when: - Order already exists - Intent succeeded - Hard decline received - Manual review is required This avoids infinite retry loops and fraud amplification. ![UI/log mock showing retry block](https://res.cloudinary.com/dnd6owhkg/image/upload/v1764133762/docx-images/kvrk9lycmkru8ce8tnx5.png) **Description:** A UI/log mock showing how Magento detects and blocks a second payment attempt when the first already succeeded. --- ## 9. Handling Late PSP Webhooks Late webhooks are inevitable in distributed systems. Magento must: - Store last known PSP state - Compare webhook status with internal state - Ignore stale or duplicate notifications - Reconcile discrepancies deterministically Customer-facing behavior: - Show “Payment Pending” - Avoid duplicate checkout attempts - Poll backend status instead of retrying blindly --- ## 10. Recovering Orphaned PSP Payments When payment succeeds but order creation fails: Recovery strategy: 1. Detect unmatched PSP transactions 2. Map PSP reference → quote 3. Recreate order programmatically 4. Attach transaction metadata 5. Notify finance / customer This is essential for **revenue completeness** in high-volume stores. --- ## 11. Queue-Based Retry Architecture Queues provide **serialization and durability**. Recommended design: - Payment creation events go to MQ - Single consumer processes attempts - Deduplication enforced in consumer - Order creation becomes atomic This prevents race conditions across web nodes and retries. --- ## 12. Observability & Logging Critical metrics to log: - Idempotency keys - Quote lock transitions - Retry counts - Webhook latency - Duplicate request rejections - Orphan recovery events Dashboards should surface: - Retry rate trends - Blocked duplicate percentage - Average webhook delay - Recovery success ratio Observability turns retry chaos into actionable insight. ![Mock dashboard](https://res.cloudinary.com/dnd6owhkg/image/upload/v1764133764/docx-images/uu21m8uwnivslos6b0tf.png) **Description:** Mock dashboard summarizing retry attempts, blocked duplicates, webhook latency, and successful recovery flows.