> ## Documentation Index
> Fetch the complete documentation index at: https://perplayerkit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate PerPlayerKit Data Between Storage Backends

> Move your PerPlayerKit kit data from SQLite to MySQL, PostgreSQL, or Redis using the built-in migration command — with zero data loss.

If your server is growing and you need to move from the default SQLite database to MySQL, PostgreSQL, or Redis — or switch between any two supported backends — PerPlayerKit includes a built-in migration command that copies all kit data from one storage system to another. The process is fully asynchronous, meaning the server stays online and functional throughout. No third-party tools or manual SQL exports are required.

## Supported Storage Backends

| Type         | Use Case                                          |
| ------------ | ------------------------------------------------- |
| `sqlite`     | Single-server setups; the default out of the box  |
| `mysql`      | Multi-server or larger deployments                |
| `postgresql` | Multi-server or larger deployments                |
| `redis`      | High-performance, distributed network setups      |
| `yml`        | Development and testing only — not for production |

## Migration Command

Run the following command in-game or from the server console to migrate between backends:

```bash theme={null}
/perplayerkit migrate <source> <destination>
```

**Permission required:** `perplayerkit.admin`

**Examples:**

```bash theme={null}
/perplayerkit migrate sqlite mysql
/perplayerkit migrate sqlite postgresql
/perplayerkit migrate mysql redis
/perplayerkit migrate redis sqlite
```

<Warning>
  Always back up your data before running a migration. For SQLite, copy the `database.db` file from your plugin's data folder to a safe location. For YAML storage, copy `please-use-a-real-database.yml`. Skipping this step means you have no recovery path if something goes wrong.
</Warning>

## Step-by-Step Migration

<Steps>
  <Step title="Back up your existing data">
    Stop the server or ensure no active writes are happening, then copy your current database file to a safe backup location. For SQLite this is `plugins/PerPlayerKit/database.db`.
  </Step>

  <Step title="Configure the destination storage in config.yml">
    Add the credentials and connection details for your target backend before running the migration. The plugin must be able to connect to the destination before any data is transferred.

    <Tabs>
      <Tab title="MySQL">
        ```yaml config.yml theme={null}
        mysql:
          host: "localhost"
          port: "3306"
          dbname: "kitdatabase"
          username: "username"
          password: "pa55w0rd"
          useSSL: false
          maximumPoolSize: 10
        ```
      </Tab>

      <Tab title="PostgreSQL">
        ```yaml config.yml theme={null}
        postgresql:
          host: "localhost"
          port: "5432"
          dbname: "kitdatabase"
          username: "username"
          password: "pa55w0rd"
          useSSL: false
          maximumPoolSize: 10
        ```
      </Tab>

      <Tab title="Redis">
        ```yaml config.yml theme={null}
        redis:
          host: "localhost"
          port: 6379
          password: "pa55w0rd"
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Test connectivity to the destination database">
    Confirm the database server is running, reachable from your Minecraft server's host, and that the credentials you entered are correct. Firewall rules and open ports are the most common connectivity blockers.
  </Step>

  <Step title="Run the migration command in-game">
    With the destination storage configured, execute the migration command — for example:

    ```bash theme={null}
    /perplayerkit migrate sqlite mysql
    ```

    Progress updates will appear in chat and in the console as data is copied across. The migration runs asynchronously, so the server remains live.
  </Step>

  <Step title="Wait for the completion message">
    Watch for the **"Migration completed successfully!"** confirmation in chat and console. Do not restart the server or change the storage type until this message appears.
  </Step>

  <Step title="Update storage.type in config.yml">
    Switch the active backend to your new storage system:

    ```yaml config.yml theme={null}
    storage:
      type: "mysql"  # replace with your new backend
    ```
  </Step>

  <Step title="Restart the server">
    A full server restart is required for PerPlayerKit to connect to the new storage backend. After restarting, run through the post-migration checklist below to confirm everything is working correctly.
  </Step>
</Steps>

## Post-Migration Verification Checklist

After the server comes back online, verify the following before announcing the migration to players:

* [ ] No storage connection errors in the server console on startup
* [ ] Kit loading works correctly for a test player account
* [ ] Kit saving works correctly and persists across relog
* [ ] Public kits are accessible and load the correct inventories

## Troubleshooting

<AccordionGroup>
  <Accordion title="Connection Error during migration">
    The plugin could not reach the destination database. Check the following:

    * Confirm that the host, port, username, and password in `config.yml` are correct.
    * Ensure the database server process is running.
    * If connecting to a remote host, verify that firewall rules permit inbound connections on the database port (default `3306` for MySQL, `5432` for PostgreSQL, `6379` for Redis).
    * For SSL issues, try setting `useSSL: false` temporarily to isolate the problem.
  </Accordion>

  <Accordion title="Missing data after migration">
    Kit data is not appearing after switching to the new backend. Work through these checks:

    * Open the console and scroll back through the migration output — look for any error lines that indicate skipped or failed entries.
    * Confirm that the migration completed with the success message before you updated `storage.type`.
    * Verify that you saved `config.yml` after updating `storage.type` and that the server was fully restarted, not just reloaded.
  </Accordion>

  <Accordion title="Partial migration — some entries are missing">
    If the migration was interrupted or only transferred a subset of entries, simply run the same migration command again. The process will overwrite any entries that already exist in the destination, and fill in any that were missed the first time — no data in the destination will be corrupted by re-running.
  </Accordion>
</AccordionGroup>

<Note>
  The migration command **copies** data from the source backend to the destination — it does not delete or modify the source. Your original database remains intact after migration, giving you a clean rollback path. To roll back, just revert `storage.type` in `config.yml` to the original backend and restart the server.
</Note>

<Tip>
  For large datasets with thousands of player entries, schedule the migration during a low-traffic window such as a maintenance period. The server stays online throughout, but heavy read/write activity during migration can cause brief delays for players actively saving or loading kits. Progress is logged to the console every 100 entries so you can monitor throughput in real time.
</Tip>
