DEV Community

Dev Insights
Dev Insights

Posted on

Serie 2: Resilient Architecture — Production Patterns

The Problem

When a payment processor fails to update the order status, it can lead to a situation where the customer is charged but the order remains in a pending state. This implementation exists to ensure that when a payment is successfully processed, the corresponding order status is updated in a timely manner. The handleSuccessfulPayment function is designed to handle the payment confirmation from the payment gateway and update the order status to 'PAID' to prevent duplicate charges or order mix-ups.

If this implementation is missing or incorrect, it can result in inconsistent order states, leading to customer complaints and potential financial losses due to duplicate charges or undelivered orders.

One trade-off of this implementation is that it introduces an additional dependency on the orderRabbitClient, which can be a single point of failure if not properly managed.

What is the best approach to handle transient failures in the orderRabbitClient, should we implement a retry mechanism or use a message queue to buffer the updates.

The Implementation

      throw new BadRequestException('Error al procesar el pago');
    }
  }

  async handleSuccessfulPayment(data: {
    paymentId: string;
    status: string;
    orderId: string;
    merchantOrderId?: string;
    preferenceId?: string;
  }) {
    this.logger.log(`💰 Procesando pago exitoso: ${data.paymentId}`);

    try {
      const updatedOrder = await this.orderRabbitClient.updateOrderPaymentStatus(
        data.orderId,
        {
          paymentId: data.paymentId,
          paymentStatus: 'PAID',
          paymentDate: new Date(),
        });
Enter fullscreen mode Exit fullscreen mode

Why This Matters in Production

This pattern directly prevents common failure modes in distributed systems.
Without it, you're exposed to race conditions, data inconsistency, and cascading failures.

Trade-offs

Every architectural decision has a cost. This approach adds complexity to your
codebase and requires your team to understand the pattern deeply before modifying it.

Key Takeaways

  • Understand the failure mode before implementing the solution
  • Test the unhappy path, not just the happy path
  • Document the why, not just the what

Part of the Serie 2: Resilient Architecture series.

Top comments (0)