{"id":50,"date":"2026-08-14T13:08:25","date_gmt":"2026-08-14T13:08:25","guid":{"rendered":"https:\/\/barrymind.com\/?p=50"},"modified":"2026-08-14T13:08:28","modified_gmt":"2026-08-14T13:08:28","slug":"when-encompass-says-not-now","status":"publish","type":"post","link":"https:\/\/barrymind.com\/?p=50","title":{"rendered":"When Encompass Says \u201cNot Now\u201d"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Building an Asynchronous Retry System<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is a particular kind of software problem that doesn&#8217;t look very complicated at first.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You save something.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The system says no.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You try again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It says no again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You wait.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You try again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Still no.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eventually, you realize the problem isn&#8217;t really your code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Someone has the loan locked.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Welcome to one of the realities of building software around Encompass.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Problem: You Don&#8217;t Always Own the Loan<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When working with Encompass, modifying a loan generally requires the loan to be locked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That makes perfect sense from a data consistency perspective. You don&#8217;t want two different processes changing the same loan at the same time and creating a beautiful little data disaster.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The problem is that a loan can remain locked for quite a while.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A broker might have the loan open in the Encompass client. They might be reviewing it, editing something, or simply have it open while they go get coffee.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meanwhile, our application is trying to save something.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And Encompass basically says:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Nope. This loan is busy.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">From the broker&#8217;s perspective, this is even worse.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They click <strong>Save<\/strong> on our application, and the operation fails because somebody else happens to be using the loan.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That isn&#8217;t a particularly friendly user experience.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And there was another problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SDK + Speed = A Dangerous Combination<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Anyone who has spent enough time working with the Encompass SDK knows that it isn&#8217;t exactly famous for being fast.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Calling the SDK can be surprisingly slow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And when you put a slow external operation directly into a web request, the problem isn&#8217;t just that the operation takes a long time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Your application has to wait for it.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The user has to wait.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The web server has to keep the request alive.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Threads remain occupied.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And if you have a lot of users doing this at the same time, a slow Encompass operation can start affecting the performance of the entire application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So now we had two problems:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The loan might be locked.<\/li>\n\n\n\n<li>Even when it isn&#8217;t locked, the operation itself may take a while.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Putting all of that directly into a web request is not exactly a recipe for a relaxing afternoon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We needed a different approach.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">So We Built a Retry Machine<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of making every Encompass update happen directly inside the user&#8217;s request, we built our own asynchronous retry mechanism.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I like to think of it as a <strong>retry machine<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The basic idea is simple:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Don&#8217;t make the user fight Encompass. Put the work in a queue and let the system fight Encompass instead.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Every operation that needs to update an Encompass loan goes through the retry system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That includes things like:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Updating loan data<\/li>\n\n\n\n<li>Uploading documents<\/li>\n\n\n\n<li>Other Encompass operations that may require the loan to be available<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When we create an operation, we don&#8217;t just store a few parameters and hope for the best.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We store the information required to reproduce the operation, including the relevant data and the logic needed to execute it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The request is then placed into a queue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">From there, the retry system processes the requests in order.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Something roughly like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Broker\n   \u2502\n   \u2502 Save\n   \u25bc\nOur Application\n   \u2502\n   \u25bc\nRetry Queue\n   \u2502\n   \u251c\u2500\u2500 Operation #101\n   \u251c\u2500\u2500 Operation #102\n   \u251c\u2500\u2500 Operation #103\n   \u2514\u2500\u2500 Operation #104\n          \u2502\n          \u25bc\n      Encompass\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If Encompass accepts the operation, great.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;re done.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If Encompass doesn&#8217;t accept it because the loan is currently locked, we don&#8217;t immediately tell the broker:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;Congratulations! Please try again later.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Instead, the operation stays in the system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After a configurable delay, we try again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And again, if necessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The important part is that <strong>the user doesn&#8217;t have to keep clicking Save<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The system does the waiting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Unexpected Bonus: It Made the Application Faster<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There was another benefit that turned out to be just as important.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The retry mechanism is asynchronous.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That means the web request doesn&#8217;t have to sit there waiting for Encompass to finish its work.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The application can accept the user&#8217;s request, put the operation into the queue, and return control to the user.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The actual Encompass update happens in the background.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is particularly valuable when working with the Encompass SDK, where some operations can take a surprisingly long time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Without asynchronous processing, a request might look like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Browser\n   \u2502\n   \u2502 Save\n   \u25bc\nWeb Server\n   \u2502\n   \u2502\u2500\u2500\u2500\u2500\u2500\u2500 Wait \u2500\u2500\u2500\u2500\u2500\u2500\u2502\n   \u2502                  \u2502\n   \u25bc                  \u25bc\nEncompass SDK     Encompass SDK\n   \u2502                  \u2502\n   \u2502\u2500\u2500\u2500\u2500 Slow \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502\n   \u25bc\nResponse\n   \u2502\n   \u25bc\nBrowser\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">With the retry system, the flow becomes much more efficient:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Browser\n   \u2502\n   \u2502 Save\n   \u25bc\nWeb Server\n   \u2502\n   \u25bc\nQueue\n   \u2502\n   \u25bc\nResponse\n   \u2502\n   \u25bc\nBrowser\n\n        ...later...\n\n      Background Worker\n             \u2502\n             \u25bc\n        Encompass SDK\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of making the user&#8217;s request responsible for the entire Encompass operation, we make the request responsible for <strong>accepting the work<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The background process becomes responsible for <strong>completing the work<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This dramatically improves the responsiveness and scalability of the application, especially when many users are performing Encompass operations at the same time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In other words, the retry mechanism wasn&#8217;t just a reliability feature.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>It also became a performance feature.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And that&#8217;s one of those architectural improvements that you don&#8217;t always appreciate until you remove it and watch the application suddenly become very unhappy.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">But Asynchronous Updates Have a Catch<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, you might be thinking:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">&#8220;Great. Just put every loan update into the queue and let it run asynchronously.&#8221;<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Not so fast.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is where mortgage software gets particularly interesting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Loan data is highly interconnected.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A seemingly small change can have a <strong>cascading impact across the entire loan<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, imagine a broker changes the loan amount.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That single change can affect calculations such as:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>LTV<\/li>\n\n\n\n<li>DTI<\/li>\n\n\n\n<li>Loan pricing<\/li>\n\n\n\n<li>Qualification results<\/li>\n\n\n\n<li>Disclosures<\/li>\n\n\n\n<li>Underwriting data<\/li>\n\n\n\n<li>Other downstream fields and processes<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Or imagine the borrower&#8217;s income changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That can affect DTI and potentially a whole chain of other calculations and business decisions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In our system, we often relied on Encompass to perform some of these calculations. We also had our own calculations in certain areas, but Encompass is a good example of why loan updates aren&#8217;t always isolated events.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">One field changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another field changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That triggers another calculation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That calculation affects another process.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Suddenly, the &#8220;simple update&#8221; isn&#8217;t so simple anymore.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So blindly making every front-end update asynchronous could introduce a completely different class of problems.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You could end up with something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>User changes Loan Amount\n          \u2502\n          \u25bc\n     Queue Update\n          \u2502\n          \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n          \u25bc               \u25bc\n     UI shows new     Encompass\n     Loan Amount      still has old value\n                          \u2502\n                          \u25bc\n                    Old DTI \/ LTV\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have two different versions of the loan temporarily living in the system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s not something you want to do casually.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Fortunately, the Business Process Helped Us<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of those cases where the business workflow actually helped solve a technical problem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In our mortgage workflow, once the <strong>Initial Disclosure<\/strong> has been issued, a broker can no longer freely modify certain loan data.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If something important needs to change, they have to initiate a <strong>Change Circumstance<\/strong> process, and the Lender takes over the actual change.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That business rule creates an important boundary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It significantly reduces the possibility of users continuously making major changes to a loan while asynchronous operations are still being processed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In other words, the business process provides a form of synchronization that the software alone would otherwise have to enforce.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is a lesson I&#8217;ve learned repeatedly in mortgage software:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Sometimes the business workflow is part of the architecture.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You don&#8217;t always solve every consistency problem with more code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes an existing business rule gives you exactly the boundary you need.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And in this case, it was extremely helpful.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That doesn&#8217;t mean the retry mechanism became unnecessary.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quite the opposite.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Even with these business controls in place, Encompass operations can still fail because of loan locking, performance, transient errors, unexpected data, or other conditions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We still needed the retry system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We just didn&#8217;t have to pretend that every loan field could safely be treated as an independent asynchronous operation.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Then We Discovered the Next Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">At this point, we had solved the original problem.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Almost.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Remember what happens when the broker clicks Save?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Their changes enter our retry queue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But what if the loan is locked?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The update hasn&#8217;t actually made it into Encompass yet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The broker, however, doesn&#8217;t care about our queue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They expect to see the change they just made.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And they&#8217;re absolutely right.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine this:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The broker changes the borrower&#8217;s phone number.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our application accepts the change.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The update gets queued.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Encompass says:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>&#8220;Loan is locked.&#8221;<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the update waits.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then the broker refreshes the page.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We read the loan from Encompass.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Encompass still contains the old phone number.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And suddenly our application appears to have forgotten what the broker just did.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s not acceptable.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So we needed another layer.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Cache: Because Reality Has a Delay<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We introduced a cache specifically for pending changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When a broker changes something, we store the updated value in our cache while the Encompass operation is waiting to be completed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When our application reads the loan, we check the cache first.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the cache contains a newer value, we use that value.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once the Encompass update succeeds, the cached value can be reconciled with the source system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Conceptually:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>                Read Loan\n                    \u2502\n                    \u25bc\n             \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n             \u2502 Cache has    \u2502\n             \u2502 newer data?  \u2502\n             \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n                Yes  \u2502  No\n                 \u2502   \u2502\n                 \u25bc   \u25bc\n              Cache Encompass\n                 \u2502   \u2502\n                 \u2514\u2500\u2500\u2500\u2518\n                    \u2502\n                    \u25bc\n                   UI\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So even if Encompass hasn&#8217;t been updated yet, the broker can still see the change they just made.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This creates a much better user experience.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But, naturally&#8230;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>we had just created another problem.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Cached Data Has an Expiration Date<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A cache is great when it contains newer information than the source system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A cache is dangerous when nobody remembers to update it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine an Encompass operation fails.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then it fails again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And again.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Maybe the loan stays locked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But what if it wasn&#8217;t actually a lock?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What if the failure is caused by a bug in our code?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What if the data is malformed?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What if an unexpected value causes the Encompass operation to fail every single time?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have a pending update sitting in our queue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And we have cached data that is newer than Encompass.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If nobody handles the failed operation, that cached data can sit there for a very long time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eventually, our &#8220;temporary&#8221; cache becomes an alternative version of reality.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s when things get dangerous.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Someone Has to Watch the Queue<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is one of the less glamorous parts of building reliable software.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Automation is great.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But automation doesn&#8217;t eliminate the need for humans.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It changes the kind of work humans need to do.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Our administrators need to monitor failed operations and determine <strong>why<\/strong> they failed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the loan was simply locked, the operation may just need another retry.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the failure is caused by a code bug, retrying it 50 times isn&#8217;t going to magically fix the bug.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If the data itself is invalid, someone needs to investigate it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And if the system has entered an unexpected state, someone needs to understand what happened before we make things worse.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the retry queue became more than just a technical component.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It became an operational tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We needed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Automatic retries<\/li>\n\n\n\n<li>Configurable retry intervals<\/li>\n\n\n\n<li>Persistent operation history<\/li>\n\n\n\n<li>Failure tracking<\/li>\n\n\n\n<li>Manual retry capability<\/li>\n\n\n\n<li>Administrative visibility<\/li>\n\n\n\n<li>A way to identify operations that are repeatedly failing<\/li>\n\n\n\n<li>A way to reconcile pending changes with the actual Encompass data<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">The Bigger Lesson<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Looking back, the interesting part isn&#8217;t really the queue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A queue is easy.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The hard part is everything around it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We started with a relatively simple problem:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Encompass might have the loan locked when we need to update it.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Our first solution was:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Retry the operation later.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Then we discovered:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>But the user still needs to see their changes immediately.<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">So we added a cache.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then we discovered:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>But what happens if the operation never succeeds?<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">So we added monitoring and administrative tools.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And then there was the performance problem:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Why make the user&#8217;s request wait for a slow Encompass SDK operation if it doesn&#8217;t have to?<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">So the queue also became an asynchronous processing layer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And then there was the business problem:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>What happens when a seemingly small loan change affects half a dozen other pieces of data?<\/strong><\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">That forced us to think carefully about which operations could safely be asynchronous and which ones required stronger business controls.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eventually, the system became something much larger than a retry mechanism.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It became a way of separating <strong>the user&#8217;s expectation of immediate feedback<\/strong> from <strong>the eventual consistency, business rules, and performance characteristics of an external system<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s a pattern I&#8217;ve encountered again and again in mortgage software.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The system you&#8217;re integrating with doesn&#8217;t always respond when you want it to.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes it&#8217;s slow.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes it&#8217;s locked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes it&#8217;s down.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes it accepts your request but doesn&#8217;t behave exactly the way you expected.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And sometimes the only thing you can do is wait.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The trick is making sure <strong>your users don&#8217;t have to wait with you.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">One Last Thing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">There is a temptation when building integrations to think of an external system as if it were just another database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It isn&#8217;t.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It has its own state.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its own performance characteristics.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its own locking rules.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its own failure modes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its own business rules.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And, occasionally, its own personality.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">When you&#8217;re building a system around something like Encompass, reliability isn&#8217;t just about successfully calling the API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s about designing your application around the possibility that <strong>the API might not be available when you need it, might be slower than you expect, and might fail for reasons completely outside your control.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It&#8217;s also about understanding the business process around that API.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Because in mortgage software, <strong>the architecture isn&#8217;t just the code.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The business workflow, the external systems, the data dependencies, and the operational processes are all part of the architecture.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That&#8217;s where asynchronous processing, retries, caching, monitoring, and good operational tooling become much more than implementation details.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>They become part of the architecture.<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Building an Asynchronous Retry System There is a particular kind of software problem that doesn&#8217;t look very complicated at first. You save something. The system says no. You try again. It says no again. You wait. You try again. Still no. Eventually, you realize the problem isn&#8217;t really your code. Someone has the loan locked. &#8230; <a title=\"When Encompass Says \u201cNot Now\u201d\" class=\"read-more\" href=\"https:\/\/barrymind.com\/?p=50\" aria-label=\"Read more about When Encompass Says \u201cNot Now\u201d\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-50","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/posts\/50","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/barrymind.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=50"}],"version-history":[{"count":1,"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions"}],"predecessor-version":[{"id":51,"href":"https:\/\/barrymind.com\/index.php?rest_route=\/wp\/v2\/posts\/50\/revisions\/51"}],"wp:attachment":[{"href":"https:\/\/barrymind.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=50"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/barrymind.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=50"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/barrymind.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=50"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}