How it was built · architecture

An election dashboard ready for millions of people

One collector, static files on Cloudflare's edge and a standby VPS. None of our servers sit in the visitor's path.

Banner: ready for millions, how the election dashboard was built
In short

This page explains how the eleicoes.inema.club dashboard was made. It showed the 2026 2nd-round count live, using official TSE data. A single collector reads the TSE and writes ready-made files; those files sit on Cloudflare servers spread around the world; each person's browser only reads those files. So the number of visitors changes nothing about the load on the TSE or on our machine. It is for anyone who wants to understand, copy or teach this way of building a site that handles traffic peaks at low cost.

The idea

Three parts that only talk through files

The collection talks to the TSE and writes files. The contract defines the format of those files. The site only reads the files and draws the screen. One part can go down or move to another machine without touching the others — which is what happened when the whole operation moved to the VPS.

Single collector, immutable files, Cloudflare edge, low cost, standby VPS and one-command switch
TSE→ 1 collector (every 15 s, with ETag)→ Checks the sums→ Versioned files + manifest→ Cloudflare edge→ Each person's browser
Timeline

From the first commit to the live dashboard: about 37 hours

Taken from the repository history (git log), with a night's sleep in the middle. Everything was done in Claude Code sessions; each fixed failure became a line in FALHAS.md.

Oct 24 04:19
1st commitCollector, contract and dashboard tested with real 1st-round data.
Oct 24 05:50
MunicipalitiesAll 5,571 cities on the map, in a system separate from the dashboard.
Oct 25 early hours
Projection, audit and standbyProjection calibrated on 224 scenarios (2022 data and simulations), Source and audit section, standby on the VPS and domain switching by script.
Oct 25 17:00
TSE opens the release of resultsThe collectors start on their own via timers. During the count, 10 commits go in: fixes and new menus.
Oct 26
After the count"The comeback" page, the "Ask your questions" chat and the whole operation moving to the VPS.
Scale

Why it handles millions without bringing a server down

The secret is having none of our servers in the visitor's path.

1

The edge serves the requests

The files sit on Cloudflare servers spread around the world. Our machine only sends files when something changes. If it goes down, the site keeps showing the last result.

2

The TSE sees a single client

A thousand or a million visitors: the collector makes the same request every 15 s. If nothing changed, the TSE answers "not modified" and nothing is transferred.

3

A file that never changes is cached

Each version has its own name (v100340.json) and is never altered. The browser downloads it once and keeps it for a year.

4

Only a small file is polled

The latest.json manifest is 4.9 KB and says which version is current. The large file is only downloaded when it changes.

5

A static file runs no code

A file request is served directly, without triggering any program. According to Cloudflare's documentation, these requests are neither billed nor limited.

6

Manifest last

The collector writes the version files before the manifest, and the upload to Cloudflare takes everything together at once. Nobody sees a manifest pointing to a file that has not arrived yet.

The math ESTIMATE

Each person with the dashboard open requests the manifest every 15 seconds. It was not tested with 1 million real people: this is what the edge needs to deliver.

People at the same timeRequests per second at the edgeTrafficRequests to the TSELoad on our machine
10 thousand~670~3 MB/s1 every 15 snone
100 thousand~6,700~33 MB/s1 every 15 snone
1 million~67,000~330 MB/s1 every 15 snone

Where the real limits are

Visitor counter

It is a single instance on Cloudflare. With millions of simultaneous sessions, it becomes a bottleneck. If it fails, only the number disappears from the menu; the dashboard keeps working. Fix: split it into several instances and add them up.

"Ask your questions" chat

Each question calls the Anthropic API. That's why there is a cap: 25 questions per hour and 80 per day per visitor, 1,500 per day on the site.

The source

If the TSE is late or sends a file that doesn't add up, that state stays frozen at the last valid value. We can't be faster than the source.

Publishing

Each change becomes an upload to Cloudflare taking 18 to 26 seconds (measured in the publisher log). Added to the 15 s collection interval, the site stays about half a minute behind the TSE (estimate).

Costs

The cost does not grow with the number of visitors

For the dashboard itself, more people looking doesn't raise the bill. Only the chat and the counter have a per-use cost.

ItemCostType
Collector, analyses and publisherOne small VPS (Hetzner CX23: 2 processors, 4 GB). Price in the range of a few euros per month.ESTIMATE
Site and data (files on the edge)No per-request charge on Cloudflare static files.FACT
Counter and chat (program on Cloudflare)Within the free allowance at low volume; billed by volume above it, according to the account's plan.ESTIMATE
Chat (Anthropic API, Claude Opus 5.5)About US$ 0.04 per question, measured in the first conversations.FACT
TSE dataPublic and free, no key.FACT
Backup

A standby VPS and a one-command switch

On count night, a second machine ran everything for real, ready to take over in minutes.

Its own collection

The VPS had its own collectors, started at 5 pm, writing versions from 500001. That way they never collided with the files already published by the main machine (which start at 100001).

Always-on copy

The VPS served both sites at eleicoes2026.inema.club and municipios2026.inema.club, with the same cache rules. The standby could be tested at any time.

Switch by script or by hand

One command sent the domains to the VPS and another brought them back. Without the main machine, a manual explains the same switch through the Cloudflare dashboard: ferramentas/vps/TROCA-MANUAL.md (in Portuguese). The backup is installed with ferramentas/vps/instalar.sh vps.

# on election night: send the traffic to the VPS (without --executar it only shows what it would do)
ferramentas/vps/trocar_dominios.sh vps --executar
# switch back to Cloudflare
ferramentas/vps/trocar_dominios.sh volta --executar
# today (since Oct 26) the VPS is the primary; reinstall the entire operation:
ssh root@<VPS-IP> 'cd /opt/eleicoes2026 && git pull && bash ferramentas/vps/operacao.sh --executar'

On Oct 26 the final data was copied to the VPS, the analyses ran there with identical results (checked by the sha256 fingerprint) and the main machine was shut down. The site never went offline.

Techniques

What made it efficient

Nothing exotic: a handful of simple decisions, applied with discipline.

  1. Contract first. The file format was written before the code; collection and site moved in parallel.
  2. Separate who collects from who displays. The site never talks to the TSE; the collection knows nothing about the screen.
  3. Immutable file + small manifest. Eternal cache on what doesn't change, cheap polling on what does.
  4. Ask the TSE "did it change?" (ETag). Download only the state that changed.
  5. Check before publishing. A sum that doesn't add up, a vote count that decreases, a time that goes backwards: that state isn't published and the last valid value stays.
  6. Keep the original with a fingerprint (sha256). The Conferência (Check) page redoes the sums and checks the integrity of each downloaded file.
  7. Atomic writes. Write to a temporary file and swap in one step; nobody reads a half-written file.
  8. Publish only on change. The publisher compares a signature of the data; restarting duplicates nothing.
  9. Services with limits and schedules. Automatic restart, memory limit, a timer to start at 5 pm and shut the simulations down at 4 pm, even if the machine reboots.
  10. Rehearse the night. Accelerated simulation with fictional names and a "fake TSE" with deliberate failures.
  11. Test the model on old data. The Projection was tested on 2022 data and on simulations: across 224 scenarios, the range contained the final result 98.7% of the time. This is measured on the same sample that helped set the range, so it is not a guarantee.
  12. Hot standby. The VPS ran for real all night, with a different series of versions.
  13. One-line failure log. Example from that night: the TSE index listed Brazil with overseas time (16 hours in the future) and the total wouldn't publish; the fix was to ignore times in the future.
Read more

Everything open in the repository

The full document, with the technical details and file names, is in ARQUITETURA.md.