OrmLite JSON serialization reverts to JSV?

I’m serializing complex objects as JSON in my Sqlite3 db, using this in Startup:

SqliteDialect.Provider.StringSerializer = new JsonStringSerializer();

However, running the same code, occationally it still gets serialized as JSV – same places as previously (and after) it would serialize as JSON. So it’s like sometimes it just decides to do JSV.

My program is too large for a working sample, but is there any chance ServiceStack “forgets” the serializer setting somehow? Is there a better place to set it? Or hint to what I should investigate. I’m running in Visual Studio via debugger, could hot code replacement trigger this (of my own code)?

I don’t see how it wouldn’t use the configured Dialect Provider Serializer unless it’s not using the Dialect Provider. You can try using the BeforeExecFilter to intercept DB commands before they’re executed like printing the generated SQL output which should identify queries with the issue:

OrmLiteUtils.PrintSql();

We would need a stand-alone repro to be able to investigate.

We’re having this problem again, and it’s hard to track, especially since it happens without any warning.

So to recap:

I’ve got a class which I serialize to our DB. Since 2021/2022 these lines are in my code to force JSON always:

        SqlServerDialect.Provider.StringSerializer = new JsonStringSerializer();
        SqlServer2017Dialect.Provider.StringSerializer = new JsonStringSerializer();
        SqliteDialect.Provider.StringSerializer = new JsonStringSerializer();

        // followed by this:
        ServiceStack.JS.Configure(); // this fixes a lot, don't remember why

Dialect provider is set explicitly to SqlServer2017Dialect, except for unit testing where Sqlite is used:

var dialectProvider = connectionString.StartsWith("Server=") ? SqlServer2017Dialect.Provider : SqliteDialect.Provider;
var dbFactory = new OrmLiteConnectionFactory(connectionString, dialectProvider);
services.AddSingleton<IDbConnectionFactory>(dbFactory);


At one point we had to add [Serializable] because we were getting deserialization error, but this was a very explicit error that threw exceptions. However it was around the same time (november) when we got the errors the first time (timeline later).

[Serializable]  // to be able to serialize it in GlobalState, ref. https://docs.servicestack.net/releases/v6_06#msvr-76883
public class ActionInstanceReference
{
    // some public properties
}

So what happens is that we have a class which we save to the db.
It is basically

public class ProcessInstance
{
    [AutoIncrement]
    public int Id { get; set; }

