惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
爱范儿
爱范儿
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
V
V2EX
博客园_首页
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
GbyAI
GbyAI
H
Help Net Security
A
About on SuperTechFans
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Blog — PlanetScale
Blog — PlanetScale
W
WeLiveSecurity
云风的 BLOG
云风的 BLOG
D
Docker
Security Archives - TechRepublic
Security Archives - TechRepublic
Help Net Security
Help Net Security
N
News and Events Feed by Topic
Simon Willison's Weblog
Simon Willison's Weblog
G
Google Developers Blog
A
Arctic Wolf
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
博客园 - 三生石上(FineUI控件)
aimingoo的专栏
aimingoo的专栏
Hacker News: Ask HN
Hacker News: Ask HN
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 司徒正美
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
T
Troy Hunt's Blog
T
Tenable Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Recorded Future
Recorded Future
F
Fortinet All Blogs
D
DataBreaches.Net
B
Blog
T
Threat Research - Cisco Blogs
MyScale Blog
MyScale Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
The GitHub Blog
The GitHub Blog
Security Latest
Security Latest
M
MIT News - Artificial intelligence

Clerk Blog

Going to production with Clerk Deploy Clerk Init: The fastest way to start a new project Introducing Clerk CLI Middleware-based route protection bypass Postmortem: Clerk System Outage (March 10, 2026) Clerk for the AI era Add API Key support to your SaaS in minutes Postmortem: Clerk System Outage (February 19, 2026) Using Clerk in a React Native app Postmortem: DNS Provider Outage (February 10, 2026) How do I implement passkeys in Next.js? Clerk ranked #4 fastest-growing software vendor on Ramp’s December 2025 list How do I handle JWT verification in Next.js? Committing to Agent Identity: Clerk raises $50m Series C from Menlo and Anthropic’s Anthology Fund What is the best way to handle authentication in Next.js App Router? Postmortem: Database Incident (September 14–18, 2025) How do I add authentication to a Next.js app? Introducing Free Trials in Clerk Billing Postmortem: August 28, 2025 - elevated API latency and errors Introducing Mosaic: Bring Your Brand to Every Authentication Flow Multi-tenant authentication: What you need to know (and how Clerk helps) What are the risks and challenges of multi-tenancy? Resilience in Practice: Regional Failover at Clerk Build a Cross-Platform B2B App with Clerk, Expo, and Supabase Highlights from the MiduDev/Clerk Hackathon Add multi-tenancy to an app built with Clerk, Lovable, and Supabase How to build an AI coding rules app with Clerk, Lovable, and Supabase How to Build Multi-Tenant Authentication with Clerk Choosing the right SaaS architecture: Multi-Tenant vs. Single-Tenant Postmortem: June 26, 2025 service outage How to Design a Multi-Tenant SaaS Architecture What is multi-tenancy and why it matters for B2B SaaS How OAuth Works Synchronize user data from Clerk to Supabase Add subscriptions to your SaaS with Clerk Billing Getting started with Clerk Billing Multi-tenant analytics with Tinybird and Clerk How Huntr Migrated 250K Users to Clerk: A Scalable Auth Solution for Startups How to take Clerk to Production How to take your Clerk application to production A practical guide to testing Clerk Next.js applications Implementing multi-tenancy into a Supabase app with Clerk How Clerk integrates with a Next.js application using Supabase How Clerk integrates with Supabase Build a blog with tRPC, Prisma, Next.js and Clerk How to enrich PostHog events with Clerk user data How to build a secure project management platform with Next.js, Clerk, and Neon Validate your SaaS idea while building an audience Postmortem: February 6, 2025 service outage Implement Role-Based Access Control in Next.js 15 Build a Next.js sign-up form with React Hook Form Build a Next.js login page template How to implement Google authentication in Next.js 15 What is middleware in Next.js? How to customize Next.js metadata How to set environment variables in Node.js Building a React Login Page Template How to implement per-user OAuth scopes with Clerk Using Clerk SSO to access Google Calendar and other service data Streamline enterprise customer onboarding with SAML and Clerk Clerk launches EASIE SSO and eliminates SSO fees How to secure Liveblocks Rooms with Clerk in Next.js Securing Node.js Express APIs with Clerk and React Combining the benefits of session tokens and JWTs Build a task manager with Next.js, Supabase, and Clerk Comparing Clerk Webhooks vs Backend API A guide to reading authenticated user data from Clerk Role based access control with Clerk Organizations Mitigating OAuth’s recently discovered Open Response Type vulnerability Per-user B2B monetization with Stripe and Clerk Organizations Build a team-based task manager with Next.js, Neon, and Clerk Building a Hybrid Sign-Up/Subscribe Form with Stripe Elements Welcoming Colin from Zod as our inaugural Open Source Fellow Build a modern authenticated chat application with Next.js, Ably, and Clerk Build a waitlist with Clerk user metadata How to use Clerk with PostHog Identify in Next.js How to secure API Gateway using JWT and Lambda Authorizers with Clerk What are passkeys and how do they work? Comparing Authentication in React.js vs. Next.js How to Add an Onboarding Flow for your Application with Clerk Create Your Own Custom User Menu with Radix - Part 2 Introducing Webhook Workflows with Inngest & Svix Clerk raises $30M Series B from CRV and Stripe Clerk in 2023: A Year in Review Build a Movie Emoji Quiz App with Remix, Fauna, and Clerk Ultimate Guide to Magic Link Authentication Create Your Own Custom User Menu with Radix Introducing has(), protect(), and <Protect> Updated Pricing: 10,000 MAUs Free, and a new “Pro Plan” Next.js Authentication with Clerk: Streamlined SSR Handling Clerk Webhooks: Data Sync with Convex Exploring Clerk Metadata with Stripe Webhooks The Ultimate Guide to Next.js Authentication Empower Your Support Team With User Impersonation Clerk Webhooks: Getting Started A Complete Guide to Session Management in Next.js The Advanced Guide to Passwordless Authentication in Next.js How We Roll – Chapter 10: Roundup How We Roll – Chapter 9: Infrastructure Password-Based Authentication in Next.js
Automate Neon schema changes with Drizzle and GitHub Actions
Brian Morrison II · 2024-08-22 · via Clerk Blog

