I made several errors in this application that I'd avoid today.
1) Json schemas. I originally hosted them as a Lambda function which added a few seconds to the execution time. It wasn't a mistake per se but became an issue as execution time got crowded with other functions. The traditional Json schema model is to pull the schemas real-time from a URL. I tried several different methods and I eventually decided the best model is to host the schemas in their own repo, import them during the build process and execute them locally. This gives minimum execution time at the expense of real-time updates but maybe real-time updates are a bad idea in a monetary app.
2) Clear definition of domains - Reference, Action, Guarantee I didn't explicitly define domain goals to guide design. They were roughly in my head but not as clearly thought out as two years later.
3) Parameter store is free but rate-limited, Secrets Store is a per-use cost. I worried too much about cost and not enough about performance.
4) Entry API should have been issuance of the internal tracking number. Then it could have been embedded in the original message to maintain immutability. I treated it as a secondary consideration so it always polluted immutability. Is it really immutable here, what about there, what if this happens, etc. Forcing it as the entry point simplifies decision-making later in the process flow.
5) Exclusive use of Lambda functions. The lack of stored state became an issue later which I didn't account for. I'm pretty sure I needed an EC2-hosted service which could store state.
6) Language choice. Once again, not a mistake per se but eventually an issue. In retrospect, I'd choose python over java because it's the crypto language of choice and probably more appropriate in size of application versus scalability reliability etc. Java saved two months of development time in a 12-month window so I'm still ambivalent if it was a "mistake". That two months bought several additional presentations to venture capitalists.
7) Circuit breakers. One reason to use AWS SQS is the depth of its error handling. For most of the app, I can probably delegate application errors by invoking an AWS SQS error.
Also, I didn't know the SAAS concept of a circuit breaker. The error handling of external API calls was haphazard. I'd use a standardized library now like this: