Skip to content

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

0 of 3 steps done0%

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.

Your computerUndo the bad commit
git log --oneline -n 5
git revert --no-edit <COMMIT_SHA>
git push origin main

Replace <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#

Your computerRebuild and publish an older 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.

Your computerSee previous versions of index.html
aws s3api list-object-versions --region ap-south-1 --bucket <WEB_BUCKET> --prefix index.html \
  --query 'Versions[].{id:VersionId,latest:IsLatest,modified:LastModified}' --output table

Replace <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 actions
Your computerThe same from the CLI
aws codepipeline retry-stage-execution --region ap-south-1 --pipeline-name shortlink-web-prod \
  --stage-name DeployWeb --pipeline-execution-id <EXECUTION_ID> --retry-mode FAILED_ACTIONS

Replace <EXECUTION_ID> with your own value.

How caching behaves#

FileCache headerWhy
index.htmlno-cacheIt references the hashed file names. Browsers must re-check it every visit so they see a new release
assets/index-<hash>.js / .cssS3 default (none)The file name changes when the content changes, so an old file name never serves new code
Anything else (icons, images)S3 defaultRe-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#

SymptomLook at
Pipeline did not startDid the push touch shortlink-web/** or a buildspec? Was it to main? Is the connection Available?
Red BuildCodeBuild log of shortlink-web-build: npm ci, a failing test, or a Vite error
Red DeployWebCodeBuild log of shortlink-web-deploy: AccessDenied or a wrong bucket
Site unchanged after greenHard refresh; the bucket named in the DeployWeb log
Site broken after greenThe 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.

GitHubyour fork · mainpushSourceCodeConnectionsAPI BuildCodeBuildWeb BuildCodeBuildDeployAPICodeDeployDeployWebCodeBuild · s3 syncweb waitsEC2 APIagent + hooksS3 websitestatic files
One pipeline can run both paths. The API and web builds run in parallel; the web deploy waits for the API deploy to succeed.

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 output WebArtifact), then a new stage DeployWeb after Deploy with the WebDeploy action taking WebArtifact.
  • 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 staging branch lets you check changes before main.

Next: troubleshooting.

Found a mistake? Edit this page on GitHub.