Validation, deployment, and maintenance records

Validate application behavior after a future update, plan deployment, handle failures, and distinguish public release notes from internal maintenance records.

Use this article after evaluating your update's goal and completing the necessary merges. If you do not currently need an update, keep your existing project. There is no need to deploy, create tags, or perform database operations.

1. Define the acceptance criteria

Focus validation on the changes and their actual effects. Checking only the home page is not enough, but an unrelated copy change does not require testing every third-party feature either.

ChangeRepresentative scenarios to validate
Sign-in, sessions, or email verificationNew and existing accounts, valid and invalid sessions, incorrect verification codes, and required step-up verification
Permissions and product rulesStandard accounts and accounts with purchases, historical grants, and behavior after expiration or revocation
Payments and webhooksTest purchases, duplicate deliveries, delayed or out-of-order events, and old plan associations
Data structuresReading and writing existing data, constraints, empty database initialization, and existing database upgrades
Queues or ReactionSuccessful execution, retryable failures, duplicate messages, and execution records saved before the upgrade
Content and languagesNavigation, body content, search, enabled languages, and missing text
Resources and domain namesBinding targets, cookies, callbacks, Cron, and runtime logs

In development mode, emails appear as terminal previews. A successful preview does not validate actual delivery. When using Stripe test mode, also confirm that the connection, Price, and webhook belong to the same test environment.

2. Complete local checks

After completing your code changes, run:

npm run verify

The template runs ESLint, TypeScript type checking, tests for the application and scripts, and a production build in sequence. You must also resolve content or type errors generated during these checks. A screenshot of the final successful build alone is not sufficient.

To inspect the built pages locally, you can use:

npm run preview

A local preview does not prove that production resources, email services, or third-party callbacks work. If you need to validate integrations online, first prepare isolated resources and explicit test configuration. The current template does not automatically provide a complete staging environment.

3. Confirm the actual deployment target

Record the commit you plan to deploy, site URL, Worker, resource IDs, migration files, and configuration changes. Confirm that the original master key and other credentials needed for recovery remain securely stored. Record only their storage locations or update status.

If production data will change, confirm that backups or recovery points are available and assess whether related writes need to be restricted during deployment. A Git tag alone does not protect database or external service state.

For a normal update, use:

npm run deploy:update

This command deploys the current working directory. It does not download or merge the template. Its sequence includes production checks, type generation, full validation, remote migrations, Worker deployment, KV synchronization, and page health checks.

Because it already includes verify, there is no need to repeat the same checks immediately before deployment just to complete a process. However, if you have changed code since an earlier validation, those results do not prove that the current version is valid.

For deployment details, see Initial deployment and subsequent updates.

4. Determine what happened before recovering from a failure

Where execution stoppedPossible current stateRecovery approach
Configuration checks or verifyThis update's remote migrations and deployment have not runFix the failures, then continue the update
Database migrationSome earlier migrations or migrations for the other database may have completedCheck migration records and schemas to determine the corrective SQL
Worker deploymentMigrations may have completed, and old code may still be liveEnsure the old code is compatible with the current schema and fix deployment
KV synchronizationThe new Worker is live, but content has not been fully synchronizedResume synchronization using the correct version
Health checksAll preceding steps may have completedInspect actual pages and logs to locate application or entry-point issues

Do not delete resources, clear databases, or repeat initial deployment just because a command fails. For more detailed troubleshooting, see Deployment, resources, and domain names.

Rolling back code does not restore the whole system

If only application code changed, with no changes to data formats, configuration semantics, or external state, you can consider redeploying a previously validated version. This approach does not apply directly if a migration has removed old fields or the new version has written data that the old version cannot recognize.

Restoring a database may undo legitimate data changes made after the recovery point. Completed Stripe payments, sent emails, and the effects of processed Queue messages do not disappear when you roll back Git history. They require separate reconciliation.

The project has no command that automatically rolls back the entire system. Design recovery for the specific change. Document what to restore, the basis for that decision, the execution order, and any business operations that need follow-up processing after recovery.

5. Validate the affected features after deployment

Once page health checks pass, validate the representative cases prepared before deployment. Check existing accounts and historical data. Do not rely only on a successful result from a newly created account.

For background work, continue checking Event, Command, and consumer results. For payments, confirm that transactions and entitlements agree. After the first successful result, continue watching for delayed callbacks or scheduled tasks over the relevant business cycle. A short period without errors does not mean every path has been validated.

Once the update is stable, remove temporary logic, test configuration, and old references that are no longer needed. Do not delete unused resources based solely on similar names. First confirm that nothing reads or writes them and that they are not needed for recovery.

6. Keep an internal maintenance record

Internal records explain implementation and recovery. Public release notes explain what users received. They serve different purposes.

You can copy the following record template when you have an actual update to make. Fill in the placeholders with the facts of that update. This is not a record of an upgrade that has already happened:

# Change record: <change-name>

- Status: under evaluation / pending release / released / recovered
- Reason for the update:
- Original application commit and version:
- Original and target template sources:
- Changes included in this update:
- Template changes retained or excluded, with reasons:
- Database migration files and validation results:
- Configuration, variable, and resource changes:
- Manual operations on third-party platforms:
- Automated checks and business validation results:
- Deployed commit, deployment time, and target Worker:
- Recovery conditions, targets, and steps in case of failure:
- Post-deployment observations:
- Unresolved issues:

Do not store Secrets, cookies, tokens, complete production data, or email verification codes in these records. Store database backups separately and securely as well. Do not commit them to the repository with the documentation.

Even if you defer an update, you can record the target version and the reason for postponing it. This avoids having to reconstruct that information from scratch during the next evaluation.

7. Maintain public release notes

The current template's changelog page reads a static array in src/components/server/Changelog/entries.ts. It does not automatically turn Git commits or the package.json version into announcements.

Entries currently use these fields:

FieldPurpose
commitText identifying the associated commit
date, displayDateDate and display date
type, title, descriptionUpdate category, title, and description
iconAn icon name supported by the current component
itemsA list of changes, each with kind and copy

Entry content currently uses the English strings in the array directly. Only the surrounding page text uses language keys such as pages.changelog. Editing language JSON alone does not translate titles or entries in entries.ts. If you need multilingual release note content in the future, connect it to the appropriate resources through the project's existing internationalization mechanism.

An initialized product should not automatically adopt the template's history as its own release history. When you make an actual release, record the changes you have delivered to users. If nothing has changed, do not invent a new version to fill the page.

Describe concrete results. For example, “Fixed an issue where notifications continued going to the old address after an email address change” is more useful than “Improved the email module.” Keep internal resource IDs, recovery points, sensitive data, and details of specific security controls in access-controlled maintenance records.

8. Tags, source archives, and deployment are independent

npm run release:tag creates a tag and pushes it to origin. It is not a local read-only operation and does not deploy the Worker. release:archive generates a source archive from a specified Git tree and excludes uncommitted changes.

The template maintainer's commit script is removed from published source archives. Do not assume an initialized project provides the same one-command commit workflow.

Your own version management process should determine whether to use these release commands. If you do not need a release now, you do not need to create tags or archives in advance. Keep records that let you trace the project's state.