Going Live Properly: The Plan (9 October 2026, revised the same day)

What this is. The step-by-step plan that follows from PRODUCTION-RESEARCH-2026-10-09.md, sized for a pilot: the one server and one database already decided in docs/27, about $66 a month at the start and about $103 at 1,000 students a year in (§2), plus the things that are nearly free and matter most: logs you can search, alarms that reach a phone, deploys with no outage, backups you have proven you can restore, and cookies that cannot leak across subdomains.

It has three parts:

Status: the decisions in §1 were approved on 11 October 2026. Sections 3 to 7 explain the four that needed working out: videos, releases, retention and the night window, and how the plan grows. Nothing is built yet. Part A starts with the account steps (A-steps 1 to 14), and every later phase begins only after the gate before it is ticked by a named person.


1. Decisions first (Gate 0)

#DecisionRecommendedAlternativeMonthly effect
D1RegionUS East (N. Virginia), as docs/27 decidednone
D2ShapeOne EC2 t4g.medium + RDS db.t4g.micro, as docs/27 decided$44.56
D3One front doorYes: API served at thnkrr.com/api through the existing CloudFront, host-only cookiesKeep api.thnkrr.com with the .thnkrr.com cookienone
D4Logging and alarmsYes, the right-sized set (B7, A-steps 22 to 25)about $4
D5Releases with no outageDecided: the new version runs beside the old one, passes automatic checks, then takes 1 request in 10 for 10 minutes before taking over; the old one stays warm for 30 minutes (§4, B9)Restart with a brief outagenone
D6Firewall (WAF managed rules)Switch on the week real students arriveNever / from day one$8 when on
D7VideoDecided: our own speech-to-text transcript and the captions get the writing check; a person watches every video; known child-abuse matching as D11; no AI judging the pictures (§3). Memory caps addedFrame check on every second of videonone / about $20 at 1,000 students
D8Retention numbersDecided (§5), changeable on request: messages 2 years; closed accounts deleted in 30 days with a locked legal copy for 1 year; dormant accounts 3 years; removed content 1 year; logs 1 year; backups 12 monthsFounder and lawyer set different numbersslows storage growth
D9Monthly update windowDecided: Sunday 3:00 to 3:30 am US Eastern. The server is replaced by a freshly updated one rather than restarted, so there is no outage; the database's updates take under a minute, and its rare required fixes a few minutes, with a banner that works even while the server is away (§6)A second server and load balancer (no window)about 5 cents / about $45
D10Budget alarmsAlarm at $80, ceiling $95 while the pilot is under about 300 students. Raise to $120 and $140 before 1,000 students (§2)One fixed ceilingnone
D11Known child-abuse matchingDecide before deploying (by Gate 2). The code has a ready slot with nothing connected; the server won't start in production until the choice is written in its settings. Recommended: connect NCMEC's list and PhotoDNA for photos, Google CSAI Match and Project Arachnid for video, as each application is approved; until then none, where the person reviewing each upload is the only checkDeploy with none and connect laternone (all free)
D12Security monitoringDecided: GuardDuty on from day one, base protection only (account activity, network and DNS records); its optional add-ons stay off. Findings go to the alarm inbox and phoneOff until a school asksabout $5 to $13

2. What it all costs

Everything this plan uses, priced in US East. "1,000 students" means 1,000 active students, each writing about 100 checked posts, comments and messages a month, uploading 3 photos, and 1 in 5 posting a 1.5-minute video (the same usage as docs/27 §12). All of it is paid from the AWS credits.

What we use from day one

WhatWhat it isStart (about 20 students)1,000 students, first month1,000 students, a year in
ServerEC2 t4g.medium $24.53, its 30 GB disk $2.40, its fixed address $3.65$30.58$30.58$30.58
DatabaseRDS db.t4g.micro $11.68, its 20 GB disk $2.30$13.98$13.98$13.98
Files and deliveryPhotos, videos and the website in S3; CloudFront delivery is free up to 1 TB a month$0.10$1.15$13.80
Logs, alarms, outside health checkCloudWatch above its free 5 GB, plus the Route 53 health check $1.50$2$4$4
DNSRoute 53 for thnkrr.com: $0.50 for the domain plus lookups$1$1$1
AI writing checkBedrock, about $0.155 per 1,000 checks$0.31$15.50$15.50
Photo checkRekognition, $1 per 1,000 photos. Flags photos for the reviewer; never approves on its own. Needs the AI-services opt-out (A-step 11) first$0.12$6$6
Video transcriptsWhisper on our own server, so no extra charge$0$0$0
Known child-abuse matching (photos and video)NCMEC's list, PhotoDNA, Google CSAI Match, Project Arachnid: free, once the founder's applications are approved (D11)$0$0$0
EmailSES, $0.10 per 1,000 emails$0.01$0.50$0.50
FirewallWAF managed rules (D6: on the week real students arrive)$8$8$8
Security monitoringGuardDuty (D12), base protection: $4 per million account events read, $1 per GB of network and DNS records. Watches for signs of a break-in and alarms; never blocks. Free for the first month, which also shows our real monthly estimate$10$10$10
Backups, CloudTrail, Budgets, Parameter Store, Session Manager, certificates, basic attack protectionInside free allowances at this size$0$0$0
Total a monthabout $66about $91about $103

The only line that grows on its own is files: storage adds about $1.15 a month for every month at 1,000 students. The retention numbers in §5 slow that: the full-quality originals, about half of it, go after 30 days. The monthly server swap (§6) adds about 5 cents a month.

