Safe Release Switches on a Small Host
A release procedure that identifies the artifact, verifies the useful path and states where rollback stops being simple.
On this page
A small service still has a release boundary. At one moment requests reach the old application; later they reach the new one. Making that change understandable matters more than choosing a sophisticated deployment tool. The operator should know which artifact is running, which configuration it uses, how it was checked, and what can be recovered if an observation goes wrong.
This note describes a procedure for a single service behind a reverse proxy. It is a design checklist, not a claim that two processes on one host provide high availability. They share the host, its storage and usually its network. The method improves the visibility of a release without removing those shared failure modes.
Identify the complete change
Give the build an immutable identity, such as an image digest or a verified archive checksum. Record the application revision separately from the configuration revision. A label like latest does not tell a later reader whether the artifact changed between two attempts.
Include data changes in the record. Adding an optional column may permit both old and new versions to operate. Removing a column that the old version requires may make an application rollback impossible. A service that writes a new file format can create the same problem without using a database.
An example record is deliberately plain:
artifact: release-2026-10-03 / verified digest
configuration: settings revision 14
data change: none
previous artifact: release-2026-09-29
preflight: isolated read-only fixture
switch condition: useful request succeeds
stop condition: unexpected write or missing evidenceThese values are illustrative. A real record needs the actual identities and observations, rather than a copied declaration that every check passed.
Verify before receiving normal traffic
Start the candidate on a separate loopback port, with the same production settings that matter to its behavior. Give it a distinct cache directory if it writes local cache files. Use an isolated fixture for stateful checks; an unnoticed candidate writing into live storage is already a production change.
Check a useful request, not only whether a process exists. For a publication, load an article, its stylesheet and its canonical metadata. For a worker, process a harmless fixture and inspect the resulting state. A successful TCP connection establishes a narrower fact than a successful application operation.
Also check expected failures. A missing article should return a controlled not-found response. An unavailable optional upstream should not erase local content. Do not infer success from a response body that contains the word healthy while returning an error status.
Treat the proxy switch as a separate step
Prepare the new upstream configuration, validate its syntax, and retain the previous configuration. The application check and the proxy check answer different questions. A candidate can work locally while the public route still points to the wrong port or the wrong virtual host.
After switching, make a request through the actual intended route. Confirm the release identity through an internal record or a bounded response check. Avoid publishing detailed infrastructure inventory merely to simplify this check.
A reload does not mean every old connection instantly disappears. Keep the previous process available for the intended drain interval, within the host's memory budget. If there is not enough memory for two processes, document a stop-and-start release with a brief interruption. Pretending that a constrained host supports a seamless overlap makes the procedure less reliable.
State rollback limits in advance
For a stateless publication, recovery may mean restoring the previous upstream and retaining the new artifact for inspection. That still requires compatible configuration, available files and a functioning previous process. For a stateful application, undoing the executable does not undo writes already made by it.
List the observations that justify rollback: repeated useful-request failures, an unexpected data mutation, or a configuration mismatch. Separate them from transient noise. An optional feed failure can be expected degraded behavior rather than a reason to repeatedly switch the entire site.
If the data has crossed a compatibility boundary, stop the automatic rollback path. Use the documented recovery or forward-fix procedure instead. The person performing the release needs to see this limit before the switch, not discover it while looking for a command to reverse a schema change.
Observe a bounded window
Choose the observation window and evidence before starting. A handful of synthetic requests can catch routing mistakes; they cannot prove sustained load capacity. Request errors, resource use and application outcomes provide different evidence, and each has a sampling limit.
Record what was checked, when, and against which revision. If there were no requests during the window, an error count of zero says little about application behavior. If a signal is missing, label it missing rather than interpreting it as a successful check.
The release is complete when the useful path works, the retained recovery option is understood, and the record explains the final state. Keep cleanup separate: retire the old process only after the agreed observation window, and remove obsolete artifacts according to retention rules. Small changes become easier to operate when each change leaves a precise, modest account of what actually happened.