Migrating from Apache Ignite 3.0 to 3.1
Overview
This guide provides step-by-step instructions for migrating Apache Ignite clusters from version 3.0 to version 3.1. Due to architectural changes in 3.1, including the introduction of zone-based replication, migration requires creating a new 3.1 cluster and migrating data using the export/import process.
| 
 Important 
 | 
 This migration requires cluster downtime.  | 
Zone-Based Replication
Apache Ignite 3.1 introduces zone-based replication, replacing the table-based replication model from version 3.0. Table-based replication is still supported, however it will be dropped in a later release.
Table-Based vs Zone-Based Replication
| Aspect | 3.0 Table-Based | 3.1 Zone-Based | 
|---|---|---|
RAFT Groups  | 
Each table creates separate RAFT groups  | 
Tables in same zone share RAFT groups  | 
Example (100 tables)  | 
100 separate RAFT group sets  | 
1 shared RAFT group set  | 
Memory Footprint  | 
Higher with more tables  | 
Significantly reduced  | 
Thread Overhead  | 
Higher (more RAFT groups)  | 
Lower (fewer RAFT groups)  | 
Benefits of Zone-Based Replication
- 
Reduced Memory Footprint: Fewer RAFT groups means lower memory consumption for clusters with many tables
 - 
Lower Thread Overhead: Decreased number of RAFT groups reduces thread management complexity
 - 
Improved Performance: Better resource utilization for multi-table workloads
 - 
Transparent Migration: No changes to user-facing APIs or query behavior
 
| 
 Note 
 | 
 Zone-based replication is an internal cluster optimization. Your applications will continue to work without code changes.  | 
Phase 1: Document Current Environment
Step 1.1: Connect to 3.0 Cluster
Connect to your Apache Ignite 3.0 cluster using the CLI tool:
cd ignite3-cli-3.0.0/bin
./ignite3
Once connected, enter sql execution mode:
sql
Step 1.2: Document All Schemas
List all schemas in your cluster:
-- List all schemas
SELECT * FROM SYSTEM.SCHEMAS;
Save the output to a file for reference during schema recreation.
Step 1.3: Document All Tables
List all tables across all schemas:
-- List all tables
SELECT SCHEMA_NAME, TABLE_NAME
FROM SYSTEM.TABLES
WHERE TABLE_TYPE = 'TABLE'
ORDER BY SCHEMA_NAME, TABLE_NAME;
Save the output to a file for reference during table recreation.
Step 1.4: Document Table Schemas
For each table, capture its complete schema definition:
-- Get detailed schema for each table
SELECT
  SCHEMA_NAME,
  TABLE_NAME,
  COLUMN_NAME,
  TYPE,
  NULLABLE,
  COLUMN_DEFAULT
FROM SYSTEM.TABLE_COLUMNS
WHERE SCHEMA_NAME = 'YOUR_SCHEMA'
ORDER BY TABLE_NAME, ORDINAL_POSITION;
Save the output to a file for reference during schema recreation.
| 
 Important 
 | 
 Document the exact CREATE TABLE statements for all tables. You’ll need these to recreate the schema in 3.1.  | 
Step 1.5: Document Distribution Zones
Capture current distribution zone configuration:
-- Document distribution zones
SELECT * FROM SYSTEM.ZONES;
Save the output to a file for reference during schema recreation.
Step 1.6: Calculate Data Volume
Estimate the size of data to be migrated:
-- Get row count for each table
SELECT
  TABLE_NAME,
  COUNT(*) as ROW_COUNT
FROM your_table
GROUP BY TABLE_NAME;
Save row counts for each table. You’ll use these to verify data integrity after migration.
Step 1.7: Create Schema Recreation Script
Create a SQL script file named schema-recreation.sql containing all CREATE TABLE statements:
-- Example for a table:
CREATE TABLE analytics.events (
  id INT PRIMARY KEY,
  event_time TIMESTAMP NOT NULL,
  user_id VARCHAR(100),
  event_type VARCHAR(50),
  payload VARCHAR(4000)
) WITH (
  -- Document any table options here
);
-- Repeat for all tables
Save the output to a file for reference during schema recreation.
| 
 Warning 
 | 
 Ensure your CREATE TABLE statements include all constraints, indexes, and table options. Missing configuration can lead to performance or data integrity issues.  | 
Phase 2: Export Data from 3.0 Cluster
Step 2.1: Create Export Directory
Create a directory for export files on accessible storage:
mkdir -p /backup/ignite-3.0-export
chmod 755 /backup/ignite-3.0-export
| 
 Note 
 | 
 If using shared network storage, ensure all nodes have write access to this location.  | 
Step 2.2: Choose Export Format
Apache Ignite supports two export formats:
| Format | Advantages | Best For | 
|---|---|---|
CSV  | 
Human-readable, easy to debug, compatible with many tools  | 
Small to medium datasets, troubleshooting  | 
Parquet  | 
Compressed, faster I/O, efficient for large datasets  | 
Large datasets, production migrations  | 
Step 2.3: Export Table Data
Export each table using the COPY INTO command.
CSV Export
-- Export with headers for easier import
COPY FROM (SELECT * FROM analytics.events)
INTO '/backup/ignite-3.0-export/analytics_events.csv'
FORMAT CSV
WITH 'header'='true';
For large tables, export in chunks:
-- Export in chunks by partition
COPY FROM (SELECT * FROM analytics.events WHERE id BETWEEN 0 AND 1000000)
INTO '/backup/ignite-3.0-export/analytics_events_part1.csv'
FORMAT CSV
WITH 'header'='true';
Parquet Export (Recommended)
COPY FROM analytics.events (id, event_time, user_id, event_type, payload)
INTO '/backup/ignite-3.0-export/analytics_events.parquet'
FORMAT PARQUET;
Step 2.4: Automate Exports with Script
Create a shell script to export all tables automatically:
#!/bin/bash
# export-all-tables.sh
BACKUP_DIR="/backup/ignite-3.0-export"
# Array of tables to export (schema.table format)
TABLES=(
  "analytics.events"
  "analytics.users"
  "sales.orders"
  "sales.products"
)
for table in "${TABLES[@]}"; do
  schema=$(echo $table | cut -d'.' -f1)
  tbl=$(echo $table | cut -d'.' -f2)
  echo "Exporting ${table}..."
  ignite sql "COPY FROM (SELECT * FROM ${table}) \
    INTO '${BACKUP_DIR}/${schema}_${tbl}.parquet' \
    FORMAT PARQUET"
  if [ $? -eq 0 ]; then
    echo "✓ ${table} exported successfully"
    # Get row count for verification
    ignite sql "SELECT COUNT(*) as row_count FROM ${table}" > "${BACKUP_DIR}/${schema}_${tbl}.count"
  else
    echo "✗ Failed to export ${table}"
    exit 1
  fi
done
echo "Export complete. Files in ${BACKUP_DIR}"
Make the script executable and run it:
chmod +x export-all-tables.sh
./export-all-tables.sh
Step 2.5: Verify Exports
Check that all export files were created successfully:
# List all export files
ls -lh /backup/ignite-3.0-export/
# Verify file sizes are reasonable (not 0 bytes)
find /backup/ignite-3.0-export/ -size 0
| 
 Caution 
 | 
 Do not proceed to the next phase until all exports are verified. Missing or corrupted export files will result in data loss.  | 
Step 2.6: Stop 3.0 Cluster
Once all exports are verified, gracefully stop all cluster nodes:
# Stop all nodes gracefully
ignite node stop --node node1
ignite node stop --node node2
...
| 
 Warning 
 | 
 After stopping the 3.0 cluster, do not delete any data until the migration is completely verified in the 3.1 cluster.  | 
Phase 3: Set Up 3.1 Cluster
Step 3.1: Download Apache Ignite 3.1
Download the Apache Ignite 3.1 distribution from the official website.
Step 3.2: Configure Cluster Nodes
Update your configuration files from 3.0 to 3.1 format:
Configuration Changes in 3.1
| Change Type | 3.0 Format | 3.1 Format | 
|---|---|---|
Timeout Properties  | 
  | 
  | 
Zone Creation  | 
  | 
  | 
| 
 Tip 
 | 
 Review the Apache Ignite 3.1 documentation for a complete list of configuration changes.  | 
Step 3.3: Start Cluster Nodes
Start each node in your cluster:
# Start each node (repeat for all nodes)
./bin/ignite3 node start --config ignite-config.conf
| 
 Note 
 | 
 By default, nodes load the configuration from   | 
Step 3.4: Initialize the Cluster
Once all nodes are started, initialize the cluster from any node:
ignite cluster init --name=ignite-cluster
Step 3.5: Verify Cluster Topology
Confirm all nodes are part of the cluster:
ignite cluster topology
Expected output should show all nodes in ACTIVE state:
[name=node1, address=192.168.1.10:10800, state=ACTIVE] [name=node2, address=192.168.1.11:10800, state=ACTIVE] ...
Step 3.6: Recreate Schemas
Connect to the cluster and recreate all schemas:
-- Create schemas
CREATE SCHEMA analytics;
CREATE SCHEMA sales;
Step 3.7: Recreate Distribution Zones
If you have custom distribution zones, recreate them:
-- Create distribution zones (if customized)
CREATE ZONE analytics_zone (REPLICAS 3) STORAGE PROFILES['default'];
Step 3.8: Recreate Tables
Execute your saved schema recreation script:
CREATE TABLE analytics.events (
  id INT PRIMARY KEY,
  event_time TIMESTAMP NOT NULL,
  user_id VARCHAR(100),
  event_type VARCHAR(50),
  payload VARCHAR(4000)
);
-- Repeat for all tables
Verify each table was created correctly:
-- Verify table creation
SELECT * FROM SYSTEM.TABLES WHERE TABLE_NAME = 'EVENTS';
| 
 Important 
 | 
 Ensure table schemas in 3.1 exactly match the schemas from 3.0. Mismatches will cause import failures.  | 
Phase 4: Import Data into 3.1 Cluster
Step 4.1: Import Individual Tables
Import data for each table using the COPY FROM command.
CSV Import
COPY FROM '/backup/ignite-3.0-export/analytics_events.csv'
INTO analytics.events (id, event_time, user_id, event_type, payload)
FORMAT CSV
WITH 'header'='true', 'batchSize'='2048';
Parquet Import (Recommended)
COPY FROM '/backup/ignite-3.0-export/analytics_events.parquet'
INTO analytics.events (id, event_time, user_id, event_type, payload)
FORMAT PARQUET
WITH 'batchSize'='2048';
Step 4.2: Automate Imports with Script
Create a shell script to import all tables:
#!/bin/bash
# import-all-tables.sh
BACKUP_DIR="/backup/ignite-3.0-export"
# Array of tables to import
TABLES=(
  "analytics.events:id,event_time,user_id,event_type,payload"
  "analytics.users:user_id,username,email,created_at"
  "sales.orders:order_id,customer_id,order_date,total"
  "sales.products:product_id,name,price,stock"
)
for entry in "${TABLES[@]}"; do
  table=$(echo $entry | cut -d':' -f1)
  columns=$(echo $entry | cut -d':' -f2)
  schema=$(echo $table | cut -d'.' -f1)
  tbl=$(echo $table | cut -d'.' -f2)
  echo "Importing ${table}..."
  ignite sql "COPY FROM '${BACKUP_DIR}/${schema}_${tbl}.parquet' \
    INTO ${table} (${columns}) \
    FORMAT PARQUET \
    WITH 'batchSize'='2048'"
  if [ $? -eq 0 ]; then
    echo "✓ ${table} imported successfully"
    # Verify row count
    actual_count=$(ignite sql "SELECT COUNT(*) FROM ${table}" | grep -oE '[0-9]+')
    expected_count=$(cat "${BACKUP_DIR}/${schema}_${tbl}.count" | grep -oE '[0-9]+')
    if [ "$actual_count" == "$expected_count" ]; then
      echo "✓ Row count verified: ${actual_count}"
    else
      echo "✗ Row count mismatch: expected ${expected_count}, got ${actual_count}"
      exit 1
    fi
  else
    echo "✗ Failed to import ${table}"
    exit 1
  fi
done
echo "Import complete."
Make the script executable and run it:
chmod +x import-all-tables.sh
./import-all-tables.sh
Step 4.3: Verify Data Integrity
After imports complete, perform thorough verification:
Row Count Verification
-- Compare row counts
SELECT COUNT(*) FROM analytics.events;
Compare with the saved row counts from your 3.0 cluster.
Data Sampling
-- Spot check data
SELECT * FROM analytics.events LIMIT 10;
-- Verify no NULL values in NOT NULL columns
SELECT COUNT(*) FROM analytics.events
WHERE event_time IS NULL;
-- Check date ranges are preserved
SELECT MIN(event_time), MAX(event_time)
FROM analytics.events;
Create Verification Script
Automate verification across all tables:
#!/bin/bash
# verify-migration.sh
echo "=== Migration Verification Report ==="
echo
TABLES=(
  "analytics.events"
  "analytics.users"
  "sales.orders"
  "sales.products"
)
BACKUP_DIR="/backup/ignite-3.0-export"
for table in "${TABLES[@]}"; do
  schema=$(echo $table | cut -d'.' -f1)
  tbl=$(echo $table | cut -d'.' -f2)
  echo "Table: ${table}"
  # Get current count
  current=$(ignite sql "SELECT COUNT(*) FROM ${table}" | grep -oE '[0-9]+')
  echo "  Current row count: ${current}"
  # Get expected count
  expected=$(cat "${BACKUP_DIR}/${schema}_${tbl}.count" | grep -oE '[0-9]+')
  echo "  Expected row count: ${expected}"
  if [ "$current" == "$expected" ]; then
    echo "  Status: ✓ PASS"
  else
    echo "  Status: ✗ FAIL"
  fi
  echo
done
| 
 Caution 
 | 
 Do not proceed with application cutover until all verification checks pass successfully.  | 
Phase 5: Update Client Applications
Step 5.1: Update Connection Configuration
Update application configuration to point to the 3.1 cluster:
# Old 3.0 connection
ignite.endpoints=old-node1:10800,old-node2:10800,old-node3:10800
# New 3.1 connection
ignite.endpoints=new-node1:10800,new-node2:10800,new-node3:10800
Step 5.2: Review API Changes
Check for deprecated APIs in your client code:
Java API Changes
// Deprecated in 3.1
ignite.clusterNodes()
// Replace with
ignite.cluster().nodes()
| 
 Tip 
 | 
 Refer to the Apache Ignite 3.1 release notes for a complete list of API changes: https://ignite.apache.org/releases/3.1.0/release_notes.html  | 
Step 5.3: Test Client Connectivity
Before switching production traffic, test connectivity:
// Connection test
try (IgniteClient client = IgniteClient.builder()
    .addresses("new-node1:10800", "new-node2:10800", "new-node3:10800")
    .build()) {
    // Verify connectivity
    Collection<ClusterNode> nodes = client.cluster().nodes();
    System.out.println("Connected to " + nodes.size() + " nodes");
    // Test data access
    Table table = client.tables().table("analytics.events");
    RecordView<Tuple> view = table.recordView();
    Tuple record = view.get(null, Tuple.create().set("id", 1));
    System.out.println("Sample record retrieved: " + record);
}
Once the connection is confirmed, gradually migrate traffic.
Phase 6: Post-Migration Verification
Step 6.1: Verify Zone-Based Replication
Confirm zone-based replication is active by checking cluster startup logs:
# Check node logs for confirmation
grep "Zone based replication" /path/to/node/logs/*.log
Expected output:
Zone based replication: true
Verify zones are properly configured:
SELECT * FROM SYSTEM.ZONES;
Apache, Apache Ignite, the Apache feather and the Apache Ignite logo are either registered trademarks or trademarks of The Apache Software Foundation.