Not used (the trigger to reconsider each is in C5): the frame-by-frame video check ($18 to $22 a month at 1,000 students) and Amazon Transcribe (Whisper does this job).

GuardDuty's line is an estimate between about $5 and $13: it depends on how busy the account is, which nobody knows until it runs. Its free first month shows the real figure; D10's alarms are set with room for the high end.

The credits. About $5,000 (docs/18). At $66 a month they last about 6 years; at $103, about 4 years.


Words used in sections 3 to 7

WordWhat it means here
RequestOne question the app asks our server, such as "show me the feed". A page needs a few
PortA numbered door on the server. Two versions of Thnkrr can run side by side on two doors
Table, row, fieldThe database keeps information in tables, like spreadsheets: a row is one item (one message), a field is one column (its text, its time)
Postgres, minor versionPostgres is our database program. A minor version is a small update to it (17.4 to 17.5), mostly fixes
Background workWork nobody waits for on screen: the AI checks, emails, converting videos
The consoleAmazon's website for running our account
DNSThe internet's address book: it turns thnkrr.com into the number of the machine to connect to
Security certificateWhat lets a browser trust it is talking to the real Thnkrr over an encrypted connection
origin.thnkrr.comA behind-the-scenes name for our server. Only Amazon's delivery network (CloudFront) uses it; visitors never see it
ProductionThe real site that students use, as opposed to test copies
Standby database (Multi-AZ)A second copy of the database, kept in step in another Amazon building, that takes over within about a minute
Containers (Fargate), templatesContainers package the app so Amazon can start and replace copies of it by itself. Templates are files that describe our whole Amazon setup, so it can be rebuilt by a command
NCMECThe US national centre that receives reports of child sexual abuse material
Child Safety LeadThe staff member in charge of child-safety cases
A-step, B-item, C5A-steps are the hand steps in Part A; B-items (B9, B16) are entries in Part B, the build list; C5 is the parked list in Part C

India's rules appear below even though the pilot is in the US. They apply once we have Indian users, and we follow them now so nothing has to change when that happens (DEADLINES-AND-DATA-2026-10-07.md explains each).

3. How videos are checked (D7)

Three things happen to every video, and no AI decides anything about the pictures.

  1. Our own server writes down what is said. Whisper (speech-to-text that runs on our server, so the audio never leaves it) turns the sound into text. That text, together with any captions the student typed, goes through the same writing check as a post. A spoken phone number or a spoken threat is caught the same way a written one is.
  2. A person watches every video before anyone else can see it. No video goes live on an AI's say-so, however clean its transcript is.
  3. Known child-abuse material is matched against shared lists once the founder's applications to those programmes (NCMEC's list, Microsoft's PhotoDNA, Google's CSAI Match; D11) are approved. This compares a fingerprint of the video with material NCMEC and others have already confirmed. It is matching, not an AI judging what it sees.

One detail to know. The photo check (an Amazon AI that looks for nudity and violence, switched on at launch once Amazon is told not to keep our pictures, A-step 11) also looks at one picture per video: the sheet of 30 small stills that our server makes for the reviewer. It costs about $1 per 1,000 videos and works exactly like the photo check: it never approves or rejects anything, and if it sees something, that video moves to the front of the reviewer's list. This is not the frame-by-frame check D7 rules out, which would look at every second of every video for about $90 per 1,000 videos. If you would rather it left videos alone, it is a one-line change.

4. Releasing a new version without an outage (D5)

The idea. We never stop the running version to start the new one. The new version starts next to it on the same server, proves itself first on automatic checks and then on a small share of real visitors, and only then takes over. The old version stays running, unused, for half an hour, so we can switch back in seconds. Big companies call the small-share step a "canary" (a few go first) and the two-copies idea "blue/green". We do both on one server, because one is all we need yet.

The steps. One command (deploy.sh) runs all of them and stops at the first problem.

StepWhat happensIf it goes wrong
1. PrepareThe new version is built in its own folder. Database changes are applied. They only ever add things, so the running version doesn't noticeThe script stops. Nothing has changed for anyone
2. Start beside the old oneThe new version starts on a spare port. Nobody is sent to it yet, and it does no background work (AI checks, emails, videos)It is stopped. Nobody saw it
3. Automatic checksThe script asks it directly: can it reach the database? Then a test account signs in and opens the feed, a profile, messages, alerts, search and the review list, plus a public profile signed out and the complaint and removal forms. Every answer must be right and arrive within a secondIt is stopped. Nobody saw it
4. Trial on real visitors1 request in 10 goes to the new version for 10 minutes. The script compares the two versions' errors and speed side by sideEverything goes back to the old one within seconds, with a message saying why, if the new one's failure rate is more than 1 in 100 above the old one's, or it takes over 1.5 times as long to answer
5. SwitchAll visitors and all background work move to the new version
6. Keep the old one warmThe old version keeps running, with nobody on it, for 30 minutes. One command (rollback.sh) brings it back in seconds
7. Tidy upThe old version stops. The last two versions stay on the server's disk, so going back later still takes only about a minute

A release takes about 15 minutes, then the half hour with the old version kept warm. Release on a working morning when someone can watch. Never release on a Friday evening or just before the lunchtime rush.

