Migrate from Nhost to Appwrite

Appwrite Migrations can import users, databases and files from Nhost, but functions, Hasura GraphQL queries and some rows need hands-on rework. This page maps what moves cleanly and how to plan the cutover.

On this page

Migrate from Nhost to Appwrite: what moves and what does not

If your renewal, pricing change or data residency concern is pushing you off Nhost, the short answer is this: users, files and data can move with documented tooling, but your Hasura GraphQL queries, serverless functions and some rows will need to be rebuilt by hand. Appwrite's Migrations feature imports Nhost projects, so the bulk of the data work is not the hard part. The hard part is the application layer, where client code that calls GraphQL must be rewritten against Appwrite's Auth, Databases, Storage and Functions APIs. Plan for that rewrite first, because it sets the timeline more than the data copy does.

Platform or backend engineers usually do this work, often with an implementation partner who handles the migration runbook, the target environment and cutover testing. Expect a short, repeatable import for users and files and a longer, iterative effort for schema mapping, permission rules and function ports. Appwrite is licensed under the BSD 3-Clause License, and the self-hosted edition runs in your own cloud account, data center or air-gapped network. Confirm with your team which of the Appwrite services you need in production, because the Appwrite README lists Auth, Databases, Storage, Functions, Sites, Messaging, Firewall, Realtime and MCP, and not every feature will be needed on day one.

Before you commit, run a pilot import of one non-sensitive project. Check that password hashes import in a form Appwrite accepts, since the Users API supports several hash types, and confirm that every row imports with the expected types and relationships. Ask your implementation partner to document which Hasura permissions map to Appwrite permissions and which need redesign. Also plan for operations: the self-hosted Helm chart runs its built-in PostgreSQL, Redis, ClickHouse and object storage as single replicas, so production data should sit on managed services or operators with replication. Review the Appwrite self-hosting installation guide for the baseline before you size the target environment.

Which Nhost capabilities map to Appwrite, and which need rework

This table maps each Nhost component to its closest Appwrite counterpart and marks it as clean, needs rework or gap. Read the status column first, then the notes, since most migration effort sits in functions, Hasura-specific logic and a subset of rows. Confirm every Hasura feature you rely on against your own metadata before you commit to a schedule.

Nhost componentAppwrite counterpartStatusNotes for the migration
Postgres dataDatabases on PostgreSQLNeeds reworkAppwrite 2.0 provisions PostgreSQL by default, but data is modeled as Appwrite collections and attributes, so schemas, types and relations need mapping and some rows may need manual reshaping.
Hasura GraphQL queriesAppwrite Databases client and server SDKsNeeds reworkEvery GraphQL query and mutation in your app must be rewritten against Appwrite APIs. Confirm how your client code calls Hasura before estimating effort.
Hasura permissionsAppwrite permissions on documents and collectionsNeeds reworkRow-level rules written in Hasura metadata must be restated as Appwrite permissions. Review each role against the new model.
Hasura event triggers or custom resolversAppwrite FunctionsGapNo direct equivalent is documented here. Confirm whether each trigger or resolver can be rebuilt as an Appwrite Function or a client-driven flow in your environment.
Nhost Auth users and sessionsAppwrite AuthNeeds reworkAppwrite's Users API accepts several imported password hash formats, so confirm your Nhost hash type before planning password continuity. Session tokens and sign-in flows change.
Nhost Storage filesAppwrite Storage bucketsCleanFiles can be imported with Appwrite Migrations, but bucket structure, file IDs and access rules should be checked after import.
Nhost FunctionsAppwrite Functions on the Open Runtimes executorNeeds reworkRuntimes, dependencies and environment variables differ. Each function must be rebuilt and tested, and this is usually the largest manual item.
Realtime subscriptions via GraphQLAppwrite RealtimeNeeds reworkSubscriptions must be reimplemented with Appwrite Realtime channels in the client code.
DocumentsDB and VectorsDBAppwrite 2.0 optional databasesGapThese ship disabled and need PostgreSQL and MongoDB engines that a stock install does not deploy. Enable them only if your plan requires them.

Which data, identities and integrations to move

Nhost projects bundle a Postgres database, Hasura metadata, auth users, storage files and functions, and each one moves differently. Appwrite Migrations can import some of these directly, while permissions, Hasura metadata and functions need to be rebuilt in Appwrite terms. Confirm the exact Nhost export formats in the Migrations docs before you scope the work.

Appwrite Migrations for Nhost

Appwrite's Migrations feature imports Nhost projects, so it is the first path to test on a copy of your data. Run it against a staging Appwrite project, then compare record counts, user totals and file counts with the Nhost source. Confirm in the Migrations docs which Nhost resources the importer covers and which ones it skips, because that list sets the manual scope. Record the result of each run so the cutover checklist reflects what actually moved.

User accounts and password hashes

Users can move without a forced password reset only if Appwrite accepts the hash type Nhost exports. Appwrite's Users API accepts several hash types, including bcrypt, Argon2, Scrypt and SHA variants. Confirm which algorithm and parameters Nhost Auth uses for your project, and test a sample login on the imported account before you plan a reset campaign. Users who signed in with OAuth or magic links have no password hash to move, so list those accounts separately.

Storage files and buckets

Files in Nhost Storage are stored as objects with metadata, and Appwrite organizes them into buckets with their own permission sets. Map each Nhost bucket to an Appwrite bucket and decide which file-level permissions must carry over. Check file sizes against the bucket limits of your self-hosted install, and verify that download URLs in your client code point to the new endpoint. Spot-check checksums on a sample of files after the copy.

Database rows and Postgres schema

Nhost stores application data in Postgres, while Appwrite's Databases service stores records as collections and documents with attribute definitions. Some rows will map cleanly, but relations, JSON columns and custom types usually need a transform step or a schema decision. Export a row count per table, load it into Appwrite, and reconcile the totals. Expect manual work for any table that depends on Postgres features Appwrite collections do not model directly.

Functions and serverless logic

Nhost functions are Node.js handlers that Appwrite does not run from the same source, so each one needs to be rewritten as an Appwrite Function with its own runtime, environment variables and triggers. Inventory every function, its schedule and every external service it calls. Plan to redeploy and test each one in staging before the cutover, because the import process does not carry over the logic.

Hasura metadata, permissions and auth providers

Hasura metadata defines the GraphQL schema, relationships and row-level permissions that protect your data. These rules have no direct import into Appwrite, so you must rebuild them as Appwrite permissions on collections, documents and buckets. Auth provider settings such as OAuth client IDs, redirect URLs and email templates also need manual reconfiguration. Document each rule before you start, and test every role with a live request.

The migration sequence from inventory to decommission

This sequence moves one Nhost project to self-hosted Appwrite in five controlled phases, so each data set is counted, tested and signed off before users depend on it. The end state is a verified Appwrite deployment and a retired Nhost project with a recorded evidence trail.

  1. Inventory tables, users, files, functions and clients

    List every Postgres schema and table, every Hasura table, relationship, permission and event trigger, every auth user and provider, every storage bucket, every serverless function and each client app that calls them. Record which items the Appwrite Migrations feature can import directly and which need rebuilding by hand, which in practice is usually functions and some row-level logic. The output is a signed inventory with a row count per table, a user count per auth provider and a file count per bucket. The step is done when the engineering owner and the data owner both approve it.

  2. Run a pilot migration on self-hosted Appwrite

    Install a non-production self-hosted Appwrite instance, following the installation guide for the current release, and run Appwrite Migrations against a copy of the Nhost project. Import users first, then databases and files, and log every item the import skips or transforms. Test a sample of migrated users by logging in with their existing passwords, which confirms that the hash algorithm and parameters were carried over correctly. The step is done when the pilot reports match the inventory counts and the skipped list is fully assigned to a rebuild task.

  3. Rebuild functions and replace Hasura queries

    Rewrite each serverless function for the Appwrite Functions runtime and replace each Hasura GraphQL query and mutation with calls to the Appwrite Databases and Auth APIs in the client code. Test every changed call against the pilot data, comparing the returned records with the same records from Nhost. The output is a tested function set and a client build that targets Appwrite. The step is done when each function has a passing test and no client path still calls the Nhost endpoint.

  4. Verify data and run both backends in parallel

    Run a fresh full migration close to the planned cutover, then compare each table by row count and checksum of sampled key fields, each bucket by file count and file checksums, and each user list by login results. Keep the Nhost project live and run the client in a staging channel pointed at Appwrite, reviewing error logs and performance. Agree a user-facing cutover plan that states the notice period, the read-only window and the support contact. The output is a reconciliation report and an approved cutover runbook.

  5. Cut over during a read-only window

    Put Nhost into read-only mode for writes, run a final incremental import of rows, users and files written since the verification run, and repeat the row, user and checksum comparisons. Switch the client configuration and DNS or environment values to the Appwrite endpoint, then test sign-in, a read, a write and a file download with a real user account. Keep the rollback path documented until the checks pass. The output is a signed cutover record listing the final counts and the time the switch completed.

  6. Decommission Nhost and retain evidence

    After the Appwrite project has run in production through an agreed observation period, export a final archive of the Nhost database, storage and auth data to retention storage that your policy defines, then shut down the Nhost project and revoke its keys and service accounts. Remove DNS records, webhooks and secrets that still point to Nhost. The output is a retained archive with checksums, a list of revoked credentials and a decommission record that auditors can review. The step is done when no system references Nhost and the archive restore has been tested.

How the move differs by app size and starting point

A small app with a handful of tables, a modest user base and few server-side functions is usually the simplest case. The data volume is typically small, so the export and import steps are short, and most of the time goes into checking results rather than moving bytes. Appwrite Migrations can pull users, databases and files from an Nhost project, and the remaining work is mainly verification and client updates.

  • User import: Confirm which password hash format Nhost exported and whether Appwrite's Users API accepts it, so users do not need forced resets.
  • Table mapping: Check that each Postgres table maps cleanly to an Appwrite database collection, including primary keys, relations and default values.
  • Client switch: Plan the change from the Nhost GraphQL client to the Appwrite SDK as one release, since a small app has few screens to update.
  • Functions: Count the functions. A few small ones are often quick to port by hand.
  • Recurring cost: Compare the Appwrite Cloud Free plan limits with self-hosting, since the Free plan pauses after inactivity.

Ask the team to confirm the exact user count, the number of tables and functions, and whether any authentication providers beyond email are in use.

What running Appwrite self-hosted requires

Running Appwrite yourself starts with a documented baseline: 2 CPU cores, 4 GB of RAM, 2 GB of swap and Docker Compose version 2, with installation driven by a docker run command using the appwrite/appwrite:2.5.0 image and a setup wizard on port 20080. That baseline fits a proof of concept or a small internal environment. It does not describe a production footprint, and the team should size hosts for its own user counts, storage and function workloads. The sample Docker Compose file runs PostgreSQL, Redis, Traefik, ClickHouse, the Appwrite API, workers, realtime and console services, plus an Open Runtimes executor for functions. Each of those containers is a component your team patches, monitors and restarts, so plan for that operational surface before the migration starts. Confirm the current requirements in the Appwrite self-hosting installation guide for the version you intend to deploy.

The Helm chart is the more relevant path for production, and its documentation sets a clear limit. The built-in PostgreSQL, Redis, ClickHouse and object storage each run a single replica without replication or failover, so a node loss or disk failure in those components interrupts the platform. For a backend that now holds migrated user accounts and application data, the practical choice is to point Appwrite at managed PostgreSQL, a managed Redis-compatible service and an S3-compatible object store, or to run each of them under a dedicated operator with replication. Decide this before cutover, because moving the datastores later means another data migration. Ask your platform team which of these services already have backup, restore and on-call ownership in your environment.