   public Dictionary<string, object> GlobalState { get; set; } = new Dictionary<string, object>();

The GlobalState is where things sometimes goes wrong, it will only serialize the first level to JSON, then it’ll revert to JSV for the deeper nested objects.

Incorrect:

{
  "employee": "{fullName:xxxx yyyy,firstName:xxxx,lastName:yyyyy,...}",
  "endDate": "2025-01-31",
  "__REFS__": "{confirmEmailMgr:{__type:MasterProcessServer.ServiceModel.Interfaces.ActionInstanceReference, MasterProcessServer.ServiceModel,type:Message,prettyPrint:Message to MDK 169},confirmEmailEmp:{type:Message,prettyPrint:Message to MDK 965}}"
}

Correct (taken from another row in the DB):

{
  "employee": {
    "fullName": "xxxx yyyy",
    "firstName": "xxxx",
    "lastName": "yyyy",
    ...
  },
  "endDate": "2024-11-30",
  "__REFS__": {
    "confirmEmailMgr": {
      "__type": "MasterProcessServer.ServiceModel.Interfaces.ActionInstanceReference, MasterProcessServer.ServiceModel",
      "type": "Message",
      "prettyPrint": "Message to MDK 1597"
    },
    "confirmEmailEmp": {
      "type": "Message",
      "prettyPrint": "Message to MDK 580"
    },
    ....
}

This has happened intermittently. From our logs and our backups, we can see that the GlobalState object was correctly JSON-only, then turned bad at the same time.

237	2024-10-28 14:34:56.023 BAD
240	2024-10-29 15:23:05.633 GOOD
236	2024-10-31 10:18:42.287 GOOD
243	2024-11-27 14:12:45.287 GOOD
238	2024-12-16 11:00:16.037 GOOD
239	2024-12-23 18:22:03.313 BAD
241	2024-12-23 18:22:03.653 BAD
242	2024-12-23 18:22:03.900 BAD
246 2024-12-27 08:00:12.860	GOOD

From the dates, we can assume that no one was working at the time.

I could find this in my logs:

2024-12-23 18:22:03.191 +01:00 [ERR] Activity 8557 of process instance 239 failed w. exception The best overloaded method match for 'MasterProcessServer.ServiceModel.Utils.ExpandoObjectHelper.ToExpando(System.Collections.Generic.IDictionary<string,object>)' has some invalid arguments
2024-12-23 18:22:03.970 +01:00 [INF] Failed to write error to response: {0}
ServiceStack.ConfigurationErrorsException: ServiceStack: AppHost does not exist or has not been initialized. Make sure you have created an AppHost and started it with 'new AppHost().Init();'  in your Global.asax Application_Start() or alternative Application StartUp
   at ServiceStack.HostContext.AssertAppHost() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/HostContext.cs:line 34
   at ServiceStack.HostContext.RaiseAndHandleException(IRequest httpReq, IResponse httpRes, String operationName, Exception ex) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/HostContext.cs:line 261
   at ServiceStack.Host.Handlers.HttpAsyncTaskHandler.HandleException(IRequest httpReq, IResponse httpRes, String operationName, Exception ex) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Host/Handlers/HttpAsyncTaskHandler.cs:line 180

So once we got the error about “ToExpando” then I traced back and finally arrived at a DB ORMLite save call. It was guarded by this:

// just a bug hunt:
if (SqlServerDialect.Provider.StringSerializer.GetType() != typeof(JsonStringSerializer)
|| SqliteDialect.Provider.StringSerializer.GetType() != typeof(JsonStringSerializer)) {
    throw new MasterServiceException("Wrong db serializer! ");
}

However I note that it’s missing SqlServer2017Dialect and only has SqlServerDialect so of course there was nothing in the logs.

Question: Is there any case where OrmLite would revert to JSV ?

  • Like if somehow my Dictionary<string,object> (where object can be another dict of same type) got messed up somehow into another class or something?
  • Or could it be something with that last line in the log about the AppHost. Because after that I have no more log lines for the failed processes (so probably that’s when they failed). Perhaps some “default apphost” started after that? One without the JSON serialization options set?

I’m not going to be able to identify what the issue is without being able to reproduce the behavior but the most likely explanation from your “AppHost does not exist” Exception in your Error log and change in Dictionary<string,object> behavior is that when your App is being shutdown it will dispose the AppHost which will in addition to disposing all registered IDisposable dependencies will revert the JS.Configure() behavior handling of Dictionary<string,object> from JS Utils using #Script and ServiceStack.Common back to ServiceStack.Text behavior.

In which case you should probably guard against running any logic whilst your AppHost is being shutdown by adding something in your AppHost that checks the protected isDisposed and throws an Exception:

public void ThrowIfDisposed()
{
    if (isDisposed)
        throw new ObjectDisposedException(GetType().Name);
}

Or just create a public IsDisposed property that your App can check to avoid running any logic.

Thanks it may look like this is the case. When we look at the logs, it might be that some app recycling has started, and at some point our code starts to fail. First we’re loosing the JSON config that forces ISO dates instead of timestamp, then shortly after we loose JSON all together and get the default JSV.

One thing I’m unsure about is where to call the ThrowIfDisposed (or check property), assuming this is added to our AppHost. If the recycling can happen at any time… we can’t really check for disposed everywhere. Or does it need to be on the top of every service or what?

Can you elaborate a bit?

Call it before logic that relies on Dictionary<string,object> behavior.

You could check and call it from a Global Request Filter to prevent all API Requests from executing.

As documented in the Order of Operations the closest check before your Service is executed would be in your Services OnBeforeExecute method, e.g:

public class MyServices : Service
{
    public override void OnBeforeExecute(object requestDto)
    {
        ServiceStackHost.ThrowIfDisposed();
    }
}

Which would apply to all APIs implemented in this Service class or any sub classes if this is a base class for other Services. To implement it for all Services you can create a Custom Service Runner.

Note: I’ve added a public AppHost IsDisposed instance property and a static ServiceStackHost.ThrowIfDisposed() in the latest v8.5.3+ that’s now available in pre-release packages.

Thanks for including it in new releases.

Today we’ve corrected incorrectly serialized data (i.e. not JSON w. ISO) and discovered that it’s not only the Dictionary<string,object> but also other objects, such as this fully typed one, where dates and capitalization settings reverted (lost the JSConfig) – and it usually works perfectly:

public class ActivityInstance
{
    [AutoIncrement]
    public int Id { get; set; }
    public List<StatusUpdate> StatusHistory { get; set; } // this one lost ISO date format
}

public class StatusUpdate
{
    public DateTime EnteredStatus { get; set; }
    public DateTime? ExitedStatus { get; set; }
    public enActivityStatus Status { get; set; }
    public string Message { get; set; }
}

public enum enActivityStatus
{   
    [EnumMember(Value = "INACTIVE")]
    INACTIVE,
    [EnumMember(Value = "READY")]
    READY,
    ...
}

We will investigate more, but it seems very impractical to check “if a disposal/recycling is underway” everywhere we read/write to DB. The global service request filter sounds more practical, but will it catch all?

From our logs we have observed that within a single API call, the trouble can happen (so disposal check PASS and then disposal happens…):

  1. The RunLoop is started from an API call, and the first 151, 200, 209 goes well. So a disposal was not ongoing at the time, hence I don’t think a check/ReqFilter would catch it.
  2. Then 212 was partly affected, as we lost our ISO time and CamelCase option for the JSON serializer (but still no JSV at this time)
  3. Then 237, 239, 241, 242 went all the way to JSV.
  4. Message about AppHost trouble and restart complete
2024-12-23 18:22:02.698 +01:00 [INF] RunLoop found processes: 151, 200, 209, 212, 237, 239, 241, 242
2024-12-23 18:22:02.698 +01:00 [INF] Running process 151
2024-12-23 18:22:02.766 +01:00 [INF] Refreshed case 3101573 w. thirdparty id ...
2024-12-23 18:22:02.806 +01:00 [INF] Running process 200
2024-12-23 18:22:02.874 +01:00 [INF] Refreshed case 3071010 w. thirdparty id ...
2024-12-23 18:22:02.909 +01:00 [INF] Running process 209
2024-12-23 18:22:02.978 +01:00 [INF] Running process 212
2024-12-23 18:22:03.046 +01:00 [ERR] <<<unrelated error here>>>
2024-12-23 18:22:03.084 +01:00 [INF] Running process 237
2024-12-23 18:22:03.156 +01:00 [INF] Running process 239
2024-12-23 18:22:03.191 +01:00 [ERR] <<<same unrelated error here but for 239>>>
2024-12-23 18:22:03.201 +01:00 [ERR] <<<same unrelated error here but for 239>>>
2024-12-23 18:22:03.211 +01:00 [ERR] <<<same unrelated error here but for 239>>>
2024-12-23 18:22:03.388 +01:00 [INF] Running process 241 <-- no errors but still serialization bug
2024-12-23 18:22:03.701 +01:00 [INF] Running process 242 <-- no errors but still serialization bug
2024-12-23 18:22:03.960 +01:00 [INF] RunLoop DONE <-- API call done
2024-12-23 18:22:03.970 +01:00 [INF] Failed to write error to response: {0}
ServiceStack.ConfigurationErrorsException: ServiceStack: AppHost does not exist or has not been initialized. Make sure you have created an AppHost and started it with 'new AppHost().Init();'  in your Global.asax Application_Start() or alternative Application StartUp
   at ServiceStack.HostContext.AssertAppHost() in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/HostContext.cs:line 34
   at ServiceStack.HostContext.RaiseAndHandleException(IRequest httpReq, IResponse httpRes, String operationName, Exception ex) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/HostContext.cs:line 261
   at ServiceStack.Host.Handlers.HttpAsyncTaskHandler.HandleException(IRequest httpReq, IResponse httpRes, String operationName, Exception ex) in /home/runner/work/ServiceStack/ServiceStack/ServiceStack/src/ServiceStack/Host/Handlers/HttpAsyncTaskHandler.cs:line 180
2024-12-23 18:23:04.959 +01:00 [WRN] Multiple ValidationFeature Plugins detected. Removing default ValidationFeature plugin...
2024-12-23 18:23:05.281 +01:00 [INF] Initializing Application MasterProcessServer took 834.9024ms. No errors detected.

Last in the log we see the reload/restart was done. Since it took 834 ms, it should have started around 18:23:04.447, but I don’t know if we can trust the timestamps, perhaps it started earlier, because we got the error about the AppHost already at 18:22:03.970.

Point is that it seems we must check right before reading/writing via OrmLite, and that’s very many places, and quickly gets ugly. Is there an option to use BeforeExecFilter and put the check in there?

Also I don’t quite understand “…will revert the JS.Configure() behavior handling of Dictionary<string,object> from JS Utils using #Script and ServiceStack.Common back to ServiceStack.Text behavior.” I guess since the config is global (static) then it’s shared somehow.

Some useful info perhaps? I’ve noticed that our Configure.Db.cs has this Priority attribute to make sure the DB connections are registered early enough, since we’re dependent on them for different Repository classes later (see below Startup.cs).

[Priority(-1)]      // run before AppHost's Startup()
public class ConfigureDb : IConfigureServices, IConfigureAppHost

// to serialize complex objects as JSON instead of JSV
SqlServerDialect.Provider.StringSerializer = new JsonStringSerializer();
SqlServer2017Dialect.Provider.StringSerializer = new JsonStringSerializer();
SqliteDialect.Provider.StringSerializer = new JsonStringSerializer();

ServiceStack.JS.Configure(); // GLOBAL: Configure ServiceStack.Text JSON Serializer to use Templates JS parsing

Then in Startup.cs:

     JsConfig.Init(new ServiceStack.Text.Config
     {
         DateHandler = DateHandler.ISO8601,
         AlwaysUseUtc = false,
         TextCase = TextCase.CamelCase,
         ExcludeDefaultValues = false,       
         IncludeNullValues = false
     });

     container.RegisterAutoWired<FormRepository>(); // ex of class that needs the DB conn from IOC

Perhaps if the JsConfig.Init was moved into Configure.Db.cs close to ServiceStack.JS.Configure(); ? I don’t really know when the JSUtils are recreated/changed.

BTW we could continue on e-mail/meeting etc. (as part of our subscription), then it would be easier to share code that I can’t do publicly – don’t know how much value this is for others anyway.

Is there an option to use BeforeExecFilter and put the check in there?

Yes there is, but there’s only one global BeforeExecFilter handler:

OrmLiteConfig.BeforeExecFilter = dbCmd => {
    ThrowIfDisposed();
};

Also I don’t quite understand “…will revert the JS.Configure() behavior handling of

Here’s the implementation of JS.Configure():

I.e. it takes over handling of ObjectDeserialization with the ServiceStack.Common JS Utils implementation. When the AppHost disposes it reverts the behavior back to ServiceStack.Text default implementation.

public static void UnConfigure() => JsonTypeSerializer.Instance.ObjectDeserializer = null;

One thing you could try is reattach the behavior after the AppHost is disposed:

protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);
    JS.Configure();
}
1 Like

