Run Dexie Cloud on Own Servers
Dexie Cloud is available both as a cloud service and as a on-premise licensed software with source included and private git repo access. The former is the obvious choice while your business is growing but at any time, you will be able to switch over to purchase the software license, giving the following benefits:
- You can customize the software for the needs of your business. Do whatever you like with the software as long as you do not compete with Dexie Cloud. Full git access with history, branches, merge requests and updates.
- You get cost savings if your business explodes - you no longer pay per user / month.
- You can chose whatever cloud vendor and region to run it in or you can host it on bare metal.
Software Architecture
Dexie Cloud consists of a Node.js app and a Postgresql database. A typical cloud setup (like our own) also includes load balancing, auto-scaling, DoS protection (Amazon Elastic beanstalk or Azure Webapps for Node.js). The Postgres service can typically run as a managed database service on Amazon RDS for Postgresql or Azure Database for Postgresql. No matter your choice of cloud provider, the managed app and database services are very easy to get up running with, scalable and take advantage of best-practice architecture for apps and databases. You still got a cloud hosted solution but you will have more control over it and for exploding businesses, the total cost for the software becomes minimal compared to hosted version since there is no per-user cost.
Deploy in Azure
- Follow the guide Azure Database for PostgreSQL to create a Postgresql database.
- Clone the dexie-cloud repo from the URL you got with your on-premise software license.
- cd packages/dexie-cloud-server && npm install
- Follow the guide Azure Webapps for Node.js
- In azure portal, go to settings/configuration of your node app in azure and:
- Add a new SQL Connection string DEXIE_CLOUD pointing out the postgres you set up in earlier steps.
- Add a new application setting DXC_SECRET and set it to a long random string.
- Make sure your app has access to your database: In azure portal, go to settings/Connection Security of your postgres database.
- Deploy the dexie-cloud-server app to azure using the az CLI.
- In the local directory of the git repo, cd to packages/dexie-cloud-server and:
- export DXC_SECRET=<the secret you configured in azure for the same setting>
- export DXC_URL=<The URL to your node app in azure>
- execute
npm run init-cloud
. This will setup required SQL schema and tables in the database. It will also create a dexie-cloud.json / dexie-cloud.key file pair. - To create multiple logical databases in your installation, use
npx dexie-cloud create
, standing in a directory or subdirectory of the new generated files dexie-cloud.json / dexie-cloud.key. - To enable email channel for OTP authentication:
npm run init-email-channel <URL of email web hook>
. The URL must point to a web service that sends emails given the content. TODO: Refer to Web hook docs!
Deploy in Amazon AWS
TBD!
Enable Horizontal Scaling
The default setup of the Dexie Cloud service use a single shard. To add shards, create new postgres databases and note down the
connection string of each of the new databases. To manage and configure shards in your Dexie Cloud cluster, use the npm scripts in the dexie-cloud-server repo add-shard
, update-shard
, move-realms
and remove-shard
.
Zero Downtime Migration of Data
When you’ve successfully deployed the Dexie Cloud software, the next step is to import the database from the hosted Dexie Cloud into your new installation.
- Make sure to stand in a directory or sub directory of your package.json, dexie-cloud.json and dexie-cloud.key files of your new installation on your local machine and that you have the DXC_SECRET and DXC_URL env variables set correctly.
-
npx dexie-cloud start-replication --from <URL of the hosted database> --to <URL of the new database on your own installation>
After OTP authorization, this will start a replication from the hosted database to your database instance. This may take some time depending on the amount of data you are migrating. To view progress, run
npx dexie-cloud replication-progress
. When it shows “in sync”, it’s time for the next step. - Point your web app to your new database URL
db.cloud.configure({databaseUrl: newURL, ...})
and publish the web app. - Now it’s time to start redirecting all your users that haven’t yet updated their web app to the new database:
npx dexie-cloud redirect --from <URL of hosted db> --to <URL of your dexie-cloud-server app>
After OTP authorization, the hosted service will start redirecting ongoing and incoming connections to the new database URL.
- Run
npx dexie-cloud stats --db <URL of hosted database>
regularly to verify that the connections to the hosted database is dropping down to zero. - When connections drop to zero, run
npx delete-db <URL of the hosted database>
. Confirm it in the confirmation email. The hosted service will keep redirecting users to your new database for 6 months after database has been deleted.
Terms
Table of Contents
- API Reference
- Access Control in Dexie Cloud
- Add demo users
- Add public data
- Authentication in Dexie Cloud
- Best Practices
- Building Addons
- Collection
- Collection.and()
- Collection.clone()
- Collection.count()
- Collection.delete()
- Collection.desc()
- Collection.distinct()
- Collection.each()
- Collection.eachKey()
- Collection.eachPrimaryKey()
- Collection.eachUniqueKey()
- Collection.filter()
- Collection.first()
- Collection.keys()
- Collection.last()
- Collection.limit()
- Collection.modify()
- Collection.offset()
- Collection.or()
- Collection.primaryKeys()
- Collection.raw()
- Collection.reverse()
- Collection.sortBy()
- Collection.toArray()
- Collection.uniqueKeys()
- Collection.until()
- Compound Index
- Consistency in Dexie Cloud
- Consistent add() operator
- Consistent remove() operator
- Consistent replacePrefix() operator
- Consuming Dexie as a module
- Custom Emails in Dexie Cloud
- DBCore
- DBCoreAddRequest
- DBCoreCountRequest
- DBCoreCursor
- DBCoreDeleteRangeRequest
- DBCoreDeleteRequest
- DBCoreGetManyRequest
- DBCoreGetRequest
- DBCoreIndex
- DBCoreKeyRange
- DBCoreMutateRequest
- DBCoreMutateResponse
- DBCoreOpenCursorRequest
- DBCorePutRequest
- DBCoreQuery
- DBCoreQueryRequest
- DBCoreQueryResponse
- DBCoreRangeType
- DBCoreSchema
- DBCoreTable
- DBCoreTableSchema
- DBCoreTransaction
- DBCoreTransactionMode
- DBPermissionSet
- Deprecations
- Derived Work
- Design
- Dexie Cloud API
- Dexie Cloud API Limits
- Dexie Cloud Best Practices
- Dexie Cloud CLI
- Dexie Cloud Docs
- Dexie Cloud REST API
- Dexie Cloud Web Hooks
- Dexie Constructor
- Dexie.AbortError
- Dexie.BulkError
- Dexie.ConstraintError
- Dexie.DataCloneError
- Dexie.DataError
- Dexie.DatabaseClosedError
- Dexie.IncompatiblePromiseError
- Dexie.InternalError
- Dexie.InvalidAccessError
- Dexie.InvalidArgumentError
- Dexie.InvalidStateError
- Dexie.InvalidTableError
- Dexie.MissingAPIError
- Dexie.ModifyError
- Dexie.NoSuchDatabaseErrorError
- Dexie.NotFoundError
- Dexie.Observable
- Dexie.Observable.DatabaseChange
- Dexie.OpenFailedError
- Dexie.PrematureCommitError
- Dexie.QuotaExceededError
- Dexie.ReadOnlyError
- Dexie.SchemaError
- Dexie.SubTransactionError
- Dexie.Syncable
- Dexie.Syncable.IDatabaseChange
- Dexie.Syncable.IPersistentContext
- Dexie.Syncable.ISyncProtocol
- Dexie.Syncable.StatusTexts
- Dexie.Syncable.Statuses
- Dexie.Syncable.registerSyncProtocol()
- Dexie.TimeoutError
- Dexie.TransactionInactiveError
- Dexie.UnknownError
- Dexie.UnsupportedError
- Dexie.UpgradeError()
- Dexie.VersionChangeError
- Dexie.VersionError
- Dexie.[table]
- Dexie.addons
- Dexie.async()
- Dexie.backendDB()
- Dexie.close()
- Dexie.currentTransaction
- Dexie.debug
- Dexie.deepClone()
- Dexie.defineClass()
- Dexie.delByKeyPath()
- Dexie.delete()
- Dexie.derive()
- Dexie.events()
- Dexie.exists()
- Dexie.extend()
- Dexie.fakeAutoComplete()
- Dexie.getByKeyPath()
- Dexie.getDatabaseNames()
- Dexie.hasFailed()
- Dexie.ignoreTransaction()
- Dexie.isOpen()
- Dexie.js
- Dexie.name
- Dexie.on()
- Dexie.on.blocked
- Dexie.on.close
- Dexie.on.error
- Dexie.on.populate
- Dexie.on.populate-(old-version)
- Dexie.on.ready
- Dexie.on.storagemutated
- Dexie.on.versionchange
- Dexie.open()
- Dexie.override()
- Dexie.semVer
- Dexie.setByKeyPath()
- Dexie.shallowClone()
- Dexie.spawn()
- Dexie.table()
- Dexie.tables
- Dexie.transaction()
- Dexie.transaction()-(old-version)
- Dexie.use()
- Dexie.verno
- Dexie.version
- Dexie.version()
- Dexie.vip()
- Dexie.waitFor()
- DexieCloudOptions
- DexieError
- Docs Home
- Download
- EntityTable
- Export and Import Database
- Get started with Dexie in Angular
- Get started with Dexie in React
- Get started with Dexie in Svelte
- Get started with Dexie in Vue
- Hello World
- How To Use the StorageManager API
- Inbound
- IndexSpec
- Indexable Type
- IndexedDB on Safari
- Invite
- Member
- Migrating existing DB to Dexie
- MultiEntry Index
- PersistedSyncState
- Privacy Policy
- Promise
- Promise.PSD
- Promise.catch()
- Promise.finally()
- Promise.on.error
- Promise.onuncatched
- Questions and Answers
- Realm
- Releasing Dexie
- Road Map
- Road Map: Dexie 5.0
- Road Map: Dexie Cloud
- Role
- Run Dexie Cloud on Own Servers
- Sharding and Scalability
- Simplify with yield
- Support Ukraine
- SyncState
- Table
- Table Schema
- Table.add()
- Table.bulkAdd()
- Table.bulkDelete()
- Table.bulkGet()
- Table.bulkPut()
- Table.bulkUpdate()
- Table.clear()
- Table.count()
- Table.defineClass()
- Table.delete()
- Table.each()
- Table.filter()
- Table.get()
- Table.hook('creating')
- Table.hook('deleting')
- Table.hook('reading')
- Table.hook('updating')
- Table.limit()
- Table.mapToClass()
- Table.name
- Table.offset()
- Table.orderBy()
- Table.put()
- Table.reverse()
- Table.schema
- Table.toArray()
- Table.toCollection()
- Table.update()
- Table.where()
- The main limitations of IndexedDB
- Transaction
- Transaction.abort()
- Transaction.on.abort
- Transaction.on.complete
- Transaction.on.error
- Transaction.table()
- Tutorial
- Typescript
- Typescript (old)
- Understanding the basics
- UserLogin
- Version
- Version.stores()
- Version.upgrade()
- WhereClause
- WhereClause.above()
- WhereClause.aboveOrEqual()
- WhereClause.anyOf()
- WhereClause.anyOfIgnoreCase()
- WhereClause.below()
- WhereClause.belowOrEqual()
- WhereClause.between()
- WhereClause.equals()
- WhereClause.equalsIgnoreCase()
- WhereClause.inAnyRange()
- WhereClause.noneOf()
- WhereClause.notEqual()
- WhereClause.startsWith()
- WhereClause.startsWithAnyOf()
- WhereClause.startsWithAnyOfIgnoreCase()
- WhereClause.startsWithIgnoreCase()
- db.cloud.configure()
- db.cloud.currentUser
- db.cloud.currentUserId
- db.cloud.events.syncComplete
- db.cloud.invites
- db.cloud.login()
- db.cloud.logout()
- db.cloud.options
- db.cloud.permissions()
- db.cloud.persistedSyncState
- db.cloud.roles
- db.cloud.schema
- db.cloud.sync()
- db.cloud.syncState
- db.cloud.userInteraction
- db.cloud.usingServiceWorker
- db.cloud.version
- db.cloud.webSocketStatus
- db.members
- db.realms
- db.roles
- db.syncable.connect()
- db.syncable.delete()
- db.syncable.disconnect()
- db.syncable.getOptions()
- db.syncable.getStatus()
- db.syncable.list()
- db.syncable.on('statusChanged')
- db.syncable.setFilter()
- dexie-cloud-addon
- dexie-react-hooks
- liveQuery()
- unhandledrejection-event
- useLiveQuery()
- useObservable()
- usePermissions()