Appwrite Cloud pricing does not give you a cost basis for self-hosting. The hosted plans bundle bandwidth, storage, backups and support into a subscription, while a self-hosted deployment converts those into servers, managed datastores, object storage, load balancing, monitoring and staff time. Your team owns every upgrade, including the move from one release line to another, and every backup and restore test, since no vendor backup service comes with the self-hosted install. Set a regular upgrade cadence, verify restores into a separate environment, and assign who responds when a function runtime or worker fails. Support for the open-source edition is community-based, so budget for internal expertise or a retainer if you need guaranteed response.

What drives the cost and duration of the migration

This table lists the factors that most change the effort of moving an Nhost project to Appwrite, why each one matters, and how to keep it manageable. Use it to scope your own project and to shape the items you ask a partner to price in writing, since no fixed fee or duration applies across projects.

DriverWhy it changes effortHow to reduce it
Hasura permission rules and functionsHasura row and column permissions must be re-expressed as Appwrite permissions on documents, buckets and teams, and each Nhost function must be rewritten for Appwrite Functions and the Open Runtimes executor. Functions are a manual step in Appwrite Migrations.Inventory every permission rule and function before scoping. Group rules by access pattern so several collections can share one permission design.
Hasura GraphQL queries in client codeEvery GraphQL query, subscription and mutation in the frontend or mobile app must be replaced with Appwrite SDK calls, and response shapes change. This is often the largest share of client work.Export the list of operations from your client code and map each one to an Appwrite SDK call. Retire unused queries before migrating.
User count and password hash typeAppwrite's Users API accepts several imported hash types, including bcrypt, Argon2, Scrypt and SHA variants. Users whose hashes are not supported in this list may need password resets, which add support work and user friction. Confirm which hash Nhost Auth uses for your project before scoping.Confirm the hash algorithm and parameters with Nhost and test a sample import of real hashes early. Count how many accounts use providers (OAuth, magic links) that carry no password.
File volume and storage structureMigration time and transfer cost grow with the number of files and total bytes. Bucket layout, file metadata and access rules also need mapping to Appwrite buckets and permissions.Measure file count and total size by bucket. Clean up orphaned files, and migrate high-use buckets first if you can run a phased cutover.
Database rows and schema mappingPostgres tables managed through Hasura metadata must be mapped to Appwrite collections, attributes and indexes. Some rows and relations need manual repair or reshaping, especially where Hasura relationships are used heavily.Export the schema and Hasura metadata first, then decide which tables move as-is and which are reshaped. Validate row counts and key relations after each import.
Number of clients to repointEach web app, mobile build, admin console and server integration needs new endpoints, project IDs, SDK versions and auth flows. Mobile releases depend on app store review, which adds calendar time that is outside the migration team's control.List every client and its release process. Plan a compatibility window in which both backends can serve the same users during rollout.
Data residency and hosting choiceWhether you run Appwrite Cloud or self-host changes who operates the stack, which regions are available and what backups you must provide. Self-hosted Appwrite Helm chart docs say the built-in datastores run a single replica without failover, so production usually needs managed services or operators, which adds design and procurement work.Decide the hosting model and the region before scoping. Ask the implementation partner to state which high availability, backup and restore pieces are in scope and which the client provides.
Testing scope and compliance evidencePermission behavior, auth flows, file access and function outputs must be tested against the old Hasura rules to show parity. If you need evidence for a compliance assessment, the test plan and records also take effort. DeployOpen prepares evidence, while independent auditors issue any assessment outcome.Build a parity test set from the existing Hasura rules and sample real user journeys. Agree on pass criteria in writing before the migration starts.

What usually goes wrong and how to prevent it