The website (the part that runs in the browser) follows only once the server has fully switched. New files are added next to the old ones, which stay for 30 days, so a tab that is already open keeps working. The app checks for a newer version every 10 minutes and whenever the tab comes back into view. When it finds one, it says "A new version of Thnkrr is ready" and switches quietly the next time the student changes page, never in the middle of typing.

Three rules make this safe. Each is checked automatically before a release:

  1. Database changes only add things during a release. Removing or renaming something happens in a later release, once no running version uses it. For example, a table stops being used in one release and is deleted in the next. A check fails any release whose database change removes or renames something without marking it as that second half.
  2. The server keeps answering the previous website the same way. Fields are added, never removed or renamed in the same release. The type definitions the website and server already share make this a check, not a promise.
  3. Only one version does background work at a time. A job cut off half-way, such as a video being converted, simply starts again. Every job is already written to be safe to repeat.

During the 10-minute trial, the per-person limits (requests a minute, posts a minute) are counted by each version separately, so they are briefly up to twice as generous. That is harmless for 10 minutes. It gets fixed properly before a second server ever exists (§7, stage 3).

A snapshot first, only when needed. A snapshot is a full copy of the database at one moment. Today the release script asks the person releasing to take one before it changes the database. It will now ask only when a release removes something, because releases that only add things can always be undone by switching back.

5. How long we keep things (D8)

These are our numbers. They meet every legal deadline in DEADLINES-AND-DATA-2026-10-07.md with room to spare, and each one is a single setting, so it can change whenever the founder or the lawyer asks.

Four rules sit behind them:

WhatHow longThenWhy this number
Messages2 years from sendingDeletedA problem reported late still has its record: grooming often comes to light months later. Longer than every legal minimum (1 year). Students still can't delete messages themselves; that safety rule stays. When an account closes, its messages follow the closed-account rule below, for both people in the conversation
Closed accountsHidden within 24 hours, deleted within 30 daysA locked copy of what the law needs (sign-up details, messages, the record of activity) is kept 1 year, seen only by the safety team or for a legal request, then deletedLinkedIn deletes in 30 days. One year covers the 180 days in India's IT Rules, and the 1 year that India's data protection law requires from May 2027
Accounts nobody signs into3 years without a sign-inEmails 30 days and 7 days before; then closed as aboveA student can come back after school. Three years covers a gap year and the start of college
Content we removed1 year after removal, lockedDeletedIndia requires 180 days; the US child-abuse law requires 1 year for reported material. One number covers both
Child-safety evidence, and anything reported to NCMECAt least 1 year after the report; longer if the police askDeleted only by the Child Safety Lead, once the hold endsUS law. Already built so that no reviewer can delete it
Moderation records (the AI's answer and the reviewer's decision)2 yearsDeleted, unless linked to a holdLong enough to see a pattern in someone's history and to answer an appeal. Each record also holds a copy of the words it checked; for approved items that copy is deleted after 90 days, since the post or message itself still has the words
Complaints, court and government orders, and how we handled each3 years after closingDeletedProves we met each deadline. Three years is the usual time limit for bringing a claim, in both the US and India
"Who did what" (the record of staff actions)3 yearsDeleted, unless linked to a holdSame reason
A parent's permission (proof a guardian said yes)While the account is open, plus 3 yearsDeletedWe must be able to prove permission was given if anyone asks later
Sign-ups whose parent never answers30 daysDeletedAlready built
Alerts ("Maya commented on your post")90 daysDeletedLinkedIn does the same
"Who viewed your profile"90 daysDeletedAlready built
Full-quality original uploads (locked away; nobody sees them)30 days after the safe versions are approvedDeleted, unless linked to a holdOnly the safe versions are ever shown, and keeping the originals doubles storage
Rejected uploads30 daysDeleted, unless the rejection opened a safety case
Server logs90 days searchable, then a compressed copy until 1 yearDeletedIndia's cyber-security agency (CERT-In) requires 180 days; India's data law asks for 1 year from May 2027. Logs never contain what people wrote
Expired sign-ins30 days after they endDeleted
Background job records30 daysDeleted
Database backupsDaily ones 35 days; one a month for 12 monthsDeleted automaticallyOnce something is deleted, the last backup holding it expires within 12 months. The privacy notice says so
A school leaves, or its contract endsStudents are offered a copy of their own work; then the school's student data is deleted within 60 days, confirmed in writingThe standard US school data agreement (NDPA)
Anyone found to be under 13Deleted at once, except safety evidenceUS children's privacy law (COPPA)

Two things make deleting real.

What it costs, or saves. These numbers slow the one cost in §2 that grows on its own: files. The full-quality originals are about half of that growth, and they go after 30 days.

6. The monthly night window (D9)

What needs updating every month. The server's operating system and programs receive security fixes all the time. Most install themselves every night without stopping anything. A few, mainly fixes to the core of the operating system, only take effect after a restart, so once a month the server needs to start fresh. The database receives its own updates from Amazon a few times a year.

When. Sunday, 3:00 to 3:30 am US Eastern: the quietest half hour for US schools, and the pilot schools are in the US. We check it against the first month of real sign-in times, and move it when schools in other time zones join.

The server: replaced, not restarted

Restarting our one server means 1 to 2 minutes with no Thnkrr. So instead we build a fresh, fully updated server, move the site to it, and keep the old one switched off for a day as a spare.

