A production deployment is often described as pushing code live. That makes a controlled business change sound like a file transfer. The interesting work sits between approval and confidence: a repeatable build, tested artefact, environment configuration, database migration, restarted workers, traffic change, verification, monitoring and a safe way back.
01
Start with one exact version
Imagine a customer portal used to manage renewals. A new release adds a renewal reference, changes the review screen and sends an email through a queue after approval.
Before anything reaches production, the team needs to know exactly what is being released. That normally means an approved commit or tag, a clear list of included changes and a link back to the review, tests and decision that authorised it.
This is more than tidy administration. If an incident begins ten minutes after release, people need to answer basic questions quickly. Which version is running? What changed? Who approved it? Were configuration or database changes included? Which version should be restored if the release has to be reversed?
A deployment system should leave an audit trail rather than rely on somebody remembering the commands they typed. Platforms such as GitHub Actions can also put protection rules, reviewers, branch restrictions and environment secrets around production. The useful principle is broader than any one tool: production access should be deliberate, limited and visible.
02
Build once and promote the same artefact
Source code is rarely the thing that runs unchanged on the server. The build may install locked dependencies, compile application code, bundle and minify front end assets, prepare production configuration caches and create a container image or release archive.
The output is an artefact: one frozen version that can be identified and stored. It should carry a version or digest so the team can prove which build reached each environment.
The safest pattern is to build once, test that artefact and then promote the same artefact into production. Rebuilding after testing can introduce a quiet difference. A package may have changed, a base image may be newer or a build flag may be different. The code commit can stay the same while the thing being deployed changes underneath it.
Automated checks belong before production. Unit and feature tests, static analysis, dependency checks and image scans can stop an obviously weak build before it touches live data. They reduce risk, but they do not remove the need for production verification. A test environment cannot perfectly reproduce real traffic, live credentials, production data shape or every connected service.
For the renewal portal, the artefact should contain the reviewed application code and built front end assets. It should not contain the production database password or email credentials. Those belong to the environment and should only become available after the production gate has passed.
03
Combine the build with production configuration
A release combines the tested build with the configuration for the environment in which it will run. That configuration may select the database, cache, file storage, mail provider, queue connection, third party APIs and feature flags.
Keeping build and configuration separate makes the artefact reusable and keeps secrets out of source control. It also creates a responsibility that is easy to overlook: configuration changes need the same care as code changes.
A perfectly good build can fail because a production variable is missing, a secret has expired or a new queue name has not been created. Configuration should therefore be versioned where it can be, reviewed without exposing secret values and checked before traffic reaches the new release.
Feature flags can reduce the size of the cutover. The new renewal screen might be deployed while hidden, checked by the team and enabled only after the supporting data and queue worker are ready. Flags are useful controls, but they need owners and removal dates. Otherwise they become another collection of old branches nobody is confident enough to delete.
04
Treat database changes as a separate risk
Application code is usually easier to replace than data. That makes database migrations one of the most important parts of a deployment plan.
The renewal release needs a new nullable renewal_reference column. Adding that column first is safer than immediately replacing or deleting an existing field. During a rolling deployment, old and new application versions may use the same database for a short period. Both versions need a schema they can understand.
This leads to an expand and contract approach. Expand the schema with the new structure. Deploy code that can work while old and new structures coexist. Move or backfill data in a controlled way. Only remove the old structure in a later release, after the new path has been proven.
Large updates may need to be split into background jobs rather than held inside one deployment transaction. Index creation, column rewrites and data backfills can lock tables or create heavy load. The deployment plan should state how long the change may take, what it locks, how progress is observed and what happens if it stops halfway through.
Framework migration commands are helpful, but a rollback command is not a complete recovery plan. Reversing a schema change may discard data created by the new version. Before release, the team should decide whether rollback means reversing the migration, restoring a backup, disabling the feature or deploying a compatibility fix.
05
Decide how the new version receives traffic
There is no single release strategy that fits every application. A small internal system may use an atomic release with a short maintenance window. A public service with several application instances may replace them gradually. A high risk change may deserve a parallel environment or a limited audience first.
| Release approach | How traffic changes | Useful when | Main trade-off |
|---|---|---|---|
| Atomic release | The old version is replaced by the new version in one change | A small application can tolerate a brief controlled interruption | Simple to understand, but the cutover is abrupt |
| Rolling release | New instances start while old instances are removed gradually | Several stateless application instances already share the load | Old and new code may run together, so compatibility matters |
| Blue and green | A full new environment is prepared beside the current one, then traffic is switched | Fast cutover and a quick traffic switch back are valuable | Duplicate capacity and environment consistency cost more |
| Canary release | A small share of traffic reaches the new version before wider rollout | The team has enough traffic and monitoring to compare behaviour | Routing and interpretation are more complex |
The strategy should match the system, not the fashion. Blue and green environments add little value if the database change cannot be reversed. A canary tells the team very little if traffic is too low or the useful business signal arrives days later.
For the renewal portal, a rolling release may be reasonable if multiple application instances already exist and the database change is backward compatible. A smaller installation might be safer with a short planned window, a verified backup and one clear person controlling the release.
06
Start every process that carries the new code
Web requests are only one part of many applications. Queue workers, schedulers, WebSocket servers and long running processes can keep the old code in memory after the web application has changed.
That matters for the renewal email. The new web code may queue a job using an updated payload while an old worker is still listening for the previous shape. The page works, the deployment dashboard is green and the email quietly fails later.
A release should list every process that needs to be restarted or reloaded. It should also consider work already in progress. Can an old queued job be handled by the new worker? Will restarting a process lose a task? Should the worker finish current work before it stops?
This is a good example of why deployment instructions need to describe the application rather than only the server. A command can restart a process. It cannot decide whether two versions of a business message are compatible.
07
Health checks are the beginning of verification
Once the new version starts, infrastructure needs to know whether it can receive traffic. A liveness check can show that a process is still running. A readiness check can show that it is prepared to handle requests. Laravel, for example, includes a health route that can be used by a load balancer, uptime monitor or orchestration platform.
Those checks are necessary, but an OK response proves very little about the renewal workflow. The application can answer a health endpoint while the database credentials are wrong for one feature, the queue is stopped or the email provider is rejecting requests.
Post deployment smoke tests should exercise a small number of important paths. For this release, that might mean signing in with a controlled account, opening a renewal, saving the new reference, approving it, checking the audit entry and confirming that the queued email was accepted.
The checks need to be safe and repeatable. They should not create misleading live records, charge real cards or email real customers. A well designed application provides controlled production checks and makes their records easy to identify and remove.
08
Watch the system and the business result
A deployment is not complete when the automation reports success. It is complete when the new version is running, important journeys work and somebody is watching the signals that could reveal a problem.
Technical signals include error rate, response time, memory, CPU, database load, failed jobs, queue delay and logs. Business signals show whether the application is doing its real job. For the renewal change, useful signals could include approvals completed, references saved and emails accepted by the delivery provider.
The observation period should match the risk. A problem in sign in may appear immediately. A scheduled job may not run until midnight. A monthly invoice task cannot be proven five minutes after release. The release notes should name the later checks and who owns them.
Alerts also need a decision attached. If failed renewal jobs exceed an agreed threshold, does the team pause the feature, retry the jobs, roll back the code or begin an incident? Monitoring without ownership produces noise at exactly the moment clarity is needed.
09
Make rollback possible before it is urgent
Rollback is easiest when it has been designed before the release. The previous artefact should still exist, the deployment process should know how to restore it and the team should understand what happens to configuration, data and queued work created by the new version.
Code rollback can be quick. Database rollback may not be. If customers have already saved renewal references, removing the column would destroy valid data. In that case, redeploying the old application may also fail because it does not understand the expanded workflow.
This is why compatibility changes and feature flags are valuable. The team may be able to disable the new screen while leaving the additive column in place, restore the previous application version and investigate without deleting customer data.
The decision to roll back needs an owner. Under pressure, a room full of people watching dashboards is not the same as one person authorised to call the change. A deployment plan should name who decides, what evidence they use and how customers or staff will be told if service is affected.
10
A release finishes with evidence and ownership
A dependable production deployment leaves useful evidence behind. It records the version, approvals, build results, database operations, start and finish times, smoke test results, monitoring links and any follow-up work.
The process does not need to be grand. A small application can have a short, clear checklist. The right amount of ceremony depends on the cost of failure, the number of people involved and the ease of recovery.
What matters is that a release is treated as a controlled transition. The team knows what is changing, promotes one tested artefact, protects live data, verifies the real workflow and keeps a safe route back.
That is what happens during a production deployment. Code moves, but confidence comes from the chain of decisions and evidence around it.
DanJMills builds, modernises and supports Laravel and Vue applications for established businesses. If an important application is difficult to release safely, the first useful step is to map the current deployment, identify the fragile points and make the route to production repeatable.
Useful questions
Production deployment checklist:
- Is one exact commit, tag or artefact approved for release?
- Has the same artefact passed the required automated checks?
- Are production configuration and secrets present without being built into the artefact?
- Are database changes backward compatible with old and new application versions?
- Have long running workers and schedulers been included in the release plan?
- Does the traffic strategy fit the system and its recovery options?
- Do smoke tests prove an important business journey, not only a health endpoint?
- Are technical and business signals being watched after release?
- Is the previous version available and is the rollback decision owned?
- Are delayed checks and follow-up work assigned to named people?


