Migrate from Self-Hosted PostgreSQL to Xata
Learn how to migrate your self-hosted PostgreSQL database to Xata using xata clone. Step-by-step instructions for configuring the migration.
Prerequisites
- Self-hosted PostgreSQL instance
- Access to PostgreSQL configuration files
- Xata account and project setup
- Network access to your PostgreSQL server
Create Snapshot User
Connect to your PostgreSQL instance and create a dedicated user for migration:
-- Create snapshot user (no REPLICATION privilege needed)
CREATE USER xata_snapshot WITH LOGIN PASSWORD 'your_secure_password';
-- Grant necessary privileges
GRANT SELECT ON ALL TABLES IN SCHEMA public TO xata_snapshot;
GRANT USAGE ON SCHEMA public TO xata_snapshot;
-- Grant privileges on future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO xata_snapshot;
Network Configuration
Option 1: Direct Connection
If your PostgreSQL server is accessible from the internet:
-
Ensure PostgreSQL is listening on the correct interface:
# In postgresql.conf listen_addresses = '*'
-
Configure firewall to allow PostgreSQL port (5432):
# Linux (ufw) sudo ufw allow 5432/tcp # Linux (iptables) sudo iptables -A INPUT -p tcp --dport 5432 -j ACCEPT # macOS sudo pfctl -e # Add rule to /etc/pf.conf
Option 2: SSH Tunnel (Recommended)
For better security, use SSH tunneling:
# Create SSH tunnel
ssh -L 5432:localhost:5432 user@your-postgres-server
# Then connect to localhost:5432 from your migration machine
Option 3: VPN Connection
If you have a VPN setup:
- Connect to your VPN
- Use the internal IP of your PostgreSQL server
- Ensure VPN allows PostgreSQL traffic
Get Connection String
Connection String Format
postgresql://xata_snapshot:your_password@your-server-ip:5432/your_database
SSL Configuration
If you have SSL certificates configured:
postgresql://xata_snapshot:your_password@your-server-ip:5432/your_database?sslmode=require
If you don't have SSL configured:
postgresql://xata_snapshot:your_password@your-server-ip:5432/your_database?sslmode=disable
Initialize Xata Project
Set up your Xata project configuration:
xata init
Configure the Migration
Set up your clone configuration with optional anonymization:
# Set your source URL
export XATA_CLI_SOURCE_POSTGRES_URL="postgresql://xata_snapshot:your_password@your-server-ip:5432/your_database"
# Configure anonymization rules
xata clone config --source-url $XATA_CLI_SOURCE_POSTGRES_URL --mode prompt
Start the Migration
Begin the data transfer:
# Start the migration
xata clone start --source-url $XATA_CLI_SOURCE_POSTGRES_URL
Monitor Progress
Check the migration status:
xata clone status
Verification
After migration, verify your data:
-
Connect to Xata Branch:
xata branch url
-
Check Data Integrity:
-- Compare row counts SELECT COUNT(*) FROM your_table; -- Check sample data SELECT * FROM your_table LIMIT 10;
-
Test Relationships: Verify foreign key relationships work correctly
Troubleshooting
Common Issues
-
Connection Refused:
- Check if PostgreSQL is running
- Verify the port is correct (default 5432)
- Check firewall settings
- Ensure PostgreSQL is listening on the correct interface
-
Permission Denied:
- Verify the snapshot user has correct privileges
- Check that the user has sufficient permissions
- Ensure pg_hba.conf allows connections
-
Configuration Not Applied:
- Restart PostgreSQL after configuration changes
- Check PostgreSQL logs for errors
- Verify configuration file syntax
-
Network Issues:
- Test connectivity with
telnet your-server-ip 5432
- Check if the server is reachable from your migration machine
- Verify DNS resolution if using hostnames
- Test connectivity with
PostgreSQL Logs
Check PostgreSQL logs for errors:
# Common log locations:
# Linux: /var/log/postgresql/postgresql-{version}-main.log
# macOS: /usr/local/var/log/postgresql.log
# Windows: PostgreSQL installation directory
# Check logs in real-time
tail -f /var/log/postgresql/postgresql-{version}-main.log
Using pg_dump as Alternative
If xata clone
cannot be used, you can use pg_dump
:
# Create a dump
pg_dump --format=custom -h your-server-ip -U xata_snapshot -d your_database -f backup.dump
# Get Xata connection string
xata branch url
# Restore to Xata
pg_restore --dbname "your-xata-connection-string" backup.dump
Security Best Practices
- Use SSH tunneling when possible
- Configure firewall rules to limit access
- Use strong passwords for replication users
- Enable SSL if PostgreSQL is exposed to the internet
- Monitor access logs regularly
Performance Considerations
Large Databases
For large databases, consider:
-
Increase WAL settings:
# In postgresql.conf max_wal_senders = 20 max_replication_slots = 10
-
Optimize network:
- Use wired connections when possible
- Ensure sufficient bandwidth
- Consider running migration during low-traffic periods
-
Monitor resources:
- Check CPU and memory usage
- Monitor disk I/O
- Watch network utilization
Next Steps
- Explore Xata branching for development workflows
- Learn about schema changes with zero downtime
- Set up continuous sync for ongoing replication
- Consider deployment options for your Xata instance