While it’s relatively straightforward to deploy updated code to different environments, applying the same techniques to a relational database can be disastrous.

Application code is stateless, meaning you can rebuild the code to recreate the application at any time. In fact, when deploying updated code to platforms like Vercel, the tooling will simply build and ship the latest version of the application, overwriting the previous one.

However, databases are stateful since the value is in the data contained within them. Applying the same deployment methodology to a database (removing and replacing it with a new version) would be detrimental to your users or business.

In this article, you’ll learn what schema migrations are, how they can be used to safely make database changes, and how to automate those changes to a Neon database using Drizzle and GitHub Actions.

What is a schema migration?

Schema migrations are a way to apply changes to the schema of a database in a controlled way.

Typically each schema migration is a SQL script that is applied to the database to update the schema to the latest version. The migration files can stored in version control so the state of the schema can be tracked over time.

Schema migrations are used for updating the database schema as changes are required, but can also be used to create new environments. To recreate the database up to a specific point in time, the migrations can applied in the same order they were generated.

Schema migrations and deployments

When building an application that uses a relational database, you’ll often have a different database per environment. Each database is isolated from one another so modifying the schema in one database environment does not affect the others.

Let's say you have two environments, a dev environment for building new features, and a production environment that your users are actively using.

When a feature is complete, merging your code from the dev branch to main is relatively straightforward. Once the newest version of the application is built, the artifacts of that build are deployed into the production environment, replacing the previous version.

The latest schema migrations are also applied to the database, updating the schema to support the latest version of the application. If done properly, all of the data within the database will remain intact.

How to generate and apply schema migrations with Drizzle

Now that you understand what schema migrations are and how they are used when deploying new versions of your database, let’s explore a practical example using Drizzle.

Drizzle is a type-safe ORM for applications built with TypeScript. The team also built Drizzle Kit for managing the schema of the database. Drizzle Kit can be used to analyze your TypeScript models, generate schema migrations from the models, and apply them to the database.

The demo application

The remainder of this article uses a sample to-do app to demonstrate how to use schema migrations to apply database changes. The application uses a Postgres database hosted by Neon, with a relatively simple schema.

I’ll be showing the process of adding a single column to the tasks table (shown below) so that each task can have a description stored with it.

A database table showing columns named "name", "is_done", "owner_id", "created_on", and "created_by_id"

To simulate multiple environments, the Neon database has a main branch that contains the production data and a dev branch that is an isolated environment used for adding and testing new features.

Updating the development environment

I’ll start by updating the code on the dev branch to support a “description” field of the tasks model:

src/db/schema.ts

The application has the following drizzle.config.ts which Drizzle Kit uses to locate the schema files in the project, generate and store migrations, and connect to the database:

drizzle.config.ts

Next, I’ll run the following command which will generate a new schema migration file. I’m also setting the DATABASE_URL environment variable used by drizzle.config.ts:

A new file is automatically generated and placed in the drizzle folder with the necessary SQL to apply:

drizzle/0001_loose_mojo.sql

Next, I’ll run the following command to update the database schema in Neon, adding the description column:

Once the migration is applied, the new column is added to the database and is ready to test. The schema will now look like this:

A database table showing columns named "name", "is_done", "owner_id", "created_on", "created_by_id", and "description"

Updating the production environment

When I’m ready to move the code to production, I can apply the migrations to the main database branch by passing in that branch's connection string:

Once the migrations are applied to the main database branch, I can deploy the production version of my application. Platforms like Vercel (which I am using to host this application) will commonly monitor the main branch of a repository for changes and kick off the deploy process when a change is detected. Merging my code changes into main will trigger Vercel’s CI tools to deploy the newest version of the code.

I can deploy my application to Vercel by merging the changes into the main code branch and letting Vercel’s CI tools deploy the newest version of the code.

While this example makes a single change, multiple schema migrations can be generated and applied between deployments for more complex schema changes. The files will be applied in the order they were created, ensuring that the state of the production database matches the development environment.

Automating migrations with GitHub Actions

Using Drizzle Kit to apply schema migrations helps to ensure that your schema is safely updated between deployments, but manually performing this operation introduces a point of failure in the process. If you forget to apply the migrations, and your schema doesn't match what the application expects, you could inadvertently take your service down.

GitHub Actions, a platform built into GitHub, provides a way for developers to define workflows that execute automatically when specific events (such as making changes to a repository branch) occur on GitHub. Let’s look at how GitHub Actions can automatically apply migrations when the code on the main branch changes.

First, I’ll need to securely store the connection string for my database in GitHub in a way that the GitHub Actions service can access it. This is done by adding a repository secret in "Settings" under "Secrets and variables", then "Actions".

GitHub repository settings, adding the "DATABASE_URL" secret.

The following GitHub Actions workflow can be used to execute drizzle-kit migrate each time a change is performed on the main branch in GitHub:

Since Vercel triggers a deployment when changes are made on the main repository branch, the Actions workflow will trigger simultaneously with the deployment, ensuring that your code and schema versions always stay in sync.

Conclusion

Properly applying changes to a database when new features are added to an application is important to retaining the data within the database, as well as maintaining the uptime of your application.

After reading this article, you now understand what schema migrations are and how they’re used in the development lifecycle of a database. You should also know how to use Drizzle to generate and apply migrations, and how to automate this process using GitHub Actions.