Most failed Nhost to Appwrite cutovers trace back to a few predictable gaps: authentication, authorization, client configuration, data validation, infrastructure resilience and upgrade discipline. Each card names one failure mode and the check that catches it before users do.

Failed password logins after import

Users imported with their password hashes can often sign in without a reset, but only if the hash algorithm and its parameters arrive intact. Export the Nhost auth hashes and confirm which algorithm and cost settings they use, then map them to a supported Appwrite hash type in the Users API. Run a test login with a non-production account from each hash family before cutover, and plan a reset flow for any users whose hashes cannot be imported.

Permission rules that do not carry over

Hasura row-level permissions are written as GraphQL role rules, and Appwrite uses its own permission model for databases, collections and files. Migrations move data, not the logic that decides who can read or write it. Inventory every Hasura role and its select, insert, update and delete filters, then recreate each one as an Appwrite permission and test it with a user from every role, including denied cases.

File paths and URLs breaking in clients

Storage references stored as Nhost file IDs or URLs stop resolving once files live in Appwrite buckets with different identifiers and endpoints. Mobile and web clients often hard-code the old domain, so the break shows up only after release. Build a mapping table from old file IDs to new Appwrite file IDs, rewrite stored references during the data load, and search client code and configuration for the old domain before the cutover.

Rows that fail validation

Postgres data in Nhost may contain nulls, enum values, date formats or foreign keys that Appwrite attribute definitions reject on import. A load can report success for most rows while a subset is skipped or rejected. Define each collection's attributes and required flags first, run the import against a copy of the production data, and reconcile row counts per table against the source before accepting the migration.

Single-replica data stores in production

The Appwrite Helm chart documentation states that the built-in PostgreSQL, Redis, ClickHouse and object storage each run a single replica without replication or failover. A Kubernetes install that uses these defaults in production has no automatic recovery from a node or pod failure. Decide before go-live whether to use managed PostgreSQL, an operator with replication, and external object storage, and test a restore from backup on a schedule you have written down.

Unplanned upgrades between 2.x releases

Appwrite releases move quickly, and 2.0 changed the engine under the platform and rebuilt the Console. Pulling the latest image tag without a test run can change behavior your migrated app depends on. Pin the image tag in your deployment, such as the 2.5.0 release used in the installation guide, keep a staging instance on the same version as production, and read each release note before moving a version.

Questions teams ask before moving from Nhost to Appwrite

How much does it cost to move from Nhost to Appwrite?

The cost has three parts: the Appwrite hosting bill, the infrastructure or cloud fees, and the engineering time for the migration itself. Appwrite's pricing page lists the Pro plan at $25 per month, with 2 TB bandwidth, 150 GB storage and 200K monthly active users per project. Self-hosting removes that subscription but adds servers that meet the installation guide's minimum of 2 CPU cores and 4 GB of RAM, plus staff time to patch and back them up. The one-time cost is the migration work, mainly functions, client code and rows the import does not carry. The recurring cost is hosting and operations. Ask any quote to split these lines and state who performs each one.

How long does an Appwrite migration from Nhost take?

The duration depends on data volume, the number of functions and GraphQL clients that need rewriting, and how much client code changes. No timeline is published for this specific migration, so ask for a written schedule tied to a defined scope. Importing users, databases and files is usually the fastest part. The slower work is replacing Hasura GraphQL queries with Appwrite SDK calls and re-testing permissions. A small schema with few functions will finish sooner than an app with many custom resolvers. DeployOpen works mostly on fixed scopes, so the deliverables and timeline are agreed in writing before work starts.

Can our team migrate from Nhost to Appwrite without outside help?

Yes, if the team can run Docker Compose or Helm, operate PostgreSQL, and rewrite its client data access. Appwrite's Migrations feature imports Nhost projects, so the import itself does not need custom tooling. Manual work remains for functions, which must be rewritten for Appwrite Functions, and for rows that do not map cleanly to the new schema. Teams without a dedicated platform owner often find the parallel run and cutover harder than the import. Outside help can be scoped to one part of the work, such as the import, hardening or cutover, and the written scope will show which parts your team keeps.