We’re thinking that the best would be to fix the issues and continue with load/save. Because just throwing exception… well it’s just not as good (for several reasons).

Would this work? It’s in Configure.Db.cs


    public void Configure(IAppHost appHost)
    {
        OrmLiteConfig.BeforeExecFilter = dbCmd => {
            EnsureSerializersAreCorrect();  // https://forums.servicestack.net/t/ormlite-json-serialization-reverts-to-jsv/10091/8
            Log.Info("Before Exec Filter");
            
            AppHost theAppHost = appHost as AppHost;
            if(theAppHost !=null && theAppHost.IsDisposed) {
                Log.Error("AppHost is disposed");
            }
        };        
    }


    public void EnsureSerializersAreCorrect()
    {
        if (JsConfig.DateHandler != DateHandler.ISO8601) {
            Log.Error("JsConfig.DateHandler != DateHandler.ISO8601. FIXING");
            JsConfig.Init(new ServiceStack.Text.Config
            {
                DateHandler = DateHandler.ISO8601,
                AlwaysUseUtc = false,
                TextCase = TextCase.CamelCase,
                ExcludeDefaultValues = false,        // e.g. IsStartupItem=false won't be emitted unless ==true
                IncludeNullValues = false
            });
        }
        if (JsonTypeSerializer.Instance.ObjectDeserializer != JSON.parseSpan) {
            Log.Error("Incorrect JsonTypeSerializer.Instance.ObjectDeserializer. FIXING");
            JS.Configure();
        }

        if (SqlServerDialect.Provider.StringSerializer.GetType() != typeof(JsonStringSerializer)
            || SqliteDialect.Provider.StringSerializer.GetType() != typeof(JsonStringSerializer)
            || SqlServer2017Dialect.Provider.StringSerializer.GetType() != typeof(JsonStringSerializer)) {
            Log.Error("Incorrect SqlServer2017Dialect. FIXING");
            SqlServer2017Dialect.Provider.StringSerializer = new JsonStringSerializer();
        }
    }

