A WatermelonDB adapter for AWS Amplify DataStore
This adapter integrates WatermelonDB as a storage adapter for AWS Amplify DataStore, providing an alternative to the default SQLite adapter.
AWS Amplify DataStore provides a programming model for leveraging shared and distributed data:
- π Automatic sync between cloud and local data
- π Built-in auth and conflict resolution
- π GraphQL API integration
- π Cross-platform support - Web, React Native, iOS, Android
WatermelonDB is a reactive database framework built for React and React Native applications:
- π Lazy loading - Records load on demand
- β‘ Native SQLite performance with JSI on React Native
- β¨ Fully reactive - UI updates automatically when data changes
- π Designed for scale - Handles large datasets efficiently
This adapter allows you to use WatermelonDB as the storage engine for Amplify DataStore:
// Standard DataStore setup
import { DataStore } from '@aws-amplify/datastore';
import { SQLiteAdapter } from '@aws-amplify/datastore-storage-adapter';
DataStore.configure({
storageAdapter: SQLiteAdapter
});
// With WatermelonDB adapter
import { WatermelonDBAdapter } from 'amplify-watermelondb-adapter';
DataStore.configure({
storageAdapter: new WatermelonDBAdapter()
});The adapter automatically selects the optimal storage engine for each platform:
| Platform | Storage Engine | Features |
|---|---|---|
| React Native iOS/Android | JSI + SQLite | Native performance with JSI bridge |
| Web | LokiJS + IndexedDB | Browser-optimized with IndexedDB persistence |
| Node.js | better-sqlite3 | Server-grade SQLite performance |
| Fallback | In-Memory | Development and testing scenarios |
This adapter is suitable for applications that:
- π± Use DataStore for offline-first functionality
- π Work with large datasets or complex queries
- β‘ Need reactive UI updates when data changes
- π Want WatermelonDB's performance benefits
- ποΈ Require cross-platform compatibility
npm install amplify-watermelondb-adapter @nozbe/watermelondb
# or
yarn add amplify-watermelondb-adapter @nozbe/watermelondbimport { configureDataStoreWithWatermelonDB } from 'amplify-watermelondb-adapter';
// That's it! DataStore now uses WatermelonDB
configureDataStoreWithWatermelonDB();
// Use DataStore as normal - but faster!
const todos = await DataStore.query(Todo);Already using DataStore? Migration takes 2 minutes:
import { createFallbackConfiguration } from 'amplify-watermelondb-adapter';
import { SQLiteAdapter } from '@aws-amplify/datastore-storage-adapter';
// Your existing configuration
const config = {
authProviders: { /* your auth */ },
syncExpressions: [ /* your rules */ ]
};
// Automatic upgrade with fallback safety net
createFallbackConfiguration(
config,
SQLiteAdapter, // Falls back if needed
{ enableDebugLogging: true }
);Integrates subscription variables from Amplify PR #14564 for multi-tenant GraphQL filtering.
import { WatermelonDBAdapter } from 'amplify-watermelondb-adapter';
const adapter = new WatermelonDBAdapter();
// Configure subscription variables for multi-tenant filtering
adapter.setSubscriptionVariables({
tenantId: 'tenant-456',
userId: 'user-789'
});
// Dynamic schema switching
adapter.setAlternativeSchema(alternativeSchema, () => {
// Your logic to determine which schema to use
return shouldUseAlternative() ? 'alternative' : 'primary';
});Implements connection health monitoring from Amplify PR #14563 with auto-reconnection capabilities.
// Monitor WebSocket connection health
adapter.startWebSocketHealthMonitoring({
interval: 30000, // 30 seconds
onHealthCheck: (isHealthy) => {
console.log(`WebSocket health: ${isHealthy ? 'β
' : 'β'}`);
},
onReconnect: () => {
console.log('Attempting WebSocket reconnection...');
}
});
// Track keep-alive timestamps for debugging
adapter.trackKeepAlive(); // Stores in AsyncStorageimport { getWatermelonDBMetrics } from 'amplify-watermelondb-adapter';
// Monitor your performance gains
const metrics = getWatermelonDBMetrics();
console.log(`Dispatcher: ${metrics.dispatcherType}`); // "jsi" on RN
console.log(`Cache hits: ${metrics.cacheHitRate}%`); // Track efficiencynew WatermelonDBAdapter({
// Optimize for your use case
cacheMaxSize: 500, // More cache for read-heavy apps
cacheTTL: 60 * 60 * 1000, // 1 hour for stable data
batchSize: 5000, // Larger batches for bulk imports
conflictStrategy: 'ACCEPT_REMOTE' // Your sync strategy
});Supports 'in' and 'notIn' operators from Amplify PR #14544 for advanced filtering.
// Query with 'in' operator
const priorityTasks = await DataStore.query(Todo, todo =>
todo.priority.in([1, 2, 3])
);
// Query with 'notIn' operator
const nonUrgentTasks = await DataStore.query(Todo, todo =>
todo.status.notIn(['urgent', 'critical'])
);// WatermelonDB's magic: truly reactive queries
DataStore.observe(Todo).subscribe(msg => {
// Component auto-updates when ANY todo changes
// Even from different screens or background sync!
});- π WatermelonDB Integration - Seamlessly integrates with WatermelonDB's reactive architecture
- π Drop-in replacement - Minimal configuration changes required
- π Full TypeScript - Complete type safety and IntelliSense
- π Automatic fallback - Falls back to in-memory storage if initialization fails
- βοΈ Configurable - Customizable cache, batch size, and conflict resolution
- π οΈ Development-friendly - Comprehensive error handling and debugging support
- π JSI Performance - Leverages WatermelonDB's JSI dispatcher on React Native
- π Cross-platform - Works on iOS, Android, Web, and Node.js
- πΎ Smart Caching - Built-in LRU cache with configurable TTL
- π’ Multi-Tenant Support - Dynamic schema switching for multi-tenant applications
- π‘ Subscription Variables - Filter GraphQL subscriptions per tenant/user (Amplify PR #14564)
- π WebSocket Health Monitoring - Auto-reconnection with health checks (Amplify PR #14563)
- π Keep-Alive Tracking - Debug connection issues with AsyncStorage timestamps
- π Enhanced Operators - Full support for 'in' and 'notIn' query operators (Amplify PR #14544)
// Query products with WatermelonDB's reactive performance
const products = await DataStore.query(Product,
p => p.inStock.eq(true),
{ limit: 1000 }
);// Real-time messaging with reactive updates
DataStore.observe(Message, m =>
m.conversationId.eq(currentChat)
).subscribe(update => {
// UI updates automatically when data changes
});Adapter performance characteristics from automated tests:
π WatermelonDB Adapter Performance Metrics
==========================================
Operation | Average Time
--------------------------|-------------
Adapter Creation | 0.03ms
Config Validation | 0.05ms
Dispatcher Detection | 0.01ms
Schema Version Lookup | 0.02ms
Memory (1000 instances) | 2.65MB
Concurrent Creation | 500 adapters in 0.96ms
Compatible with:
- π AWS Amplify DataStore - v4.x and v5.x
- π GraphQL subscriptions - Full support
- π Multi-auth rules - All authentication strategies
- π Conflict resolution - Version-based and custom strategies
- π Schema migrations - Automatic schema handling
- π DataStore Selective Sync - Predicate-based syncing
- π WatermelonDBAdapter - Core adapter implementation
- π§ Integration helpers - Easy setup utilities
- π Performance monitoring - Metrics collection
- π Migration tools - Upgrade from SQLiteAdapter
- π TypeScript definitions - Full type safety
- π― Examples - Real-world usage patterns
-
π Install the package
npm install amplify-watermelondb-adapter @nozbe/watermelondb
-
π Configure DataStore
import { configureDataStoreWithWatermelonDB } from 'amplify-watermelondb-adapter'; configureDataStoreWithWatermelonDB();
-
π Start using DataStore - Same API, WatermelonDB performance!
| Method | Description |
|---|---|
setSubscriptionVariables(vars) |
Set GraphQL subscription filtering variables for multi-tenant support |
getSubscriptionVariables() |
Get current subscription variables |
setAlternativeSchema(schema, selector) |
Configure alternative schema for runtime switching |
startWebSocketHealthMonitoring(options) |
Start monitoring WebSocket connection health |
stopWebSocketHealthMonitoring() |
Stop WebSocket health monitoring |
trackKeepAlive() |
Store keep-alive timestamp in AsyncStorage |
| Method | Description |
|---|---|
setup(schema, ...) |
Initialize adapter with DataStore schema |
query(model, predicate, pagination) |
Query records with optional filtering |
save(model, condition) |
Save or update a model instance |
delete(model, condition) |
Delete model(s) |
observe(model, predicate) |
Subscribe to real-time changes |
batchSave(model, items) |
Efficiently save multiple items |
Q: Is this production-ready? A: Yes! The adapter has comprehensive test coverage and follows production-grade patterns.
Q: Does it support all DataStore features? A: Yes! The adapter implements the complete DataStore storage interface.
Q: What if WatermelonDB fails to initialize? A: The adapter automatically falls back to in-memory storage to prevent app crashes.
Q: What platforms are supported? A: iOS, Android, Web, and Node.js with automatic platform detection.
- π Report Issues
- π¬ Discussions
- π Stack Overflow
- π AWS Amplify - For the DataStore framework
- π WatermelonDB - For the reactive database architecture
- π React Native - For cross-platform mobile development
MIT License - See LICENSE file for details.
π Built with WatermelonDB's reactive performance for Amplify DataStore π
Bringing WatermelonDB's β‘ performance to AWS Amplify DataStore π