Do users have to reset their passwords after moving to Appwrite?

Not necessarily. Passwords carry over when Appwrite accepts the hash format Nhost stored them in. Appwrite's Users API reference accepts several imported hash types, including bcrypt, Argon2, MD5, PHPass, Scrypt, modified Scrypt and SHA. Confirm which algorithm and parameters your Nhost Auth instance uses, because that decides whether hashes import directly. If the hash is not on the list, the usual fallback is a forced reset or a rehash at login, which must be designed and tested. OAuth and magic-link sign-ins do not depend on stored passwords, but their redirect URLs need reconfiguring.

What happens to Nhost functions and Hasura GraphQL clients?

Both need manual rewriting. Migrations does not convert them. Nhost functions move to Appwrite Functions, which run on an Open Runtimes executor in the self-hosted stack, so each handler must be rewritten for the Appwrite runtime and its SDK. Hasura GraphQL queries, subscriptions and permission rules must be replaced with Appwrite Databases, Realtime calls and Appwrite permissions. Before planning, confirm with Appwrite's current documentation whether any GraphQL interface is offered, and treat each GraphQL client as a rewrite until then. Start with a full inventory of every query, mutation, subscription and function trigger.

How do we run Nhost and Appwrite in parallel during cutover?

Run both backends side by side, but keep one system as the source of truth for each type of data at any moment. A common sequence is:

  • Stand up self-hosted Appwrite in your own environment and verify its configuration.
  • Run an initial import, then repeat the import for changes made since, after confirming how repeat runs behave.
  • Move read traffic first, then writes, one feature area at a time.
  • Keep Nhost read-only for a rollback window.

Decide which system owns sign-ups during the window, because users created in one will not appear in the other unless synced. Write the rollback steps into the scope before cutover begins.

Is self-hosted Appwrite ready for production, and what should we check?

Self-hosted Appwrite can run production workloads when it is planned for them, but the built-in datastores need attention. Appwrite's Helm chart documentation says the built-in PostgreSQL, Redis, ClickHouse and object storage each run a single replica without replication or failover, so production data should use managed services or operators. Appwrite 2.0 made PostgreSQL the default for new installs, and Appwrite 2.5.0 was released on October 13, 2026. Check backups and restore tests, the upgrade path from 1.9.x, monitoring, and who applies security patches. Appwrite is BSD-3-Clause licensed, so the license imposes no per-seat fee on the self-hosted stack.

How DeployOpen scopes and runs this migration

DeployOpen is a Chainscore Labs company that plans, implements, customizes, integrates, hardens, backs up, upgrades, documents and supports self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For a move from Nhost to Appwrite, we start from a written scope covering your users, data, files, functions and client changes, then build and verify the target in your environment.

How we scope

  • Inventory of Nhost auth providers, Postgres tables, Hasura permissions, storage buckets and functions in scope
  • Written decision on which user password hashes migrate and which users need a reset flow
  • Agreed list of client query paths to move from Hasura GraphQL to Appwrite SDK calls

How we build

  • Appwrite self-hosted deployment in your environment, sized against the installation requirements and a production datastore plan
  • Migration runs with Appwrite Migrations for users, databases and files, with manual rebuilds for functions and rows that do not map
  • Test passes on a staging copy covering login, data access rules, file retrieval and realtime behavior before any cutover

How we hand over

  • Runbook covering cutover steps, rollback points and the order in which client apps switch endpoints
  • Documentation of configuration, secrets handling, backup schedule and restore test results in your environment
  • Evidence pack for your auditors or compliance team, prepared by us but issued only by independent auditors

How we support

  • Ongoing support, upgrades and continuous testing are available as a retainer after handover
  • Upgrade planning across Appwrite releases, including the migration steps a major version requires
  • Scope changes handled as written amendments before additional work starts

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.