Rollbacks and operations
Undo a bad release, retry safely, understand caching, and combine both pipelines if you want one.
About 15 min · Verified 8 October 2026
On this page
Rolling back a bad website release#
There is no CodeDeploy here, so there is no automatic rollback. A website release is just a new build that overwrites files. Use Git as your rollback tool.
Option 1: revert in Git (recommended)#
git log --oneline -n 5
git revert --no-edit <COMMIT_SHA>
git push origin mainReplace <COMMIT_SHA> with your own value.
The pipeline tests, builds and publishes the reverted code. You keep a clear history and the same safety checks.
Option 2: run the pipeline on a known-good commit#
aws codepipeline start-pipeline-execution --region ap-south-1 --name shortlink-web-prod \
--source-revisions actionName=Source,revisionType=COMMIT_ID,revisionValue=<COMMIT_SHA>Replace <COMMIT_SHA> with your own value.
The next push to main will publish whatever main holds again, so follow up with a revert.
Option 3: restore a single file from S3 versioning#
The bucket has versioning on, so a deleted or overwritten object can be recovered. This is for emergencies, not a normal rollback, because a site is many files that must match each other.
aws s3api list-object-versions --region ap-south-1 --bucket <WEB_BUCKET> --prefix index.html \
--query 'Versions[].{id:VersionId,latest:IsLatest,modified:LastModified}' --output tableReplace <WEB_BUCKET> with your own value (or fill in the known ones once under My values at the top of the page).
Retry without rebuilding#
If DeployWeb failed but Build succeeded (for example a missing S3 permission), fix the cause and retry just that stage, so the already-built artifact is reused:
CodePipelineshortlink-web-prodDeployWebRetry stageRetry failed actionsaws codepipeline retry-stage-execution --region ap-south-1 --pipeline-name shortlink-web-prod \
--stage-name DeployWeb --pipeline-execution-id <EXECUTION_ID> --retry-mode FAILED_ACTIONSReplace <EXECUTION_ID> with your own value.
How caching behaves#
| File | Cache header | Why |
|---|---|---|
index.html | no-cache | It references the hashed file names. Browsers must re-check it every visit so they see a new release |
assets/index-<hash>.js / .css | S3 default (none) | The file name changes when the content changes, so an old file name never serves new code |
| Anything else (icons, images) | S3 default | Re-uploaded only when changed |
--delete removes asset files from earlier builds. A visitor who loaded the page just before a release may briefly request an old asset that is gone and see an error until they reload. That is an accepted trade-off for a small site.
Where to look#
| Symptom | Look at |
|---|---|
| Pipeline did not start | Did the push touch shortlink-web/** or a buildspec? Was it to main? Is the connection Available? |
| Red Build | CodeBuild log of shortlink-web-build: npm ci, a failing test, or a Vite error |
| Red DeployWeb | CodeBuild log of shortlink-web-deploy: AccessDenied or a wrong bucket |
| Site unchanged after green | Hard refresh; the bucket named in the DeployWeb log |
| Site broken after green | The browser console and Network tab; compare VITE_API_BASE_URL and the API's CORS_ORIGIN |
One pipeline for both apps (optional)#
You can run the API and the website from a single pipeline. This is how the reference deployment was built, and it suits teams that always release both together.
The stage order is Source → Build (API and Web in parallel) → DeployAPI → DeployWeb. The web deploy waits for the API deploy, so a new frontend never goes live against an API that failed to deploy.
- Create it from the backend pipeline: edit it, add a second action in the Build stage (a parallel CodeBuild action,
WebBuild, with outputWebArtifact), then a new stageDeployWebafterDeploywith theWebDeployaction takingWebArtifact. - In the editor, Add action group inside a stage means parallel. A stage added below another means sequential. Put the two builds side by side and each deploy in its own stage.
- Remove the file-path filters, or widen them to cover both apps.
Good habits and next steps#
- Review before you merge. Short-lived branches, pull requests into your own fork, and branch protection on
main. - Add a notification for failed executions (NotifyCreate notification rule, send to an SNS topic).
- HTTPS and a CDN. Add a domain, a certificate and CloudFront in front of S3, then make the bucket private. You then publish to the same bucket and add an invalidation step.
- Preview environments. A second bucket and pipeline on a
stagingbranch lets you check changes beforemain.
Next: troubleshooting.
Found a mistake? Edit this page on GitHub.