Data export & migration
How to export your data out of IdentSphere, and how to import data in.
Export
The CLI ships an export command that produces a single tarball with one
file per table, in NDJSON format:
identsphere export --database-url "$DATABASE_URL" --schema identsphere --output ./export.tar.gz
The tarball contains:
users.ndjson
organizations.ndjson
organization_memberships.ndjson
member_invitations.ndjson
user_sessions.ndjson
user_passkeys.ndjson
user_recovery_codes.ndjson
email_verification_tokens.ndjson
email_otp_challenges.ndjson
trusted_browsers.ndjson
platform_admins.ndjson
audit_logs.ndjson
api_keys.ndjson
Each file is one JSON object per line, exactly matching the column shape. Hashed credentials (password_hash, mfa_secret, recovery_codes.code_hash) are preserved — the export is portable to another IdentSphere deployment without re-onboarding users.
::: warning Sensitive content The export contains every secret the SDK persists. Treat the tarball as a top-tier credential and encrypt it at rest. :::
Import
For now, import is "use psql." The export shape mirrors \copy input,
so loading a fresh deployment is:
psql "$DATABASE_URL" -c "CREATE SCHEMA IF NOT EXISTS IdentSphere;"
identsphere migrate up --database-url "$DATABASE_URL" --schema identsphere
for f in *.ndjson; do
table="${f%.ndjson}"
psql "$DATABASE_URL" -c "\\copy IdentSphere.${table} FROM '${f}' WITH (FORMAT csv, ESCAPE '\"')"
done
A first-class IdentSphere import command lands in a later release.
Migrating from another auth system
The most common case: migrating from a legacy auth system (Devise, NextAuth, custom rails auth, etc.).
Password hashes
IdentSphere's verifier accepts bcrypt hashes directly. To migrate:
- Export
email + bcrypt_hashfrom the legacy system. INSERT INTO IdentSphere.users (id, email, password_hash, organization_id, role, status, …)with the bcrypt hash inpassword_hash.- On first login, the SDK silently rehashes to Argon2id.
Existing organizations / tenants
Map your existing tenant table 1:1 to IdentSphere.organizations. The id can
be reused (preserves foreign-key relationships in host tables).
User sessions
DO NOT migrate sessions. The session-token format is IdentSphere-specific. Force a re-login at migration cutover.
MFA secrets
If the source system also uses RFC 6238 TOTP with base32 secrets, you can
copy the secret into users.mfa_secret and set mfa_enabled = true. The
SDK uses SHA-1, 6 digits, 30s — verify the source uses the same.
OAuth / social logins
IdentSphere doesn't keep an external_id mapping for social logins; the email
is the linking key. If the legacy system mapped (provider, external_id) → user, you need to ensure the legacy user's email matches the email the
provider returns today (this is usually fine; emails are stable).
GDPR delete
A "right to be forgotten" delete is host-implemented:
BEGIN;
-- Audit entries: anonymize, don't delete (compliance requires retention).
UPDATE IdentSphere.audit_logs SET actor_id = NULL, metadata = '{}'
WHERE actor_id = '$USER_ID';
-- Sessions / tokens: hard delete.
DELETE FROM IdentSphere.user_sessions WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.user_passkeys WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.user_recovery_codes WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.email_verification_tokens WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.email_otp_challenges WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.trusted_browsers WHERE user_id = '$USER_ID';
DELETE FROM IdentSphere.organization_memberships WHERE user_id = '$USER_ID';
-- User row: anonymize email + clear PII.
UPDATE IdentSphere.users SET
email = id::text || '@anonymized.invalid',
password_hash = '',
display_name = NULL,
phone_number = NULL,
avatar_url = NULL,
bio = NULL,
preferences = NULL,
status = 'deleted'
WHERE id = '$USER_ID';
COMMIT;
Avatars in object storage need a separate sweep.
Backup
Standard Postgres backups (pg_dump, WAL archiving) cover the entire
schema. The SDK doesn't ship a separate backup mechanism.