For the AWS H0 Hackathon, I built and deployed ChatScroll
— a full-stack AI knowledge management app — using Next.js
on Vercel for the frontend and ASP.NET Core 9 on AWS ECS
Fargate for the backend. Here's how the deployment
architecture works and what I learned.
The Stack
Frontend: Next.js 14 App Router + TypeScript +
Tailwind CSS deployed on Vercel
Backend: ASP.NET Core 9 API running on AWS ECS Fargate
- Containerized with Docker
- Images stored in Amazon ECR
- Deployed automatically via GitHub Actions
Databases:
- Amazon Aurora PostgreSQL (pgvector, ltree, tsvector)
- Amazon DynamoDB (chat messages, TTL)
Auth: AWS Cognito with JWT verification
The CI/CD Pipeline
Every push to master triggers this automated pipeline:
git push → GitHub Actions → docker build → ECR push → ECS deploy → ✅ live
The key insight I learned: --force-new-deployment alone
does NOT pick up new Docker images. It just restarts the
service using the existing task definition.
The correct approach:
- Fetch current task definition via
describe-task-definition - Update the container image to the new SHA-tagged ECR image
- Register a NEW task definition revision
- Pass the new revision ARN explicitly to
update-service
NEW_TASK_DEF=$(echo "$TASK_DEF" | jq \
--arg IMAGE "$ECR_REPO:${{ github.sha }}" \
'.containerDefinitions[0].image = $IMAGE |
del(.taskDefinitionArn, .revision, .status,
.requiresAttributes, .placementConstraints,
.compatibilities, .registeredAt, .registeredBy)')
NEW_REVISION=$(aws ecs register-task-definition \
--cli-input-json "$NEW_TASK_DEF" \
--query 'taskDefinition.taskDefinitionArn' \
--output text)
aws ecs update-service \
--cluster default \
--service chatscroll-api \
--task-definition $NEW_REVISION \
--force-new-deployment
This ensures every deploy runs the exact new image.
Vercel + AWS Together
The combination of Vercel and AWS works beautifully:
- Vercel handles frontend deployment, CDN, and edge caching — zero configuration needed
- AWS ECS handles the backend with full control over the runtime environment
- Environment variables in both Vercel and ECS task definitions keep secrets secure
The frontend on Vercel calls the backend on ECS via
REST API — clean separation of concerns with each
platform doing what it does best.
Anonymous → Authenticated Migration
One interesting challenge: users can chat and save
Scrolls before signing up. When they create an account,
their anonymous data needs to migrate to their new
Cognito identity.
I built a POST /api/users/me/migrate-anonymous endpoint:
- Requires valid JWT (authenticated)
- Accepts the anonymous UUID from localStorage
- Runs 4 UPDATE statements atomically in Aurora
- Removes the anonymous user row after migration
- Frontend calls it once on first login then never again
This means users never lose their data when they sign up.
What I Built in One Hackathon
- Full CI/CD pipeline from git push to live ECS deployment
- Dual database architecture (Aurora + DynamoDB)
- Semantic search with pgvector and 3072-dim embeddings
- AWS Cognito authentication with anonymous migration
- Study Mode flashcards, scroll sharing, semantic search
Try it: https://chatscroll.vercel.app
Architecture: https://chatscroll.vercel.app/aws-showcase
I created this content for the purposes of entering
the AWS H0 Hackathon.
Top comments (0)