The Architectural Evolution of a Campus E-Voting System

|Wijatama Diwangkara

Tags: System Architecture, Data Logic, Scalability, Infrastructure, Post-Mortem

The MVP: Engineering Database Logic in a Spreadsheet (2019)

Before writing a single line of backend code, an IT system usually starts as a Minimum Viable Product (MVP) to solve an immediate business need. In 2019, my faculty needed a way to conduct student union elections digitally, but we had absolutely zero budget.

My solution was highly manual but functionally robust. I designed a unique, single-use token system using Google Forms to collect the data. To validate the votes, I essentially turned a spreadsheet (pemilu.xlsx) into a relational database and validation engine.

In the master sheet, I mapped every generated TOKEN and built a logic flow to audit the incoming form submissions. The core mechanism relied on a Terhitung sebanyak (Counted as) column. Because Google Forms couldn't prevent a user from submitting twice, the spreadsheet had to handle the data integrity.

  • If a student voted, the spreadsheet cross-referenced their token. The very first chronological entry tied to a valid token was successfully mapped to the Voted for column and flagged as Suara Sah (Valid Vote).
  • If a student tried to cheat the system and use the same token again for a different candidate, the logic caught the duplicate usage.
  • Any duplicate entries, or any random/unrecognized token strings inputted by users, were automatically filtered out and categorized as Suara Tidak Sah (Invalid Vote).

It was a manual, administrative headache to distribute the tokens, but the logic held up perfectly. I had essentially built primary key constraints and data validation using spreadsheet formulas.

Iteration 1: The Flask Monolith (2020)

By 2020, it was time to automate. I replaced the pemilu.xlsx spreadsheet system with a fully functional monolithic web application (vote-app) built using Flask and SQL.

This system automated the token validation and securely stored the voting data. We deployed it for the faculty-level election, which consisted of fewer than 500 students spanning four academic years. Because the user base was small and traffic was highly predictable, the monolithic architecture was more than capable. The system ran flawlessly, and I thought I had "solved" digital voting.

Iteration 2: Decoupled Architecture and The University Challenge (2021)

Success brings new problems. In 2021, the university-level student union approached me to adapt the system for the entire campus. Instead of hundreds of voters, we were now looking at thousands. Furthermore, they came with a very short notice.

Realizing the scale of the project, I teamed up with a colleague to upgrade the architecture. We transitioned from a monolith to a decoupled system, separating the backend API (vote-app-v2) from the frontend interface (fe-voting-apps). From a pure software engineering perspective, the code was cleaner, more modern, and ready to scale.

However, code does not run in a vacuum.

Anticipating the massive spike in concurrent users, I submitted a request to the university for dedicated server resources. The request was denied. Left with no budget and no official infrastructure, I had to deploy the entire decoupled architecture onto free-tier servers (Heroku).

The Bottleneck: Surviving a D-Day Crash

When election day arrived, the inevitable happened. As thousands of students flooded the system to cast their votes simultaneously, we slammed directly into the free server's bandwidth and transaction rate limits.

The application choked. The database connections timed out, the API endpoints dropped requests, and the system essentially bottlenecked under the load. Fortunately, because I was skeptical of running enterprise-level traffic on free servers, I had explicitly warned the university committee during the planning phase to prepare a manual backup plan. When the digital system went south, they were able to pivot to the fallback method.

The Post-Mortem Takeaway

This project remains one of the most formative experiences of my career. It taught me a brutal but necessary lesson: Software architecture is useless without the infrastructure to support it.

You can decouple your frontend and backend, write clean API endpoints, and design brilliant database schemas, but if your server cannot handle the concurrent network requests, your product will fail. Today, as an IT Consultant, this experience directly influences how I design enterprise solutions. I never just look at the application layer; I look at the resource allocation, the load testing parameters, and the worst-case fallback scenarios. Sometimes, the best way to learn how to build scalable systems is to watch one crash.

You can view the evolution of the codebases on my GitHub: