My Experience as a Systems Engineer Intern at GovTech
From managing zip file repositories to patching old BACnet building protocols and untangling custom code generation, here is what my Systems Engineer internship at GovTech taught me about managing technical debt, handover context, and building trust in the workplace.
Summary
- From zip files to proper git: Why protecting codebases by handing interns zip files hurts velocity, and why rollbacks and code reviews work much better.
- Bridging old protocols to new systems: Spending three sprints connecting a 30-year-old BACnet building system to MQTT, patching unmaintained Java code, and checking software licenses.
- Moving away from code generation: Shifting from a tool that stripped and recreated custom code per deployment toward standard reusable containers with config files.
- Leaving behind a memory layer: Setting up documentation, specifications, and AI memory workflows so the next engineer can easily understand why decisions were made.
- Engineering is mostly human: What managing soldiers in National Service taught me about giving people a 10% benefit of the doubt and building trust at work.
Introduction
When I first applied for the role of Systems Engineer Intern for the Open Digital Platform (ODP) at GovTech, I had never heard of the title "systems engineer" before. I just assumed it meant doing cloud and infrastructure.
During the interview, the interviewer asked me a question that caught me off guard: "What database would you use, MongoDB or Postgres?"
There was no background or scenario given. Without knowing how the application worked, what the data looked like, or what kind of workload it had to handle, the question felt completely out of left field. I froze, fumbled the answer, and just said: "I only use Postgres for my projects."

Looking back, if the question had more context, like whether we were storing unstructured social media feeds or processing strict financial transactions, I could have explained the technical trade-offs much better. But when someone asks a very generic question, the best move is not to guess. What I should have done was pause, ask clarifying questions, and understand the use case first before recommending any tool.

Despite that clumsy start, I still got the offer. That brought me into the team building the Open Digital Platform, which acts as the digital brain connecting IoT sensors, lifts, air-conditioning, and facilities for places like the Punggol Digital District.
Looking back, the experience taught me a lot about legacy protocols, tech debt, and how teams function when things get stressful.
The Zip File Workflow and Building Trust
When I first started, the team was quite protective of the codebase. Interns in the past had broken things before, so instead of getting access to the main Git repository, we were handed a zip folder. We had to create our own separate repository under our personal namespace, write code there, and then pass it back to be merged upstream.
It was understandable that the team wanted to protect production, but working out of a zip file slowed everything down.

Isolating engineers with manual barriers usually causes more headaches than it prevents. If you want safety, it is much better to build an environment where mistakes are cheap to fix using quick rollbacks, automated checks, and standard branch protections.

Eventually, we spoke with the team and convinced them to give us normal repository access. From there, we put standard engineering habits in place: working on feature branches and requiring a code review from another engineer before anything touched the main branch.
Translating BACnet to MQTT
A big chunk of my day-to-day work was building adapters for our middleware. This middleware translates messages between old building automation systems and modern cloud networks.
For about a month and a half, across three bi-weekly sprints, my main task was building an adapter to convert the BACnet protocol into MQTT.

BACnet is an old industry protocol. It is used everywhere in physical facilities for air conditioning, lighting, and power meters, but the software libraries for it are not actively maintained.
Because our backend was built mainly in Java, we ran into several practical problems:
- Missing Maven packages: The Java library we needed was not even hosted on standard Maven repositories. I had to pull down the original open-source project, fix bugs in the source code directly, and build and publish the package to our internal repository.
- Software license checks: In business and government projects, you cannot just grab any random open-source library. I had to learn the difference between permissive licenses (like MIT and Apache 2.0) and copyleft licenses (like GPL). Picking the wrong license can create legal obligations to release your own code to the public.
- Sprint planning and asking for help: At first, I tried to figure out task breakdowns and sprint estimates entirely on my own instead of checking in with senior engineers. A senior engineer noticed and walked me through how earlier adapters were built. That saved me a lot of wasted time and taught me not to stay silent when I hit an ambiguous problem.
Moving Away From Auto-Generated Code
While working on the middleware, I noticed an interesting architectural setup.
Originally, the team used an auto-generative tool. Whenever a new deployment was needed, this tool would look at a configuration file and generate a custom code package. It would actively strip out any code segments that were not being used by that specific deployment. The original purpose was to hide the underlying internal logic so external users could not see or copy the whole codebase.
Over time, business needs shifted. The team decided to allow users to view the source code. But the old architecture remained: every deployment was still getting custom-generated code instead of running a single, standard codebase.

Generating custom code for every site created unnecessary maintenance debt across a distributed network. It is much easier to maintain one clean container image and simply mount the configuration and environment files at runtime.
As an intern, I felt hesitant to push for this change during architecture meetings because I was worried about causing friction. But I brought it up gently as a discussion point. Toward the end of my internship, another intern with a longer tenure shared that the team decided to adopt this modular approach. Even if a good idea takes time to settle, sharing it respectfully is always worth doing.
Making Handovers Useful in the Age of AI
As my internship came to an end, I had to prepare my project handover.
Throughout my work, I had kept local design notes, task specifications, and documentation on how certain features and bugs were resolved. Usually, interns just clean up their laptops, delete their working notes, and leave a basic summary document that nobody reads again.
Around that time, GovTech was testing an internal tool called Munnin, which acted as a shared memory layer for AI coding tools. Our division leaders were also looking into engineering skills and workflows to keep code compliant with quality standards.

I realised that saving structured notes and decision history was valuable context. Instead of letting that knowledge disappear, sharing that documentation helps the next person understand why something was built a certain way, rather than just what the code does.
Sunrise Projects, Sunset Systems
During an all-hands meeting, our division director spoke very candidly about career growth and software lifecycles. He pointed out an uncomfortable truth about developer motivations: most engineers want to be recognised as pioneers building brand-new sunrise projects. Very few people want to spend their time maintaining older sunset systems.

In the sunrise stage of a project, you have complete creative freedom. You can build fast proofs of concept without strict rules holding you back. But when those fast experiments reach maturity, all the shortcuts taken early on turn into heavy technical debt for the engineers who have to maintain the system later.
Maintaining software takes serious patience and discipline. It made me realise that good engineering is not just about building new features fast; it is about building clean systems that are straightforward for someone else to keep running.
People
During my time there, GovTech also went through organisational restructuring and layoffs. The mood in the office changed noticeably. Floor access rules tightened, and even casual things like the pantry table tennis table were folded up and locked away.
That period reminded me of what I learned while serving as a Platoon Commander during National Service. When people are under stress, work environments can easily turn tense.
Here are the reminders I try to keep with me:
- Give people a 10% buffer: If someone seems blunt, irritable, or slow to reply, do not assume they have bad intentions. People have bad days, difficult workloads, and family worries outside of work.
- Speak up with care: If you see an issue or feel uncomfortable with a technical choice, do not bottle it up. Frame your feedback around how it helps the team rather than pointing fingers.
- You are more than your job: Your value as a person does not come from your sprint points or output. Make time to care about the people around you, whether that means chatting about table tennis, rock climbing, or hobbies outside of work.
Conclusion
My time at GovTech gave me a realistic look at how large public infrastructure projects actually work. Systems engineering is not just about writing clean code or picking modern frameworks. It is about understanding legacy systems, knowing when to refactor old tools, and building clear context for the team that comes after you. Most of all, it is about staying kind, reliable, and patient with the people working alongside you.

