How do I run database migrations safely in CI/CD?
Add the column nullable, move the backfill to a separate throttled step, run migrations in their own stage, and drop the old column in a later release.
Just Ask
Ask me anything about software architecture, careers, PHP, Go and the craft of building software; I answer here, in the open, for everyone. (Page 4/8)
Whatever's on your mind, don't hold back. Questions reach me directly; I answer the good ones and publish them on this page. Your email is never published.
Add the column nullable, move the backfill to a separate throttled step, run migrations in their own stage, and drop the old column in a later release.
Delete the long-lived AWS keys from GitHub Secrets and assume a repo/branch-scoped IAM role over OIDC; pull non-cloud secrets from a manager at runtime.
Leave the build tools in the builder stage: make the final stage distroless/static or scratch for Go and fpm-alpine for PHP, and run as non-root.
Move state to a versioned, encrypted S3 backend and add a DynamoDB lock table (deprecated but working), keep state per environment, and apply only from CI.
After flipping the symlink, gracefully reload PHP-FPM rather than restarting it; on Octane, octane:reload is mandatory and opcache_reset is optional.
100M rows a day breaks a plain table, so chunk it by time with hypertables, materialize the averages as continuous aggregates, and compress the old chunks.
Instead of a blocking `ALTER TABLE` on 20M rows run expand/contract: add nullable columns, dual-write, backfill in throttled batches, then drop the old.
Use a Sorted Set instead of plain string keys sorted in the app, since `ZADD` updates in O(log N) and `ZREVRANGE 0 99` returns the top 100 already ordered.
Move reporting to a read replica and adopt CQRS only when query shapes outgrow one schema, feeding the read model from outbox events, not dual-writes.
Keep products, prices and orders in PostgreSQL and put the variable attributes in one GIN-indexed `JSONB` column; reporting alone rules out splitting.