StepWhat happensWhat students notice
1A new server is made from the same recipe as the first, with every update already installed. The same version of Thnkrr goes on it, plus the one before (so going back still works), and the same automatic checks as a release (§4) run against itNothing
2Background work (AI checks, emails, videos) moves to the new server. A video half-converted on the old one starts again on the new oneNothing
3The server's fixed internet address moves to the new server, which takes a few secondsThe few requests in flight in those seconds fail. The app repeats page loads by itself. Anything being sent shows "Couldn't send, try again", with the text still in the box
4The old server is switched off, not deleted. If anything is wrong in the next 24 hours, the address moves backNothing
5After 24 hours, the old server is deletedNothing

This costs about 5 cents a month: two servers for an hour. And it gives us something for free: every month we prove we can rebuild the server from scratch, which is the disaster drill most small teams never get round to.

It works only if the server holds nothing that exists nowhere else. That is already true for uploads (they go straight to file storage), secrets (Parameter Store) and logs (CloudWatch). One thing needs work: the server's security certificate. The server gets its own name, origin.thnkrr.com. It proves it owns that name through our DNS. So a new server can get its certificate before it takes the address (B17). A video being converted at the moment of the swap needs nothing: it simply starts again.

The database: Amazon's updates, on our schedule

Kind of updateHow oftenWhat we doWhat students notice
A new minor version of PostgresA few times a yearAutomatic upgrades stay off. In our window, Amazon makes an upgraded copy kept in step with the real one (its "blue/green" feature). We test the copy, then switch to itUnder a minute when saving pauses. What is already on screen stays
Amazon's own required fixes to the database machineRare, and announced weeks ahead in the consoleScheduled into our window, with the banner set the day beforeA few minutes when Thnkrr can't save or load anything new. This is the one real outage left. A standby database removes most of it (§7, stage 2)

When the server or the database is away for a few minutes

Even with all of the above, something can be away for a few minutes, planned or not. This is what students see then, and what each part needs:

WhatHow it worksWhere it stands
The website still opensIt is files on Amazon's delivery network (CloudFront), not on our serverAlready true
A banner explainsA small status file sits on the delivery network, not on our server, so it works while the server is away. The app shows "Thnkrr is updating. Back in a few minutes. Nothing you've written is lost." as soon as the server stops answering. Staff can also set a planned message ahead of timeTo build (B16)
Nobody gets signed outOnly a real "your sign-in has ended" answer signs anyone out. A server that doesn't answer signs nobody outAlready true (checked in the code)
Open pages keep their contentWhat a student has loaded stays on screen. The app retries quietly every 20 seconds and removes the banner when we're backTo build (B16)
Nothing typed is lostA post, comment or message being written stays in its box. The Send button says "Thnkrr is updating, try again in a minute"To build (B16)
A friendly page, not an errorWhen our server doesn't answer, the delivery network gives the app a short "updating" reply it recognises. Public profile pages show a plain "This page is being updated" pageTo build (B16)
Urgent legal requests still get inThe complaint and intimate-image removal forms show an email address to use while we're away. The time the email arrives counts toward the deadlineTo build (B16)
The server survives the database going awayToday it doesn't. We tested it: when the database restarts, our server program shuts down completely instead of waiting and reconnecting. The fix is one small change, with a test that restarts the database underneath a running serverFix first (B16)
Alarms don't wake anyone for planned workThe window script pauses the "site down" alarm for its half hour and switches it back on at the end, whatever happensTo build (B17)

Deadlines keep running through the window. A 2-hour legal clock doesn't stop for our update. That is why the window is half an hour at the quietest time, why the person doing it is the on-call person named in A-step 14, and why its last step is to open the review list and check that nothing urgent arrived.

What this adds up to. Releases and server updates: no outage, at most a few seconds in which a request is repeated. Database version updates: under a minute, a few times a year. Amazon's rare required database fixes: a few minutes, announced ahead. Unplanned failures are rarer. If the server's hardware fails, Amazon moves it to new hardware within minutes (the recovery alarm in A-step 21), or the swap script (B17) builds a new server in about 15 minutes. If the database machine fails, Amazon usually restarts it within minutes. At worst, we restore from backup, which we practise (A-step 35). A standby database (stage 2) cuts that case to about a minute.

7. How this plan grows

The plan above is sized for the pilot. Each step up has a trigger: a measurement that tells us it is time, not a date. Nothing is bought early. C5 lists the detailed triggers for every parked piece.

StageWhenWhat changesMonthly effect
1. Pilot launchNow, up to about 300 studentsEverything in this plan: one server and one database, releases with a trial (§4), the clean-up numbers (§5), the monthly server swap and the banner (§6)about $66 to $75
2. More pilotsAbout 300 to 3,000 students, or the first paid school contractA standby database; a small video server; a staging server; a night-and-weekend on-call rota (details below)+$12 standby database, +$12 video server, +$5 to $10 staging
3. 3,000 to 5,000 students using it each dayThe server's processor is regularly above 70% at peak, or the load test (A-step 34) at the new size misses its marksFirst the "before a second server" work from the load audit (PLUG-AND-PLAY-AUDIT-2026-10-10.md, Phase D): per-person limits shared between servers, and new messages and alerts pushed to the browser at once instead of each open tab asking every 30 seconds. Then a second server behind a load balancer. From here there is no window for the servers at all: releases and updates go one server at a time. The database moves up a size when its measurements say so. Big tables are split by month once past about a million rows+$45 load balancer and second server, +$12 to $35 bigger database
4. 10,000+ users, or schools outside the USIndian schools join; or a second engineering team; or more servers than one person can look after by handIndian users' logs kept within India's reach, which may mean a setup in Mumbai. Containers (Fargate), with releases that roll themselves back. Every piece of AWS written down as templates, so a whole copy can be built in an hour. A read-only copy of the database for searchPriced at the time, with a table like §2