What I can’t figure out is why the program is being reconfigured at the same time it is running.
Shouldn’t ServiceStack make sure that all API calls have finished running before resetting? Probably I’m misunderstanding something.

The global state is being reset back to its default state when the shutdown event is fired. It doesn’t have any control of in-flight requests when the App is being shutdown.

We have made a working demo of the problem in this gist using the x gist-new command.

The README explains how to installed it and get the errors pretty quickly (perhaps there are better ways, but we wanted a real DB + real IIS to simulate reality).

We’re using OrmLiteConfig.BeforeExecFilter on every call, and that’s where we catch the problems and log it.

OrmLiteConfig.BeforeExecFilter = dbCmd => {
    Log.Info("Before Exec Filter");
    EnsureSerializersAreCorrect();  // check and log if problems + FIX

Since we fix the serializers in the BeforeExecFilter if they’re off, the database seems to be always consistent, as we see in the Sqlite DB.

With this we’re able to get log output such as:

2025-01-07 11:54:24.154 +01:00 [INF] Loading from Db!
2025-01-07 11:54:24.154 +01:00 [INF] Before Exec Filter
2025-01-07 11:54:24.447 +01:00 [INF] AppHost is disposing...
2025-01-07 11:54:24.574 +01:00 [INF] Before Exec Filter
2025-01-07 11:54:24.574 +01:00 [ERR] JsConfig.DateHandler != DateHandler.ISO8601. FIXING
2025-01-07 11:54:24.587 +01:00 [ERR] Incorrect JsonTypeSerializer.Instance.ObjectDeserializer. FIXING
2025-01-07 11:54:24.587 +01:00 [ERR] AppHost is disposed
2025-01-07 11:54:24.589 +01:00 [INF] Before Exec Filter
2025-01-07 11:54:24.589 +01:00 [ERR] AppHost is disposed

The [INF] AppHost is disposing... I belive comes from ServiceStack.
The [ERR] AppHost is disposed is output from our test program, inside OrmLite’s Before Exec Filter.

So this strengthens the theory that an IIS recycle can happen in the midst of an API call, and the global reset then creates problems for the on-going API calls, since the database connection is shared.

We already know the recycling can happen to APIs mid flight, ServiceStack has no control over APIs that are in-flight when the App is Shutdown.

Did you try re-configuring the JS behavior after the AppHost is Disposed like I suggested?

protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);
    JS.Configure();
}

