Migration from V10.x to V11.1
April 7, 2026 · View on GitHub
This guide helps you migrate from Akavache V10.x to V11.1 while preserving your existing data and functionality.
Overview of Changes
Akavache V11.1 introduces significant architectural improvements while maintaining backward compatibility with your data. The main changes are in how you initialize and configure Akavache, not in the core API you use daily.
Breaking Changes
- Initialization Method: The
BlobCache.ApplicationNameandRegistrations.Start()methods are replaced with the builder pattern - Package Structure: Akavache is now split into multiple packages
- Serializer Registration: Must explicitly register a serializer before use
What Stays the Same
- ✅ Core API:
GetObject,InsertObject,GetOrFetchObjectwork identically - ✅ Data Compatibility: V11.1 reads all V10.x data without conversion
- ✅ Cache Types: UserAccount, LocalMachine, Secure, InMemory work the same
- ✅ Extension Methods: All your existing extension method calls work
Migration Steps
Step 1: Update Package References
Old V10.x packages:
<PackageReference Include="Akavache" Version="10.*" />
New V11.1 packages:
<!-- Choose storage backend -->
<PackageReference Include="Akavache.Sqlite3" Version="11.1.*" />
<!-- Choose serializer -->
<PackageReference Include="Akavache.SystemTextJson" Version="11.1.*" />
<!-- OR for maximum compatibility: -->
<PackageReference Include="Akavache.NewtonsoftJson" Version="11.1.*" />
Step 2: Update Initialization Code
Old V10.x Code:
// V10.x initialization
BlobCache.ApplicationName = "MyApp";
// or
Akavache.Registrations.Start("MyApp");
// Usage
var data = await BlobCache.UserAccount.GetObject<MyData>("key");
await BlobCache.LocalMachine.InsertObject("key", myData);
New V11.1 Code:
// V11.1 initialization (RECOMMENDED: Explicit provider pattern)
using Akavache.Core;
using Akavache.SystemTextJson;
using Akavache.Sqlite3;
using Splat.Builder;
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(builder =>
builder.WithApplicationName("MyApp")
.WithSqliteProvider() // REQUIRED: Explicit provider initialization
.WithSqliteDefaults());
// Usage (same API)
var data = await CacheDatabase.UserAccount.GetObject<MyData>("key");
await CacheDatabase.LocalMachine.InsertObject("key", myData);
Step 3: Migration Helper
Create this helper method to ease migration:
public static class AkavacheMigration
{
public static void InitializeV11(string appName)
{
// Initialize with SQLite (most common V10.x setup)
// RECOMMENDED: Use explicit provider initialization
CacheDatabase
.Initialize<SystemJsonSerializer>(builder =>
builder
.WithSqliteProvider() // Explicit provider initialization
.WithSqliteDefaults(),
appName);
}
}
// Then in your app:
AkavacheMigration.InitializeV11("MyApp");
Detailed Migration Scenarios
Scenario 1: Basic V10.x App
Before (V10.x):
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
BlobCache.ApplicationName = "MyWpfApp";
base.OnStartup(e);
}
}
public class DataService
{
public async Task<User> GetUser(int userId)
{
return await BlobCache.UserAccount.GetOrFetchObject($"user_{userId}",
() => apiClient.GetUser(userId),
TimeSpan.FromMinutes(30));
}
}
After (V11.1):
using Akavache.Core;
using Akavache.SystemTextJson;
using Akavache.Sqlite3;
using Splat.Builder;
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(builder =>
builder.WithApplicationName("MyWpfApp")
.WithSqliteProvider()
.WithSqliteDefaults());
base.OnStartup(e);
}
}
public class DataService
{
public async Task<User> GetUser(int userId)
{
// Same API!
return await CacheDatabase.UserAccount.GetOrFetchObject($"user_{userId}",
() => apiClient.GetUser(userId),
TimeSpan.FromMinutes(30));
}
}
Scenario 2: Encrypted Cache
Before (V10.x):
BlobCache.ApplicationName = "MySecureApp";
BlobCache.SecureFileStorage = new EncryptedBlobStorage("password");
After (V11.1):
AppBuilder.CreateSplatBuilder()
.WithAkavache<SystemJsonSerializer>(builder =>
builder.WithApplicationName("MySecureApp")
.WithLegacyFileLocation() // Required to find V10 secure databases
.WithEncryptedSqliteProvider()
.WithSqliteDefaults("password"));
Important: The
WithLegacyFileLocation()call is critical when migrating from V10. Without it, V11 will create new databases in isolated storage directories, and your existing secure cache data will not be found.
Scenario 3: Custom Storage Locations
Before (V10.x):
BlobCache.ApplicationName = "MyApp";
BlobCache.LocalMachine = new SqliteBlobCache(@"C:\MyApp\cache.db");
After (V11.1):
AppBuilder.CreateSplatBuilder()
.WithAkavache<SystemJsonSerializer>(builder =>
builder.WithApplicationName("MyApp")
.WithSqliteProvider()
.WithLocalMachine(new SqliteBlobCache(@"C:\MyApp\cache.db"))
.WithSqliteDefaults());
Scenario 4: Dependency Injection
Before (V10.x):
// V10.x didn't have good DI support
BlobCache.ApplicationName = "MyApp";
container.RegisterInstance(BlobCache.UserAccount);
After (V11.1):
// V11.1 has first-class DI support
AppBuilder.CreateSplatBuilder()
.WithAkavache<SystemJsonSerializer>(
"MyApp",
builder => builder.WithSqliteProvider().WithSqliteDefaults(),
(splat, instance) => container.RegisterInstance(instance));
Serializer Migration
For Maximum Compatibility (Recommended for Migration)
Use Newtonsoft.Json serializer to maintain 100% compatibility:
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<NewtonsoftBsonSerializer>(builder =>
builder.WithApplicationName("MyApp")
.WithSqliteProvider()
.WithSqliteDefaults());
For Best Performance (Recommended for New Code)
Use System.Text.Json for better performance:
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(builder =>
builder.WithApplicationName("MyApp")
.WithSqliteProvider()
.WithSqliteDefaults());
Data Migration
Cross-Serializer Compatibility
V11.1 can read data written by V10.x and different serializers:
// This works! V11.1 can read V10.x data regardless of serializer choice
var oldData = await CacheDatabase.UserAccount.GetObject<MyData>("key_from_v10");
Gradual Migration
You can migrate serializers gradually:
// 1. Start with Newtonsoft for compatibility
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<NewtonsoftBsonSerializer>(/* ... */);
// 2. Later, change to System.Text.Json for performance
// Old data will still be readable!
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(/* ... */);
Platform-Specific Migration
.NET MAUI Migration
Before (V10.x):
public partial class App : Application
{
public App()
{
InitializeComponent();
BlobCache.ApplicationName = "MyMauiApp";
MainPage = new AppShell();
}
}
After (V11.1):
// In MauiProgram.cs
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder.UseMauiApp<App>();
// Initialize Akavache
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(cacheBuilder =>
cacheBuilder.WithApplicationName("MyMauiApp")
.WithSqliteProvider()
.WithSqliteDefaults());
return builder.Build();
}
}
Mobile Platform Packages
Add platform-specific SQLite support:
<!-- For iOS/Android -->
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="2.1.11" />
Testing Your Migration
1. Verify Data Access
// Test that old data is still accessible
try
{
var oldData = await CacheDatabase.UserAccount.GetObject<MyOldDataType>("existing_key");
Console.WriteLine("✅ Migration successful - old data accessible");
}
catch (Exception ex)
{
Console.WriteLine($"❌ Migration issue: {ex.Message}");
}
2. Test New Data Storage
// Test that new data can be stored and retrieved
var testData = new MyDataType { Value = "test" };
await CacheDatabase.UserAccount.InsertObject("migration_test", testData);
var retrieved = await CacheDatabase.UserAccount.GetObject<MyDataType>("migration_test");
Console.WriteLine(retrieved.Value == "test" ? "✅ New storage working" : "❌ Storage issue");
3. Performance Comparison
// Compare V10 vs V11 performance
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < 1000; i++)
{
await CacheDatabase.UserAccount.InsertObject($"perf_test_{i}", new MyData { Value = i });
}
stopwatch.Stop();
Console.WriteLine($"1000 inserts: {stopwatch.ElapsedMilliseconds}ms");
Troubleshooting Migration Issues
Common Issues
1. "No serializer has been registered"
// Fix: Ensure you register a serializer
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<SystemJsonSerializer>(/* ... */);
2. "Provider not found"
// Fix: Call WithSqliteProvider() before WithSqliteDefaults()
.WithSqliteProvider()
.WithSqliteDefaults()
3. Data not found after migration
V11 uses isolated storage directories by default, which differ from V10's file locations. To read existing V10 data, you must use WithLegacyFileLocation() so that V11 looks for database files in the same directories V10 used:
// ✅ CORRECT - Use legacy file locations to find V10 databases
AppBuilder.CreateSplatBuilder()
.WithAkavacheCacheDatabase<NewtonsoftBsonSerializer>(builder =>
builder.WithApplicationName("SameAsV10App") // Must match V10 app name
.WithLegacyFileLocation() // Required to find V10 databases
.WithSqliteProvider()
.WithSqliteDefaults());
// ⚠️ WRONG - Without WithLegacyFileLocation(), V11 creates new empty databases
// in isolated storage and your V10 data will not be found
builder.WithApplicationName("SameAsV10App")
.WithSqliteProvider()
.WithSqliteDefaults();
V11 automatically reads data from V10's CacheElement table when a key is not found in the new CacheEntry table. This backward-compatible read happens transparently — no manual data migration is needed. Just ensure V11 can find the database files by using WithLegacyFileLocation().
You can also pass FileLocationOption.Legacy directly when using CacheDatabase.Initialize:
CacheDatabase.Initialize<NewtonsoftBsonSerializer>(
configure: builder => builder.WithSqliteProvider().WithSqliteDefaults(),
applicationName: "SameAsV10App",
fileLocationOption: FileLocationOption.Legacy);
Migration Checklist
- Updated package references
- Replaced initialization code
- Added explicit provider initialization
- Used
WithLegacyFileLocation()to find existing V10 databases - Tested existing data access
- Verified new data storage
- Updated DI container registration (if applicable)
- Added platform-specific packages (mobile)
- Updated application shutdown code
Performance Considerations
V11.1 generally performs better than V10.x, especially with System.Text.Json:
- System.Text.Json: Faster than V10 across all scenarios
- Newtonsoft.Json: Comparable to V10 for small/medium data, may be slower for very large datasets
For best migration experience:
- Start with Newtonsoft.Json for compatibility
- Migrate to System.Text.Json when ready for optimal performance
Getting Help
If you encounter issues during migration:
- Check the Troubleshooting Guide
- Review the Configuration Documentation
- Ask on ReactiveUI Slack
- File an issue on GitHub
Remember: V11.1 is designed to be a drop-in replacement for V10.x with better performance and more features. Your existing data and most of your code will work without changes!