Stage 2 in more detail. Each piece has its own trigger:

How releases, monthly updates and retention change along the way:

Stage 1Stage 2Stage 3Stage 4
ReleasesTwo versions on one server, with the 1-in-10 trialThe same, tried on staging firstOne server at a time behind the load balancer, with the same checks and trialContainers; Amazon rolls back by itself when checks fail
Monthly updatesServer swapped with no outage; database a few minutes, a few times a yearDatabase about 1 minuteNo window for servers; database about 1 minuteThe same
RetentionThe §5 numbers, with nightly clean-upThe sameOld months removed in one step once tables are splitThe same, plus copies kept in India if the lawyer says so

Part A: What you do by hand

You = the founder or CTO, in the AWS console, the domain's DNS, or a browser. Where a step says "run the script", the agent has written it (Part B) and you paste one command into Session Manager. Each step ends with Check: the thing you must see before moving on. Do them in order.

A1. The account (Phase 0, about half a day plus Amazon's SES wait)

#StepCheck
1Sign in as root. Security credentials → turn on MFA with an authenticator app. Make sure root has no access keys. Account → Alternate contacts: fill billing, operations, securitySigning in as root asks for the 6-digit code. Access keys section says "No access keys"
2IAM Identity Center → enable → create a user for yourself and one for the CTO, each in an Administrators permission set, each with MFAYou can sign in through the Identity Center portal, open the console, and root is no longer needed
3Billing → Credits: read the expiry date and "applicable products". Write both into docs/28 (give them to the agent)The two values are in docs/28
4Budgets: create two monthly cost budgets, $80 and $95 (D10), emailing OPS_EMAIL. Cost Anomaly Detection: create a monitor for all services with an alert to the same addressBoth budgets show "OK"; the anomaly monitor shows "Active"
5CloudTrail → create a trail for all regions, management events, into a new bucket thnkrr-cloudtrail-<account id>; leave the first copy freeAfter 15 minutes, the trail's bucket contains a folder with today's date
6S3 → Block Public Access settings for this account → all four on. EC2 → Settings → EBS encryption → "Always encrypt new EBS volumes" onBoth pages show the setting enabled
7Set the console region (top right) to US East (N. Virginia) and keep it there for every step belowThe header says "N. Virginia"
8SES → Account dashboard → Request production access: Transactional, website https://thnkrr.com, describe sign-up/consent/alert emailsAn email from AWS says the request is received; within about a day, another says production access is granted. The dashboard no longer says "Sandbox"
9SES → Identities → Create identity → Domain thnkrr.com, Easy DKIM 2048. Add the 3 CNAME records it shows at your DNS provider. Then Custom MAIL FROM mail.thnkrr.com (add its MX and TXT). Then add a DMARC TXT at _dmarc.thnkrr.com: v=DMARC1; p=none; rua=mailto:<OPS_EMAIL>The identity shows Verified and DKIM Successful; MAIL FROM shows Verified; a DMARC lookup tool shows the record
10Bedrock: run the data-retention command from docs/27 A8 in CloudShell (mode none), then delete the temporary API key. Leave model invocation logging offThe command returns success; Bedrock → API keys shows none
11AWS Organizations → create (free) → Policies → AI services opt-out policy → opt out of all services → attach to the root. Optional, if you want the one-region rule enforced: an SCP denying actions outside us-east-1 using Amazon's example (the agent gives you the text)The policy shows "Attached"; a test call to a service in Ohio (the agent provides a harmless one) is denied if the SCP is on
12Service Quotas: write down the values for openai.gpt-oss-safeguard-20b requests and tokens per minute, and Rekognition DetectModerationLabels TPSThe numbers are in docs/28
13Domain: thnkrr.com is ours and fully under our control. Route 53 → Hosted zone thnkrr.com, then at the registrar change the nameservers to the four Route 53 gives you. Copy any records the domain already has (email, verification) into the hosted zone firstAfter the nameserver change (up to 48 h), dig NS thnkrr.com shows the Route 53 servers
14Decide and write into docs/28: the on-call person, the phone number for alarm texts, the inbox for alarm emails (OPS_EMAIL)Written in docs/28
15Tick the decisions in §1 with the CTO (D11 can wait until Gate 2)Each row has a name and date

Gate 0 ticked by: founder (decisions), CTO (steps 1 to 14).

A2. The AWS side (Phase 2, about one day; after the agent's Part B is merged)

#StepCheck
16ACM (us-east-1) → request a public certificate for thnkrr.com, www.thnkrr.com, media.thnkrr.com, DNS validation → "Create records in Route 53" (one click)Certificate status Issued
17VPC → Security groups: thnkrr-api (inbound 443 and 80 from the CloudFront origin-facing managed prefix list only; nothing else), thnkrr-db (inbound 5432 from thnkrr-api only)Each group's inbound tab shows exactly those rules; no 0.0.0.0/0 on thnkrr-api except none
18RDS → Create database: PostgreSQL 17, db.t4g.micro, 20 GB gp3 with autoscaling to 100 GB, not publicly accessible, security group thnkrr-db, backups 35 days, deletion protection on, encryption on, Database Insights standard, automatic minor upgrade off, maintenance window Sunday 07:00 to 07:30 UTC (3:00 am US Eastern, §6), database and user thnkrr, master password managed in Secrets Manager: no (keep it simple; store it in Parameter Store in step 20). Parameter group: log_min_duration_statement = 1000, shared_preload_libraries includes pg_stat_statementsStatus Available; the endpoint is visible; Backups tab shows retention 35
19IAM → Roles → Create role thnkrr-api-server for EC2 with the policy the agent wrote (deploy/aws/iam-api-server-policy.json: the two media buckets, the log-copy and evidence buckets (write only), the one Route 53 record for the origin certificate (B17), Bedrock InvokeModel on the listed models, CloudFront invalidation, Parameter Store read on /thnkrr/prod/*, CloudWatch agent, Session Manager)The role exists with that policy and the two AWS-managed policies AmazonSSMManagedInstanceCore and CloudWatchAgentServerPolicy
20Systems Manager → Parameter Store: create the secrets under /thnkrr/prod/ as SecureString (DATABASE_URL, COOKIE_SECRET, TOKEN_SECRET, DATA_ENCRYPTION_KEY, SMTP_URL, EDGE_SHARED_SECRET). Generate the random ones with the commands in deploy/README.md. Put the same values in the password managerSix parameters listed; the password manager has all six
21CloudFormation → Create stack → upload deploy/aws/server.yml (the server's recipe, B17: Ubuntu 24.04 ARM, t4g.medium, 30 GB gp3, role thnkrr-api-server, security group thnkrr-api, IMDSv2 required, no key pair), then launch the first server from its launch template. Then Elastic IPs → Allocate → Associate to it. Status checks → Actions → Create status check alarm with "Recover this instance"Instance Running, 2/2 checks passed; the Elastic IP shows the instance; the recovery alarm exists
22Connect → Session Manager. Paste the one command from deploy/README.md that runs scripts/server-setup.sh (installs Node, ffmpeg, whisper.cpp, Caddy, the CloudWatch agent, creates the thnkrr user, fetches secrets from Parameter Store into /etc/thnkrr/api.env, installs the systemd unit and Caddyfile)The script ends with "SETUP OK" and prints the versions. systemctl status caddy amazon-cloudwatch-agent both active
23Still in Session Manager: sudo /opt/thnkrr/api/scripts/deploy.sh origin/dev/pilot. Answer yes to the snapshot question only after taking one (RDS → Actions → Take snapshot; first deploy: the database is empty, so answer yes)The script ends with "OK: <sha> is live and healthy". curl -s localhost:3001/health/ready returns "ok":true with the git version
24CloudFormation → Create stack → upload deploy/aws/observability.yml (log groups with 90-day retention, metric filters, the 10 alarms, the SNS topic, the dashboard, the Route 53 health check). Parameters: OPS_EMAIL, on-call phone, health-check target. Then open the confirmation email SNS sends and click confirmStack CREATE_COMPLETE; SNS → Subscriptions shows the email Confirmed and the SMS Confirmed; CloudWatch → Alarms shows 10 alarms, all OK or Insufficient data; GuardDuty → Summary shows it enabled, and EventBridge shows the rule thnkrr-guardduty-findings
25CloudFormation → Create stack → upload deploy/aws/storage.yml (web bucket; the two media buckets with their CORS and lifecycle rules from docs/27 §8; thnkrr-evidence with versioning and Object Lock compliance; thnkrr-logs for the monthly log copies, deleted after 1 year; status.json, maintenance.json and maintenance.html in the web bucket, B16)Stack CREATE_COMPLETE; the evidence bucket's Properties tab shows Object Lock Enabled, Versioning Enabled
26CloudFormation → Create stack → upload deploy/aws/edge.yml (the two CloudFront distributions: web with the /api/*, /in/*, /school/* behaviours to the server, CachingDisabled + AllViewerExceptHostHeader, the X-Thnkrr-Edge secret header, the SPA CloudFront Function, the response-headers policy; media with the 5-minute cache). Parameters: certificate ARN, Elastic IP hostname, the edge secret. WAF parameter off for now (D6)Stack CREATE_COMPLETE; both distributions Deployed; the web one lists three API behaviours
27CloudFormation → Create stack → upload deploy/aws/backup.yml (AWS Backup vault with Vault Lock, a plan taking a monthly RDS snapshot kept 12 months, §5)Stack CREATE_COMPLETE; the vault shows Vault Lock: Locked (after its 3-day cooling period, Compliance)
28Fill the remaining settings in /etc/thnkrr/api.env from .env.example's PROD lines (CLOUDFRONT_MEDIA_DISTRIBUTION_ID, bucket names, S3_PUBLIC_URL, WEB_INDEX_URL, OPS_EMAIL, MAIL_FROM, SUPPORT_EMAIL), then sudo systemctl restart thnkrr-apijournalctl -u thnkrr-api -n 20 shows the startup line with no [storage] unavailable
29The web: in the thnkrr-web folder on your laptop run the one command in its README (VITE_API_URL=https://thnkrr.com/api pnpm build, then the upload and invalidation commands the agent wrote in scripts/publish-web.sh)The script ends with "PUBLISHED <sha>"
30DNS (Route 53): thnkrr.com and www → the web distribution (alias A/AAAA records), media.thnkrr.com → the media distribution (alias), origin.thnkrr.com → the Elastic IP (plain A record; only CloudFront may connect, A-step 17). Do not create api.thnkrr.comhttps://thnkrr.com loads the sign-in page; https://thnkrr.com/api/health returns {"ok":true}; https://media.thnkrr.com/ returns a CloudFront error page, not a bucket listing
31Test an alarm: CloudWatch → Alarms → thnkrr-site-down → Actions → Set alarm state to ALARM for a minuteThe email and the text arrive within two minutes, each containing the runbook link; the alarm returns to OK on its own
32Hand the agent the list of every click above with any deviation, so deploy/README.md matches realityREADME updated and merged

Gate 2 ticked by: CTO (steps 16 to 32).

A3. Prove it (Phase 3, about two days with the agent)

#StepCheck
33Smoke test with staff accounts only, following deploy/runbooks/smoke-test.md (docs/27 B6 and B7: sign up, consent email, post text/photo/video, approve, take down, /in/ while signed out, intimate-image test request, suspend a test student, PDF on a test order, hide a profile, two reviewers on one item)Every row in the runbook's table ticked; the removed photo's link is dead within 5 minutes
34Load test: agree a 30-minute window; the agent runs pnpm load:k6 from a laptop against the live site before any student existsThe report meets the pass marks: 95th percentile under 500 ms for feed and profile, under 300 ms for typeahead, no 5xx, "busy" under 1% of searches, server and database CPU under 70%. If not: resize (D2 up one step) and re-run
35Restore drill: RDS → Databases → thnkrr → Actions → Restore to point in time (yesterday 23:00) into thnkrr-drill, db.t4g.micro, same security group. Give the agent its endpoint; the agent runs the integration suite against it and times everything. Then delete thnkrr-drill (no final snapshot)The suite passes against the restored copy; the time from click to green is written in docs/28; thnkrr-drill is gone
36Also open one monthly log copy: S3 → thnkrr-logs → any object → DownloadThe file opens
37Failure drills (agent drives, you watch the phone): a deploy that fails readiness; sudo systemctl kill thnkrr-api; stand-in AI switched off for 6 minutes; sudo reboot; the database rebooted from the RDS console; replace-server.sh while the agent's 20-a-second loop runsExpected, in order: the old version keeps serving and the script reports; the service is back within 5 s and no alarm fires; "checking is busy" appears and the Moderation-stalled alarm texts you within 5 minutes; the site is back within 2 minutes and the Site-down alarm fires then clears; the banner shows, nobody is signed out, and the site recovers by itself when the database is back; failures only in the seconds the address moves
38Security check: open https://observatory.mozilla.org for thnkrr.com; try https://<elastic ip>/api/health from your laptopGrade A or better; the direct address times out (only CloudFront may reach the server)
39Read the ten alarm runbooks and the incident runbook; put the on-call phone and the status page address in your phoneYou can name, from memory, what to do when the Site-down text arrives

Gate 3 ticked by: CTO (numbers) and founder (plain-words summary from the agent).

A4. Go live (Phase 4)

#StepCheck
40In Session Manager: create the first staff accounts with the ops scripts; give hats with pnpm staff:role <email> <hat> (and a --backup for each). Never run pnpm db:seedpnpm staff:role --list shows every hat with a primary and a backup
41Vercel: archive the thnkrr-web project (keep thnkrr-demo if the founder uses the demo)The old Vercel address no longer serves the app
42For seven days, spend 15 minutes on the CloudWatch dashboard and the alarm history; note anything odd for the agent. On day 7, agree the final alarm thresholdsThresholds recorded in docs/28
43The week real students arrive: if D6 says so, set the EnableWaf parameter in the edge stack to true and update the stackThe web ACL shows in CloudFront's distribution settings; a request with <script> in a query string is blocked
44Then the docs/27 Phase C items: the real Bedrock measurements and the 50 → 150 → 300 ramp; the founder's names and registrationsAs docs/27

Gate 4 ticked by: founder, before the first real school signs up.

A5. Ongoing

WhenWhat you doCheck
Monthly, Sunday 3:00 am US EasternRun scripts/replace-server.sh (§6) from CloudShell. Then open the review listThe script ends with "SWAPPED"; nothing urgent arrived during the window; the next run deletes the old server
When Amazon announces a database update (a few times a year)Schedule it into the window. The day before, pnpm status set "Short update on Sunday 3:00 to 3:30 am. Saving may pause for a few minutes.". Follow database-upgrade.md, then pnpm status clearThe database's Maintenance tab shows nothing pending; the banner is gone
QuarterlyRestore drill (step 35), access review in Identity Center, pnpm outdated review with the agent, Postgres minor version check, alarm thresholds reviewEach written in docs/28 with the date
Once, before the clean-up job starts (B11)The agent runs it in dry-run against a copy of the pilot data; you read the counts; then it switches the retention_job flag onDry-run report read and approved
When the founder or lawyer changes a §5 numberTell the agent; it changes the setting and runs a dry run firstDry-run report read

Part B: What the agent builds, cleans up and updates

Branch feat/production-ready in worktrees off dev/pilot in both repos; pull requests into dev/pilot. Migrations numbered from 0035 (0031 to 0034 came with the load work), additive only. Each item has its "done when"; the agent reports in plain words at each gate.

B1. Build: /api prefix and one front door

B2. Build: cookies and sessions

B3. Build: edge secret on every API route

B4. Build: health endpoints

B5. Build: structured logs and request ids

B6. Build: feature switches

B7. Build: the server scripts and AWS templates (the files you upload or run in Part A)

B8. Build: background work cannot starve the API

B9. Build: releases with no outage (§4)

B10. Build: search check at pilot size

B11. Build: the clean-up jobs (§5; switch off until the dry run is read)

B12. Build: load test, smoke test and drills

B13. Build: runbooks and the decision record

B14. Clean up

B15. Update

B16. Build: when the server or database is away (§6)

B17. Build: the monthly server swap (§6)

Gate 1 ticked by: CTO, after CI is green on both repos, B7's scripts and templates pass their checks on a fresh VM, and the benchmark numbers are in docs/28.


Part C: Order, alarms, parked items

C1. Order and time

PhaseWhoAbout
0. Account (A1)founder, CTOhalf a day + Amazon's SES wait
1. Code, scripts, templates (Part B)agent8 working days
2. AWS side (A2)CTO, with the agent's files1 day
3. Prove it (A3)agent, CTO2 days
4. Go live (A4)CTO, founderhalf a day, then a week of watching
5. After launch (A5, B11)agentclean-up job switched on after its dry run; the monthly swap; quarterly reviews

Roughly three working weeks from Gate 0 to a production site that staff can test, at about $48 a month (the firewall's $8 starts the week real students arrive).

C2. Gates

GateTicked byMeans
0founder, CTODecisions D1 to D10 and D12 (approved 11 October 2026); A-steps 1 to 14
1CTOPart B merged; CI green; scripts and templates proven on a fresh VM; benchmark in docs/28
2CTO, founderA-steps 16 to 32; a test alarm reached the phone; D11 decided and written in the server's settings (KNOWN_ABUSE_PROVIDER)
3CTO, founderA-steps 33 to 39 pass their checks
4founderStaff accounts, DNS, first week watched; before the first real school

C3. Alarms (all within the 10 free) and their runbooks

AlarmThreshold to startRunbook
Site downRoute 53 health check on /health/ready fails 3 times (90 s)site-down.md
Errors5xx > 1% of requests for 5 minerrors.md
Moderation stalledOldest pending review > 5 minmoderation-stalled.md
Bedrock failingError rate > 5% or p95 > 10 s for 5 minai-check-failing.md
ServerCPU > 85% for 15 min, or memory > 90%, or disk > 80%, or status check failedserver.md
DatabaseCPU > 80% for 15 min, or free storage < 20%, or connections > 80% of maxdatabase.md
Busy503 "busy" > 2% of requests for 5 minbusy.md
BackupsAutomated backup or AWS Backup job failedbackups.md
EmailSES bounce > 5% or complaint > 0.1%email-reputation.md
CostBudgets at $80 and $95, raised to $120 and $140 before 1,000 students (D10); anomalycost.md
Security (GuardDuty, D12; an EventBridge rule, not one of the 10 alarms)Any medium or high findingsecurity.md

C4. Settings that change from docs/27 §11

Settingdocs/27 valueThis plan
COOKIE_DOMAIN.thnkrr.comunset (host-only __Host- cookies)
API_PREFIX(new)/api
EDGE_SHARED_SECRETset on CloudFront for /in/*, /school/*set for all three API behaviours
LOG_FILE(new)/var/log/thnkrr/api.log
BACKGROUND_WORK(new)on; deploy.sh starts a new version with off until it takes over (B9)
The server's name for CloudFrontapi.thnkrr.comorigin.thnkrr.com, certificate by DNS check (B17)
The §5 retention numbers(new)one setting each, defaults as §5 (B11)
Secrets/etc/thnkrr/api.env onlysame file, filled from Parameter Store /thnkrr/prod/* by server-setup.sh; copy in the password manager
Everything elseas docs/27same

C5. Parked, with the measurement that would justify each

PieceMonthlySwitch it on when
Bigger database (db.t4g.small / medium)+$12 / +$35The pilot-size benchmark or load test misses its marks
Load balancer + a second serverabout $45Server CPU regularly above 70% at peak (§7, stage 3). The monthly window doesn't need it: the server swap (§6) already avoids the outage
Live standby database (Multi-AZ)+$12 to +$47About 300 students or the first paid school (§7, stage 2). Shrinks database updates from a few minutes to about one
Small video server of its ownabout $12Videos wait more than 15 minutes in school hours, or the site slows while they convert. The switch is built (PROCESS_ROLE)
Staging server$5 to $10, switched off when unusedThe first paid school, or a second engineer
Containers on Fargate + infrastructure as codeabout +$80 and a few daysA second environment or second server exists
WAF managed rules$8D6: the week real students arrive, or the first attack pattern in the logs
Security Hub, Inspectorabout $5 to $8A school or insurer asks for a security attestation
Secrets Manager$2More than one server needs the same secrets
Valkey cachefrom $6A second app process, or a measured hot spot
Amazon Transcribe (+ toxicity)$14 per 1,000 videosReviewer time on video passes about an hour a day, or a spoken violation is missed
Automatic frame check (Rekognition)$90 to $108 per 1,000 videosSame trigger; the "our frames" shape is cheaper at volume
OpenSearch$350 to $735Profiles in the millions, or relevance needs Postgres cannot meet
Monthly table partitioningengineering timeA table passes about 1 million rows
Lambda, SQS, EventBridgepenniesAn event-driven need appears
X-Ray tracing$5 per million tracesMore than one service in the request path

●  Have your own?

// Publish your own markdown.

Write your own