You’re also not throwing an Exception when the AppHost is disposed in your BeforeExecFilter. What’s the point of this repro?

The point of the reproduction was to confirm the behavior, as well as easily try out solutions, such as the fix in the BeforeExecFilter, and perhaps some hope that this could be fixed at the framework level.

I’m aware that you guys know your own framework inside and out, but some things are good to state to show what we believe (to avoid misunderstanding) as well as for future readers of the forum.

We will try the suggestion in the code, but just JS.Configure won’t fix the wrong DB serializer I guess. There are two different errors (the JS Config + SqlServer2017Dialect.Provider.StringSerializer).

I’ll post the results shortly.

The reason we’re very keen on avoiding the problem altogether (by issuing a FIX right before DB access), is that just exiting doesn’t leave us in a good state.

E.g.

  1. Our API is called
  2. We call another external API, giving us an external ID back
  3. We would save that external ID in our own database, but if we have a “crash” here, we “forget” that ID, and are in a bad state

Hi,

We have added

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
        Log.Warn("FIXING JS Configure after dispose (in AppHost)");
        JS.Configure();
    }

in Configure.AppHost.cs, and after a recycle or two, we get this:

2025-01-07 14:28:19.397 +01:00 [INF] AppHost is disposing...
2025-01-07 14:28:19.561 +01:00 [WRN] FIXING JS Configure after dispose (in AppHost)
2025-01-07 14:28:19.698 +01:00 [INF] Before Exec Filter
2025-01-07 14:28:19.698 +01:00 [ERR] JsConfig.DateHandler != DateHandler.ISO8601. FIXING
2025-01-07 14:28:19.711 +01:00 [ERR] AppHost is disposed
2025-01-07 14:28:19.714 +01:00 [INF] Before Exec Filter
2025-01-07 14:28:19.714 +01:00 [ERR] AppHost is disposed

I also managed to get the other one:

2025-01-07 14:31:44.564 +01:00 [INF] AppHost is disposing...
2025-01-07 14:31:44.566 +01:00 [INF] Before Exec Filter
2025-01-07 14:31:44.567 +01:00 [ERR] Incorrect JsonTypeSerializer.Instance.ObjectDeserializer. FIXING
2025-01-07 14:31:44.567 +01:00 [ERR] AppHost is disposed
2025-01-07 14:31:44.568 +01:00 [INF] Before Exec Filter
2025-01-07 14:31:44.569 +01:00 [ERR] AppHost is disposed
2025-01-07 14:31:44.683 +01:00 [WRN] FIXING JS Configure after dispose (in AppHost)

So I don’t think it works.

Looks like the Before Exec Filter is fired after the AppHost is disposed but before the behavior is reverted.

I’d consider short circuitomg all DB Requests if the AppHost is disposed. If an Exception is thrown during a DB transaction that transaction should be rolled back.

You could also try calling JS.Configure(); if needed within a BeforeExecFilter.

Is this what happens?

Are the resetting of

  • SqliteDialect.Provider.StringSerializer
  • JsonTypeSerializer.Instance.ObjectDeserializer

necessary for the Dispose()? I don’t know the details of Dispose, just reading that MS says The Dispose method is primarily implemented to release unmanaged resources

It’s used to reset Global state to get back to the default behavior and disposes all Registered IOC IDisposable dependencies.

It doesn’t explicitly reset SqliteDialect.Provider.StringSerializer so I’m not sure why you’re seeing that.

You can also choose to not call base.Dispose(disposing) to prevent invoking it’s default Dispose() behavior.

I have tried your suggestion of

This works 100% – I can not get it to fail any more with our demo app. The BeforeExec reports 0 errors (so it’s not needed).

Before committing to this fix, not being an export on Dispose()is this a good way to go forward? Are there any drawbacks that we need to be aware of? We don’t use any unmanaged resources (that we know about).
Will DB connections still be released by OrmLite as well as any other things that ServiceStack keeps, if we skip the base.Dispose in AppHost?

So what we did was:

// in Configure.AppHost.cs
protected override void Dispose(bool disposing)
{
    Log.Warn("AppHost.Dispose(): SKIPPING default Dispose of AppHost due to problems w. resetting formats");
   // no call to base.Dispose()
}

Have a look at the Dispose() implementation that was linked in the post and implement the parts you want. IMO you’ll still want to fire any OnDisposeCallbacks and Dispose of the IOC container and remove the TaskScheduler.UnobservedTaskException event handler:

protected virtual void Dispose(bool disposing)
{
    if (isDisposed) return;
    
    Log.InfoFormat("AppHost is disposing...");
    if (disposing)
    {
        isDisposed = true;
        //clear managed resources here
        foreach (var callback in OnDisposeCallbacks)
        {
            callback(this);
        }

        if (Container != null)
        {
            Container.Dispose();
            Container = null;
        }
            
        TaskScheduler.UnobservedTaskException -= this.HandleUnobservedTaskException;

        Instance = null;
    }
    //clear unmanaged resources here
}

ServiceStack doesn’t keep any DB connections or other active singleton connections, they’re released back to the pool after each usage. Either way they would still be released when the Web App is recycled and AppDomain is shutdown.