Build1 distinct publisher3 min readUpdated
A Space Invaders build on AWS accepts kill events instead of scores and recomputes the total in a pure function. ECS Express Mode absorbs the ALB, certificate and DNS that choice drags along.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
A Space Invaders build on AWS accepts kill events instead of scores and recomputes the total in a pure function. ECS Express Mode absorbs the ALB, certificate and DNS that choice drags along.
Follow any of these and your For You feed starts watching them — no settings page required.
A developer publishing as roxsross put a Space Invaders clone on AWS and reported that the hard part was not the game but the leaderboard: a ranking that trusts the score the client sends fills up with cheats almost immediately [1]. The interesting part is where the fix lives, which is in the request schema rather than in the client binary.
The failure mode is familiar. The browser posts `{ nickname, score: 999999 }`, the server stores it, and everything works until someone with devtools open notices [2]. According to the post, the naive answer is to encrypt the score on the client; the better one is to stop trusting the client's score at all and have it send raw events while the server does the addition, which the author frames as a decision rather than a feature [3].
So the client sends an array of kill events shaped `{ type, level, t }` [4], and the server recomputes the total from an official points table: small=30, medium=20, large=10, ufo=150 [5]. The validator, `validateScoreSubmission` in `src/scores.mjs`, is a pure module with no I/O that runs eight rules in strict order, first failure wins [6]. The early ones are shape and hygiene: `malformed_request`, `missing_fields`, `invalid_nickname`, then `score_mismatch`, which compares the declared score against the recomputed one and rejects with an `expected` value [7]. The middle ones are budgets rather than heuristics: a run cannot be shorter than 8 seconds, cannot contain more than 55 kills in a level, and cannot sustain more than 10 kills per second [8].
Those numbers set a hard ceiling. At 55 kills per level and 150 points for the best target, a level is worth at most 8,250 points, so the classic `score: 999999` would require more than 121 levels of flawless UFO hunting to survive recomputation [9]. When validation passes, the function returns the recomputed score and a server-side `playedAt` as authoritative, and the `POST /api/scores` handler persists those, never `req.body.score` [10]. The only module that touches AWS, `src/db.mjs`, also mints `scoreId` and `playedAt` itself and never accepts the client's, and it maps SDK failures into typed errors that the HTTP layer turns into 503 [11]. Fastify's schema runs first for shape, the semantic rules second, persistence last, and `additionalProperties` is left true on purpose: a client can post a bogus `scoreId` and the server simply discards it [12].
The deployment side is the same argument applied to infrastructure. A game service on classic ECS means VPC, subnets, security groups, ALB, target groups, listeners, an ACM certificate, auto-scaling and IAM policies, all of which can be written wrong in twenty ways [13]. Here the whole Terraform stack is five resources: an ECR repository, a DynamoDB table and three IAM roles [14], with ALB, certificate, target group and DNS provisioned by AWS [15]. The author says Express Mode saved writing about thirty Terraform resources [16], which puts the hand-written share at roughly one seventh of the total [17].
Two things to watch. The rules described in the post validate arithmetic and rates, but none of them binds the submitted events to a session the server observed, so the residual attack is a patient client posting a plausible event array under the caps [18]. And the caps are game-design constants: change level pacing or spawn counts and 55 kills or 8 seconds stops describing legitimate play. On the infrastructure side, the same trade reappears when you need to touch a listener rule or a certificate that AWS now owns [15].
Ranked by verification strength, evidence, and original report placement.
The author, publishing as roxsross on dev.to, left a Space Invaders game running on AWS and says the hardest part was not the game but that a leaderboard whose server trusts the client-sent score fills with cheaters in five minutes; the result was a backend that receives kill events instead of scores plus an 8-rule anti-cheat that recomputes the score server-side.
The inevitable bug of a global leaderboard: the client sends { nickname, score: 999999 } and the server stores it; it works until someone with devtools open notices.
The naive solution is to send the score encrypted from the client; the better defence is not to trust the client score at all, having the client send raw events and the server do the summing, which the author calls a decision rather than a feature.
The client does not send the final score; it sends an array of kill events shaped { type, level, t }.
The server recomputes the score using an official KILL_POINTS table (small=30, medium=20, large=10, ufo=150), the single source of truth for recomputation.
src/scores.mjs holds a pure module with no I/O implementing the anti-cheat; validateScoreSubmission validates eight rules in strict order and the first failure wins.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Specific and code-backed, but entirely self-reported from one source
The post supplies an unusually concrete artifact trail: the full validateScoreSubmission body, named rejection reasons, numeric thresholds, the KILL_POINTS table, the render() metrics function, module boundaries and an exact Terraform resource count. That is well above typical tutorial vagueness. Against that, every claim rests on one author's account with no repository verification, no test or attack results, no independent reproduction, and the supplied body is truncated mid-deployment section, leaving the eighth anti-cheat rule unnamed.
One self-reported hobby deployment
Adoption evidence is a single personal Space Invaders service on AWS plus its CI pipeline using the ECS Express Mode deploy action. There are no users, no traffic figures, no third-party deployments, no reported values for the si_requests_total or si_cheats_rejected_total counters, and no indication the pattern is in use beyond this author's project.
Modestly overstated: closes arithmetic forgery, framed as closing cheating
The engineering is sound and the framing is mostly restrained ('a decision, not a feature'). The overshoot is in absolutes: 'no hay discusión posible' and limits described as physical rather than heuristic imply the cheat problem is settled, when the described pipeline only guarantees that a declared score matches a submitted event array that stays under generous per-level and per-second caps. Nothing shown binds those events to a game the server watched, so a scripted client remains viable. The '999,999 needs 121 levels' ceiling is real deterrence, not proof. Separately, the thirty-avoided-resources figure that anchors the infrastructure story is an unaudited author estimate, and no adoption or effectiveness data backs either half.
Personal build-log promotion of own project and a new AWS primitive
This is an individual developer's portfolio-style post on dev.to showcasing their own game and infrastructure choices, with a favourable framing of a recent AWS managed feature and its official GitHub Action. That creates a mild pull toward reporting the wins (five resources, thirty saved, cheaters defeated) and not the costs or residual weaknesses. No sponsorship, vendor affiliation or paid relationship is disclosed or implied in the supplied material, and the technical content is checkable rather than gated, so the distortion pressure is moderate rather than high.
Confident on the described design, weak on effectiveness and generality
What the code and inventory establish is reliable: the module boundaries, rule ordering, server-authoritative persistence and the five-resource Terraform stack can be read straight off the excerpt. Confidence drops sharply on anything requiring corroboration or outcomes, because there is one publisher, one hobby deployment, no measured cheat-rejection results, an unnamed eighth rule and a truncated body.
build
Force the tool call, then hand Lightsail a long-lived key1 distinct publisher
build
CSA's 2026 threat list is a flat line, so ask which threats a config snapshot can prove1 distinct publisher
build
A cleanup commit deleted the sanitizer. Five days later a scanner cashed it in.1 distinct publisher
build
A Stripe SDK Major Bump Turned One Metadata Lookup Into a Silent Non-Delivery1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 20, 2026