Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I chose the Payment Settlement Pipeline challenge because it aligns closely with the kind of problems I have worked on in backend and distributed systems. It includes concerns like dual writes, idempotency, retries, and eventual consistency, which are issues I find more representative of real production systems than simple CRUD flows.
The main architectural decision I made was to use a Transactional Outbox for event publishing. I chose this to avoid the risk of committing to the database and failing to publish the event afterward. For idempotency, I handled it at the consumer level with a consumer_acks table, since I think deduplication should be owned by the consumer and not rely only on broker guarantees.
For failed retries, I decided to emit a compensating event so the payment can move to a terminal state immediately instead of depending on a separate DLT flow. For status tracking, I used an event-driven aggregator instead of a saga, since the flow is still simple and can be resolved by checking business tables directly.
I also treated fraud scoring as non-blocking, because I see it as informational at this stage of the process, not as something that should stop settlement. On the infrastructure side, I used per-country topics, a Unit of Work pattern for transaction handling, and Hexagonal Architecture to keep the core business logic independent from frameworks and infrastructure details.
With more time, I would improve concurrency handling in the aggregator with a distributed lock, add schema or contract validation for events, improve observability, and clean up old idempotency records automatically. I would also consider CDC instead of polling for the outbox relay.
For more details, please see the README. Thanks!