<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ishan Anand</title>
    <description>The latest articles on DEV Community by Ishan Anand (@ananis25).</description>
    <link>https://dev.to/ananis25</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1345260%2Fbe503490-3fcc-444d-9b7a-246cb9b20d31.jpeg</url>
      <title>DEV Community: Ishan Anand</title>
      <link>https://dev.to/ananis25</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ananis25"/>
    <language>en</language>
    <item>
      <title>Migrating your data from PlanetScale to Neon</title>
      <dc:creator>Ishan Anand</dc:creator>
      <pubDate>Mon, 11 Mar 2024 15:19:02 +0000</pubDate>
      <link>https://dev.to/ananis25/migrating-your-data-from-planetscale-to-neon-5nd</link>
      <guid>https://dev.to/ananis25/migrating-your-data-from-planetscale-to-neon-5nd</guid>
      <description>&lt;p&gt;PlanetScale &lt;a href="https://PlanetScale.com/blog/PlanetScale-forever" rel="noopener noreferrer"&gt;recently announced&lt;/a&gt; that they are sunsetting their free tier and will no longer be offering it to new users. For users exploring alternative database providers, &lt;a href="https://neon.tech" rel="noopener noreferrer"&gt;Neon&lt;/a&gt; offers an appealing option, as a fully managed Postgres database.&lt;/p&gt;

&lt;p&gt;Neon provides a generous &lt;a href="https://neon.tech/pricing" rel="noopener noreferrer"&gt;free tier&lt;/a&gt;, making it a good fit for small applications and hobby projects. While not a one-to-one replacement (PlanetScale, notably, is a MySQL-compatible database, while Neon is a PostgresQL provider), Neon offers a similar serverless experience and is a reasonable alternative for most use cases.&lt;/p&gt;

&lt;p&gt;This guide will walk you through the process of migrating your data from PlanetScale to Neon. Considering both MySQL and Postgres follow the relational database model, for most applications, the migration process is relatively straightforward.&lt;/p&gt;

&lt;p&gt;We'll use the &lt;a href="https://pgloader.io/" rel="noopener noreferrer"&gt;PGLoader utility&lt;/a&gt; to migrate the data from PlanetScale to Neon. It is an open-source tool that can migrate data from various sources to Postgres, handling data type conversions and other necessary adjustments.&lt;/p&gt;

&lt;p&gt;Note that there might be other inconsistencies depending on the exact set of MySQL features that your application relies on and if there is a Postgres equivalent. These can be addressed during the migration process or adapting the application to Postgres after the migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you begin
&lt;/h2&gt;

&lt;p&gt;Ensure you have the following prerequisites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A Neon account. If you do not have one, sign up at &lt;a href="https://neon.tech" rel="noopener noreferrer"&gt;Neon&lt;/a&gt;. You can also visit their &lt;a href="https://neon.tech/docs/get-started-with-neon/signing-up" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; page for more details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A PlanetScale account and an existing MySQL database there. Presumably, else why'd you be reading this guide :)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A terminal or command-line interface to run &lt;code&gt;pgloader&lt;/code&gt; commands. I'd recommend using a unix-based system, such as macOS or Linux, for a simpler setup.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that Neon's free tier supports databases up to 500 MiB of data, and larger datasets require upgrading to a paid plan. If your dataset is above this size, check out Neon's &lt;a href="https://neon.tech/pricing" rel="noopener noreferrer"&gt;pricing plans&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;It would also be a good idea to review the &lt;a href="https://pgloader.readthedocs.io/en/latest/ref/mysql.html" rel="noopener noreferrer"&gt;Pgloader MySQL to PostgreSQL Guide&lt;/a&gt; to better understand the adjustments needed for your migration and resolve any show-stopping issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetch your PlanetScale credentials
&lt;/h2&gt;

&lt;p&gt;To migrate data from your PlanetScale database, &lt;code&gt;pgloader&lt;/code&gt; needs to authenticate with it. To gather the credentials:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log into your &lt;a href="https://app.PlanetScale.com" rel="noopener noreferrer"&gt;PlanetScale dashboard&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Select the database you want to migrate. From the database page, navigate to the the &lt;code&gt;Passwords&lt;/code&gt; section in the &lt;code&gt;Settings&lt;/code&gt; tab.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Connection strings&lt;/code&gt; section lists the necessary parameters for connecting to your database:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hostname&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;database name&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;username&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;password&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Copy these details for configuring &lt;code&gt;pgloader&lt;/code&gt; later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6onfndxx6bab3nk19uxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6onfndxx6bab3nk19uxy.png" alt="PlanetScale console - credentials"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To illustrate the migration workflow, I set up a database on PlanetScale using the &lt;a href="https://dev.mysql.com/doc/sakila/en/sakila-installation.html" rel="noopener noreferrer"&gt;Sakila&lt;/a&gt; dataset. It is a well-known MySQL test database containing tables and views representing the records for a DVD rental store, making it useful for validating the migration steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up your Neon project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a Neon database
&lt;/h3&gt;

&lt;p&gt;When signing up, Neon prompts you to create a new project. Once you've created a project, a ready-to-use database called &lt;code&gt;neondb&lt;/code&gt; is automatically created for you.&lt;/p&gt;

&lt;p&gt;However, when migrating, you need to create a new database with the same name as your existing PlanetScale database. To create a new database,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to the &lt;a href="https://console.neon.tech/" rel="noopener noreferrer"&gt;Neon console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Select your project and navigate to the &lt;code&gt;Databases&lt;/code&gt; section in the sidebar.&lt;/li&gt;
&lt;li&gt;Click on &lt;code&gt;New Database&lt;/code&gt; and provide the same name as your PlanetScale database. Then, click &lt;code&gt;Create&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Fetch your Neon credentials
&lt;/h3&gt;

&lt;p&gt;Once again, select your project from the console, and navigate to the &lt;code&gt;Connection Details&lt;/code&gt; section in the dashboard. Select the database you want to use for migration from the dropdown menu. Now you can find the Postgres connection details for your Neon database. It will resemble:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

postgres://[username]:[password]@[your-endpoint-id].us-east-2.aws.neon.tech/[dbname]?sslmode&lt;span class="o"&gt;=&lt;/span&gt;require


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcipa1dliaqf5l5r68cr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcipa1dliaqf5l5r68cr7.png" alt="Neon console - credentials"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adjust this string by including your endpoint ID with your password. This is a necessary step to ensure certain older Postgres drivers can still connect to Neon. The modified connection string will look like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

postgres://[username]:endpoint&lt;span class="o"&gt;=[&lt;/span&gt;your-endpoint-id]&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;password]@[your-endpoint-id].us-east-2.aws.neon.tech/[dbname]?sslmode&lt;span class="o"&gt;=&lt;/span&gt;require


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This workaround ensures compatibility with &lt;code&gt;pgloader&lt;/code&gt;. Refer to the &lt;a href="https://neon.tech/docs/connect/connection-errors#d-specify-the-endpoint-id-in-the-password-field" rel="noopener noreferrer"&gt;connection workaround&lt;/a&gt; section of the Neon documentation for more details.&lt;/p&gt;

&lt;p&gt;Keep this connection string handy for configuring &lt;code&gt;pgloader&lt;/code&gt; later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using PGLoader
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Set Up PGLoader
&lt;/h3&gt;

&lt;p&gt;We'll use the &lt;code&gt;pgloader&lt;/code&gt; tool to migrate the data from PlanetScale to Neon, converting MySQL data formats to Postgres-compatible ones and streaming data directly into your Neon database.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;pgloader&lt;/code&gt; following the instructions on &lt;a href="https://pgloader.readthedocs.io/en/latest/install.html" rel="noopener noreferrer"&gt;Installing pgloader&lt;/a&gt; and depending on your operating system. It lists multiple methods, including Docker, Homebrew for macOS, Debian (apt), and RPM packages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're using a macOS machine, using &lt;code&gt;Homebrew&lt;/code&gt; is the simplest method:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

brew &lt;span class="nb"&gt;install &lt;/span&gt;pgloader


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Create a configuration file named &lt;code&gt;config.load&lt;/code&gt; in the directory where you want to run the migration. This file will contain details to connect to both the source and the destination database. It needs to be in the following format:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

load database
  from &amp;lt;source-connection-string&amp;gt;
  into &amp;lt;destination-connection-string&amp;gt;;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using the credentials retrieved before from PlanetScale, we can create a source connection string.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

mysql://[username]:[password]@[hostname]/[database name]?sslmode=require


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace the &lt;code&gt;hostname&lt;/code&gt;, &lt;code&gt;database name&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, and &lt;code&gt;password&lt;/code&gt; with the actual values from your PlanetScale database. For the destination, we can copy over the Neon connection string we fetched and modified earlier, which looks like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

postgres://[username]:endpoint=[your-endpoint-id];[password]@[your-endpoint-id].us-east-2.aws.neon.tech/[dbname]?sslmode=require


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We are now good to go with the configuration file. Note the trailing semicolon following the postgres connection string. This is important for &lt;code&gt;pgloader&lt;/code&gt; to know where the configuration ends.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the Migration
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;pgloader&lt;/code&gt; set up, initiate the migration by running the following command in your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pgloader config.load


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Monitor the output for any errors or messages indicating the migration's progress. &lt;code&gt;PGLoader&lt;/code&gt; doesn't stream logs to the terminal as it migrates the data, so you may need to wait for the process to finish.&lt;/p&gt;

&lt;p&gt;Once finished, you'd see a report summarizing the migration like the one below, including num of rows migrated, time taken, and count of errors encountered.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;LOG report summary reset&lt;br&gt;
             table name     errors       rows      bytes      total time&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    fetch meta data          0         80                     2.204s
     Create Schemas          0          0                     0.491s
   Create SQL Types          0          2                     1.723s
      Create tables          0         32                    11.624s
     Set Table OIDs          0         16                     0.133s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      sakila.rental          0      16044     1.2 MB          2.626s
     sakila.payment          0      16044   962.6 kB          2.408s
  sakila.film_actor          0       5462   146.0 kB          1.948s
   sakila.inventory          0       4581   137.1 kB          2.356s
        sakila.film          0       1000   190.9 kB          2.814s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;sakila.film_category          0       1000    25.7 kB          2.087s&lt;br&gt;
            sakila.city          0        600    21.4 kB          2.547s&lt;br&gt;
         sakila.address          0        603    57.7 kB          2.957s&lt;br&gt;
        sakila.customer          0        599    57.6 kB          3.036s&lt;br&gt;
           sakila.actor          0        200     7.2 kB          3.085s&lt;br&gt;
         sakila.country          0        109     3.5 kB          3.346s&lt;br&gt;
        sakila.category          0         16     0.5 kB          3.481s&lt;br&gt;
        sakila.language          0          6     0.2 kB          3.519s&lt;br&gt;
           sakila.staff          0          2    71.2 kB          3.022s&lt;br&gt;
           sakila.store          0          2     0.1 kB          2.654s&lt;br&gt;
       sakila.film_text          0          0                     2.791s&lt;/p&gt;



&lt;p&gt;COPY Threads Completion          0          4                    11.057s&lt;br&gt;
         Create Indexes          0         42                    16.047s&lt;br&gt;
 Index Build Completion          0         42                     4.386s&lt;br&gt;
        Reset Sequences          0         13                     1.604s&lt;br&gt;
           Primary Keys          0         16                     5.784s&lt;br&gt;
    Create Foreign Keys          0         22                     8.018s&lt;br&gt;
        Create Triggers          0          0                     0.241s&lt;br&gt;
        Set Search Path          0          1                     0.611s&lt;br&gt;
       Install Comments          0          0                     0.000s&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Total import time          ✓      46268     2.8 MB         47.748s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Verify the Migration&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Navigate to your project from the Neon console and go to the &lt;code&gt;SQL Editor&lt;/code&gt; tab. Run a few queries to verify that the tables/views from your PlanetScale database have been migrated to Neon. A couple points to note:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure the database selected in the SQL editor is the one you migrated the data to. You can change the database by clicking on the dropdown at the top of the SQL editor.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PGLoader&lt;/code&gt; creates the migrated tables/views in a schema named the same as the original database. For example, if your PlanetScale database was named &lt;code&gt;sakila&lt;/code&gt;, you'd find the migrated tables in a schema named &lt;code&gt;sakila&lt;/code&gt; in your Neon database.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Things to consider post-migration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Differences between MySQL and Postgres
&lt;/h3&gt;

&lt;p&gt;There are some differences between MySQL and Postgres that you'd need to be cognizant of after switching your application database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Type Incompatibilities&lt;/strong&gt;: MySQL and Postgres have differences in data types that may require manual adjustments. &lt;code&gt;PGLoader&lt;/code&gt; does a best-effort job of mapping data types, but you may need to review and modify the schema post-migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indexing Differences&lt;/strong&gt;: Postgres offers a wider variety of indexing options. Review your indexes for optimization opportunities post-migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Case Sensitivity&lt;/strong&gt;: Postgres and MySQL have different default case-sensitivity behavior for string/text columns. This can affect queries and data retrieval unless accounted for in your application code or database schema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Neon Postgres features
&lt;/h3&gt;

&lt;p&gt;Neon offers multiple features on top of Postgres, both to manage your database and simplify your app development workflows. After migrating to Neon as your application database, you should leverage these. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Branching&lt;/strong&gt;: Neon supports &lt;a href="https://neon.tech/branching" rel="noopener noreferrer"&gt;branching&lt;/a&gt;, that allows you to create a copy of your database for testing and development purposes. This is useful for testing schema/data changes to your application without affecting your production database.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Autoscaling and Autosuspend&lt;/strong&gt;: Neon's &lt;a href="https://neon.tech/docs/introduction/autoscaling" rel="noopener noreferrer"&gt;autoscaling&lt;/a&gt; feature automatically scales your database to handle traffic spikes and high loads. While, &lt;a href="https://neon.tech/docs/introduction/auto-suspend" rel="noopener noreferrer"&gt;autosuspend&lt;/a&gt; automatically suspends your database when it's not in use, saving compute costs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logical Replication&lt;/strong&gt;: Neon supports &lt;a href="https://neon.tech/docs/introduction/logical-replication" rel="noopener noreferrer"&gt;logical replication&lt;/a&gt; that allows you to replicate data from your Neon database to other destinations in near real-time. This is useful for syncing data across multiple databases, analytics and other operational use-cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that some of these features make sense only for production use-cases and hence need a paid plan to use. You can refer to the &lt;a href="https://neon.tech/docs" rel="noopener noreferrer"&gt;Neon documentation&lt;/a&gt; for more information on these features.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pgloader.readthedocs.io/en/latest/install.html" rel="noopener noreferrer"&gt;PGLoader&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pgloader.readthedocs.io/en/latest/ref/mysql.html" rel="noopener noreferrer"&gt;PGLoader MySQL to PostgreSQL Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neon.tech/docs" rel="noopener noreferrer"&gt;Neon Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://PlanetScale.com/docs" rel="noopener noreferrer"&gt;PlanetScale Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>planetscale</category>
      <category>neon</category>
      <category>mysql</category>
      <category>postgres</category>
    </item>
  </channel>
</rss>
