We have an API that handles ~45k monthly requests that was, at times, responding strangely. I suspected it was related to the .NET Core service lifetimes.
The symptoms in question were that out of the blue, the API response body had a status code of 409 with a message of invalid user-provided values, however, the actual HTTP response status code was 200.
From then on, the API would respond with the same invalid body, no matter what the request was.
To give a little background, the API is deployed on-premises as multiple instances of Windows services.
And the fix? Well, the fix for this issue was to simply restart the Windows services. After the restart, the API would start responding as expected.
Finding the Issue
After debugging and stepping through the code locally, I reached a base class holding a list of validations for the Domain Entities (IList<SpecificationValidationResult> _validationResults = new List<SpecificationValidationResult>()
).
It is here where I noticed this list holding validations throughout the application’s lifetime, in other words, a singleton instance of the validator class.
The problem? Well, if a validation result reached an invalid state, the list would hold this invalid state for any future requests, returning a failure upon list evaluation.
Fixing The Service Lifetimes
Upon looking at the Dependency Injection (DI) configurations, I noticed the validator was being configured as Transcient, however, the services running the configurations were configured as Singleton.
This means, that upon the singleton services receiving the first request, they would instantiate the validator for the first time and keep the same instance throughout the service lifetime.
The original intention of having the validators be Transcient was to have one validator instance per HTTP request, however, running a Transcient service from within a Singleton service will effectively make the Transcient service a Singleton.
Refactoring the validators as Scoped and the services to Transcient fixed the issue. It gave the validators back their original intent, which was to live only the duration of the HTTP request.
Moral of the Story
Make sure you are implementing the correct DI for your use case and test the application thoroughly before deploying!
There are plenty of tutorials out there that show how .NET Core service lifetimes and Dependency Injection (DI) work, however, the most useful one I have found is “Dependency Injection Deep Dive” by Amichai Mantinband https://youtu.be/yjUCKSKCQxg?si=oSnza8jZpk4x9PMS“.
Have you run into any issues regarding service lifetimes? Let me know in the comments below!
If you liked this reading, share it on your social media and you can follow me on Twitter or LinkedIn.
Consider giving back by getting me a coffee (or a couple) by clicking the following button: