<?xml version="1.0" encoding="UTF-8" ?>
    <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
        <channel>
            <title>pgEdge Posts from Matthew Mols</title>
            <link>https://www.pgedge.com/blog</link>
            <description>The latest pgEdge Posts from Matthew Mols</description>
            <atom:link href="https://www.pgedge.com/feeds/rss/user/matthew-mols/postgresql.xml" rel="self" type="application/rss+xml" />
            <language>en-us</language>         
            
            <item>
            <category>pgEdge,Distributed Postgres,PostgreSQL</category>
            <title><![CDATA[pgEdge + CloudNativePG: Simplifying Distributed Postgres on Kubernetes]]></title>
            <link>https://www.pgedge.com/blog/pgedge-cloudnativepg-simplifying-distributed-postgres-on-kubernetes</link>
            <pubDate>Wed, 05 Nov 2025 09:27:00 GMT</pubDate>
            <description><![CDATA[ <p>With pgEdge now fully open source, we’re continuing our mission to make distributed Postgres accessible to developers, operators, and the broader open-source community. A key part of that story is how we can make it easier to run pgEdge using tools that have broad adoption in the community.Today, we’re excited to introduce two key releases that make it even easier to deploy and operate pgEdge Distributed Postgres on Kubernetes:<ul><li> New pgEdge Postgres Container images built for compatibility with CloudNativePG</li></ul><ul><li>An updated pgEdge Helm chart that simplifies deploying pgEdge on Kubernetes by leveraging CloudNativePG</li></ul>CloudNativePG is an open-source Kubernetes operator that automates the lifecycle of PostgreSQL clusters using native Kubernetes resources. Its adoption has skyrocketed in recent years, and its recent acceptance as a <a href="https://www.cncf.io/projects/cloudnativepg/">CNCF Sandbox project</a> has cemented it as the community standard for running Postgres natively on Kubernetes.<h2>New pgEdge Postgres Container Images</h2>In order to make it easier to operate pgEdge in CloudNativePG, and to support other integrations, we’re releasing a new container image built from our pgEdge Enterprise Postgres packages with support for Postgres 16 through 18.These images are published on the Github Container Registry as <a href="https://github.com/pgEdge/postgres-images/pkgs/container/pgedge-postgres">https://github.com/pgEdge/postgres-images/pkgs/container/pgedge-postgres</a>We’re releasing two image flavors initially.<ul><li>The </li><li>minimal</li><li> image comes bundled by default with the required pgEdge extensions to support distributed deployments: spock, snowflake and lolor</li></ul><ul><li>The </li><li>standard</li><li> image includes popular extensions pgVector, PostGIS and pgAudit</li></ul>This approach means that you can utilize a single set of images across your Postgres deployments, whether they be in a single region, or distributed with spock’s multi-master replication.Over time, we’ll make additions to the image flavors we publish to support additional extensions and improvements. You can also extend these images to add other extensions to your deployment.This image is designed to be compatible with CloudNativePG, but also includes support for the official Postgres entrypoint, as well as a Patroni entrypoint. This adds more integration opportunities for popular open source tools.You can learn more about the new images here: <a href="https://github.com/pgEdge/postgres-images">https://github.com/pgEdge/postgres-images</a><h2>pgEdge Distributed Postgres in CloudNativePG with pgedge-helm</h2>We also want to make it easier to operate distributed architectures in Kubernetes so that more users can leverage spock’s powerful multi-master capabilities.In order to do this, we’ve released an updated version of our <a href="https://github.com/pgEdge/pgedge-helm">pgEdge Helm </a>chart which supports deploying both pgEdge Enterprise Postgres and pgEdge Distributed Postgres in Kubernetes.This new version leverages <a href="https://cloudnative-pg.io/">CloudNativePG</a> to manage Postgres, providing flexible options for single-region and multi-region deployments.The new chart supports the following features:<ul><li>Postgres 16, 17, and 18 via </li><li>pgEdge Enterprise Postgres Images</li></ul><ul><li>Flexible deployment options for both single-region and multi-region deployments</li></ul><ul><li>Configuring Spock replication configuration across all nodes during helm install and upgrade processes.</li></ul><ul><li>Best practice configuration defaults for deploying pgEdge Distributed Postgres in Kubernetes.</li></ul><ul><li>Extending / overriding configuration for CloudNativePG across all nodes, or on specific nodes.</li></ul><ul><li>Configuring standby instances with automatic failover, leveraging Spock's delayed feedback and failover slots worker to maintain active-active replication across failovers and promotions.</li></ul><ul><li>Adding pgEdge nodes using Spock or CloudNativePG's bootstrap capabilities to synchronize </li><li>data from existing nodes or backups.</li></ul><ul><li>Performing Postgres major and minor version upgrades.</li></ul><ul><li>Client certificate authentication for managed users, including the </li><li>pgedge</li><li> replication user.</li></ul><ul><li>Configuration options to support deployments across multiple Kubernetes clusters.</li></ul>The chart includes a simple example which demonstrates deploying a pgEdge Distributed Postgres deployment with 3 nodes.You can install this example by first downloading the latest release package and setting up the required dependencies:1. Download the latest pgedge-helm release package from<a href="https://github.com/pgEdge/pgedge-helm/releases/"> </a><a href="https://github.com/pgEdge/pgedge-helm/releases/"><u>pgEdge Helm Releases</u></a>.After downloading and extracting the package on your machine, navigate into the pgedge-helm directory.2. Install pre-requisites (CloudNativePG and cert-manager)3. Install the chartThe chart includes a Kubernetes job which ensures spock’s configuration is kept up to date across chart upgrades.Once the chart is deployed, you can utilize the <a href="https://cloudnative-pg.io/documentation/current/kubectl-plugin/">CloudNativePG kubectl plugin</a> to connect to the app database on the primary for each pgEdge nodeAutomatic DDL replication is enabled by default, so inserting a new table with data will be replicated to all other nodes:4. Create a table and insert data on n15. Query the data on n2For more details on using chart features, see the <a href="https://docs.pgedge.com/pgedge-containers">pgEdge documentation</a>.<h2>Deploying across multiple Kubernetes clusters</h2>A single Kubernetes cluster is most commonly deployed in one region, with support for running workloads across multiple availability zones. Most customers who are taking advantage of pgEdge Distributed Postgres operate nodes in different regions for performance or availability reasons, sometimes across multiple Cloud providers.Deploying across multiple Kubernetes clusters with pgEdge Distributed requires addressing two aspects:<ul><li>Network Connectivity</li></ul><ul><li>Certificate Management</li></ul>These domains are well known in the Kubernetes community as part of operating other multi-cluster workloads, and customers often have solutions in place to manage them, so building a single approach into pgedge-helm doesn’t make sense.Instead, the new chart includes a few configuration mechanisms to support multi-cluster deployments:<ul></ul><ul></ul><ul></ul>In order to apply these to a multi-cluster scenario, you can utilize these configuration elements across deployments in multiple clusters.For example, let’s assume you want to deploy 2 pgEdge nodes across 2 Kubernetes clusters, with a single helm install run against each cluster. These values files highlight how to leverage these options, ensuring that:<ul><li>Certificates are only issued during deployment to the first Kubernetes cluster</li></ul><ul><li>Spock configuration is applied across nodes in both clusters by the initialization job run in the second Kubernetes cluster</li></ul><h3>Cluster A: cluster-a.yaml</h3><h3>Cluster B: cluster-b.yaml</h3>This example assumes you have a cross-cluster DNS solution in place. If you want to simulate this type of deployment in a single Kubernetes cluster, deploying into two separate namespaces should provide a similar experience without needing to handle this aspect.We’ll be working to produce more blog content for multi-cluster approaches using different Kubernetes networking / certificate management solutions as we move ahead.<h2>Conclusion</h2>These updates mark an important step toward making pgEdge simpler, more flexible, and easier to integrate into Kubernetes environments.You can explore the new images and Helm chart today on GitHub:<ul><li><a href="https://github.com/pgEdge/postgres-images">https://github.com/pgEdge/postgres-images</a></li></ul><ul><li><a href="https://github.com/pgEdge/pgedge-helm">https://github.com/pgEdge/pgedge-helm</a></li></ul>Whether you’re running in a single region or operating a multi-cluster deployment across clouds, pgEdge now provides the open-source foundation and tools to achieve your requirements in Kubernetes.Our team is here to help with your journey, including 24×7×365 global support from seasoned Postgres experts with decades of experience and direct contributions to the PostgreSQL community, with optional Forward Deployed Engineer services for dedicated assistance.Learn more and try pgEdge Enterprise Postgres for free - <a href="/download">www.pgedge.com/download</a></p> ]]></description>
            <guid>https://www.pgedge.com/blog/pgedge-cloudnativepg-simplifying-distributed-postgres-on-kubernetes</guid>
            <author><name>Matthew Mols</name></author>
            </item>
            <item>
            <category>PostgreSQL</category>
            <title><![CDATA[Managing DDL Migrations in a Multi-master Database]]></title>
            <link>https://www.pgedge.com/blog/managing-ddl-migrations-in-a-multi-master-database</link>
            <pubDate>Wed, 02 Jul 2025 05:50:00 GMT</pubDate>
            <description><![CDATA[ <p>A DDL Migration is a set of DDL changes applied in a consistent manner, often via version-controlled scripts or tools, which enable a schema to evolve alongside applications that use it. In an active-active multi-master database, properly managing DDL migration is key to maintaining replication health across your database nodes.Generally, DDL changes in a multi-master database must be coordinated across all nodes to prevent divergence and to ensure that replication can appropriately apply ongoing changes to each node.pgEdge provides <a href="https://docs.pgedge.com/platform/autoddl#configuring-automatic-ddl-replication"><u>Automatic DDL Replication</u></a><a href="https://docs.pgedge.com/platform/autoddl#configuring-automatic-ddl-replication"> </a>(Auto-DDL) to make it easier to manage changes to your database schema. This feature allows you to make your DDL changes against a single node and have them replicated to other active nodes. With Spock’s powerful capabilities, you can also take full control of schema updates and their associated replication configuration using <a href="https://docs.pgedge.com/spock_ext/using_spock/repset_mgmt"><u>Replication Sets</u></a>.As you consider moving your applications to use a multi-master database, you should consider employing the following strategies to improve your application’s write availability and to limit unexpected downtime due to DDL changes that can be made more safely and efficiently.<h2>Make Backward-compatible Changes</h2>To ensure the safe evolution of your schema, it’s best to make safe, backward-compatible changes to your schema that ensure writes can continue to be replicated to other nodes without needing  downtime.These guidelines can help you craft backward-compatible changes:<ul><li>Ensure new columns are nullable or use a default value, to ensure that write transactions that are currently replicating can safely land on other nodes, regardless of the migration state.</li></ul><ul><li>Avoid renaming existing objects (tables, columns, indexes, etc).</li></ul><ul><li>Use a phased deployment approach for non-backward compatible changes, such as column, table, or index renames:</li><li>○ </li><li>On the first deployment, add the new column and begin dual writes to the old and new columns to populate the new column</li><li>○ </li><li>On the second deployment, adjust your application to apply read and write transactions only to the new column.</li></ul><ul><li>Avoid reusing object names across multiple dependent migrations:</li><li>○ </li><li>For example, if you are dropping a constraint and introducing a newer version of that constraint, use a different name so it’s easier to recognize the migration status, and perform corrective actions.</li></ul><ul><li>Avoid changing types for existing columns:</li><li>○ </li><li>Instead, introduce a new column with the new type and populate it through application logic or triggers to keep it in sync with the original column.</li><li>○</li><li> Once your application has migrated write transactions to the new column, you can then safely remove the old column in a separate migration.</li></ul><ul><li>Avoid removing an object (table, column, index) until it is no longer used by application code.</li></ul><ul><li>Utilize pre-migration validations when applying UNIQUE or NOT NULL constraints, which safely skip these migrations (and any that depend on it) if the underlying data is not valid.</li></ul><ul><li>Use </li><li>CREATE INDEX CONCURRENTLY</li><li> separately on each node if you want to avoid blocking other queries in the database.</li></ul><ul><li>Use </li><li>IF EXISTS / IF NOT EXISTS </li><li>where possible in your DDL to defend against migrations being run multiple times:</li><li>○</li><li> This also gives you an escape hatch to make manual corrective changes on specific nodes when queued DDL statements are not completing, as they will become a No op.</li></ul><ul><li>For more complex migrations that include longer operations, it may be best to apply your changes individually on each node using </li><li>spock.repair_mode</li><li> rather than making them with Spock's AutoDDL functionality:</li><li>○</li><li> This may require coordination / scripting to run across all nodes, with verification performed to ensure it is complete.</li><li>○</li><li> If necessary, you can leverage </li><li>pg_advisory_lock</li><li> in coordination with your application to better control the behavior of other write statements to the database.</li></ul>Regardless of the approach you take to your DDL changes, it’s best to always test and verify the changes on a staging environment before rolling them out to production.<h2>Run Migrations Once when Using AutoDDL</h2>When you are relying on AutoDDL to propagate DDL changes to other nodes, it’s generally best to run your migrations only once against a single, dedicated node.If you are leveraging DNS routing to your nodes or using a load balancer that routes writes to multiple nodes, you run the risk of creating a situation where DDL changes with dependencies are applied to different nodes out of order, causing changes to not apply cleanly due to missing dependencies, resulting in schema mismatch.This issue can be made worse when using migration tools, including ones bundled with Object-Relational Mappers (ORMs). Migration tools typically rely on a migration state that is stored in a database table and updated as migrations are successfully applied in their desired order to a single node.If your changes are applied on application startup, multiple deployments of your application may attempt to apply the same DDL changes multiple times. This can generate errors and break replication across your subscriptions if the replicated statements do not prevent this scenario.To counteract this, you should configure your applications to only run DDL changes from a single migration or application instance. If you're using a standalone migration tool, such as the Liquibase CLI, you should only run that tool against a single pgEdge Postgres instance.If you are leveraging a library that runs as part of your application startup, you may need to introduce an environment variable like  and wrap any library code involved in the migration so that it only executes on one application instance.Migration documentation for various libraries and tools is linked below. If you are using a home-grown solution, the same approach should work to ensure your changes are only run once.<h4>Python</h4><ul><li>SQLAlchemy + Alembic</li><li>○ </li><li>https://alembic.sqlalchemy.org/en/latest/tutorial.html</li></ul><ul><li>Django ORM</li><li>○ </li><li>https://docs.djangoproject.com/en/stable/topics/migrations/</li></ul><h4>Go</h4><ul><li>GORM</li><li>○ </li><li>https://gorm.io/docs/migration.html</li></ul><ul><li>Golang-migrate</li><li>○ </li><li>https://github.com/golang-migrate/migrate/blob/master/README.md#usage</li></ul><ul><li>Ent</li><li>○ </li><li>https://entgo.io/docs/migrate/</li></ul><h4>Node.js</h4><ul><li>Prisma</li><li>○ </li><li>https://www.prisma.io/docs/orm/migrate</li></ul><ul><li>Sequelize</li><li>○ </li><li>https://sequelize.org/docs/v6/other-topics/migrations/</li></ul><ul><li>TypeORM</li><li>○</li><li> </li><li>https://typeorm.io/migrations</li></ul><h4>Java</h4><ul><li>Hibernate</li><li>○</li><li>https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#schema-generation </li></ul><ul><li>Flyway</li><li>○ </li><li>https://flywaydb.org/documentation/usage/</li></ul><ul><li>Liquibase</li><li>○ </li><li>https://docs.liquibase.com/</li></ul><h2>Make DDL Changes in Advance</h2>With the popularity of migration tooling integrations with applications, it’s common to perform migrations during startup and then immediately begin leveraging new tables and columns in newly deployed application code.This can cause issues in a multi-master system, especially when deployments may contain many DDL updates that may take time to apply across all nodes, even with AutoDDL managing those changes. DDL changes are queued by Spock, and applied in order, so if one change takes longer than expected, other database nodes may not be updated immediately.In that event, your application may begin to exhibit errors if connecting to those other nodes, because it expects new tables and columns to be available for write transactions. In general, making DDL changes well in advance of when they are actually needed will help to avoid this problem.One strategy to avoid this problem is to perform migrations as their own deployments. DDL changes typically occur early in the development process for new features, and if you are using a continuous delivery approach, you can make smaller deployments that are only meant to migrate the database. When you combine this approach with backward-compatible DDL changes, your application should not be impacted by new columns and tables that are not required for functionality.Another strategy is to run data migrations prior to application deployment. Within your deployment process, add a step prior to application deployment that performs and verifies migrations against your database. If you are deploying your application in Kubernetes, an init container or pre-deployment job can achieve the same outcome.Data migrations should be verified using a separate verification script, ensuring they are applied on all nodes before moving on to deploying the application. If you integrate this separate step into your CI/CD process, it should be easy to set up alarms and notifications to know when something may be wrong<h2>Monitoring Migrations and Resolving Problems</h2>It’s important to be able to monitor the status of schema migrations across all nodes in the system to know when they have succeeded.In general, you should monitor the PostgreSQL logs to ensure that there were no issues applying changes to other nodes within the system. Look for spock apply errors to see if there might be issues with updates taking too long, or not being applied due to a previous mismatch.A good way to understand where differences may exist is to utilize the schema-diff capability in the Active Consistency Engine (ACE) to identify differences in your schemas across nodes. You can then understand if a previous mismatch is preventing a DDL statement from being applied, or where your schema is out of sync. ACE could be run after your migration process to ensure the schema is stable before proceeding to deploy applications.If you identify any differences across nodes, you can fix up individual node(s) using a manual DDL update with spocks’ <a href="https://docs.pgedge.com/platform/exception#using-spockrepair_mode-when-repairing-transactions"><u>repair_mode</u></a><a href="https://docs.pgedge.com/platform/exception#using-spockrepair_mode-when-repairing-transactions"> </a>feature enabled. This can help to unblock a queued DDL change that may have relied on the existence of a specific column or table without also applying that DDL to other nodes.If you make manual updates to resolve inconsistencies using , you may need to delete a queued DDL statement from  to allow other DDL changes and data replication to be unblocked. This is uncommon if you follow the best practices highlighted here, but may be necessary if a troublesome DDL migration is applied that is causing timeouts within Spock’s apply worker.</p> ]]></description>
            <guid>https://www.pgedge.com/blog/managing-ddl-migrations-in-a-multi-master-database</guid>
            <author><name>Matthew Mols</name></author>
            </item>    
    
        </channel>
    </rss>