My first internship @ OMERS (2022)

August 30th, 2023

From May 2022 until August 2022, I interned at OMERS as a Frontend Engineer on the myOMERS term. Although I was title 'frontend,' I took on a fullstack role as I mainly worked on the services that powered the application, while doing some frontend work towards the end of my internship. My team was in charge of maintaining the myOMERS member application, which involved building new features as per product requirements or fixing bugs.

The Product

Here's a quick overview of the product. myOMERS is a web application that serves as a self-serve for members to quickly execute actions on their pension. This could involve viewing their accounts, calculating their retirement fund, adding additional contributions, and more.

Prod Squad

One of the most memorable parts of this internship was my tenure on the Prod Squad. For context, during my time at OMERS, a big chunk of each sprint was spent fixing bugs. The team realized that we spent so much time fixing bugs that it was hard to find time to work on feature tickets. This lead to the creation of the Prod Squad - a duo (dev + qa) that worked together to fix production bugs for an entire sprint. Each sprint, the members of the duo were switched. I was a part of the inaugural prod squad, and I was able to fix bugs that improved the member registration flow for over 40,000 members.

HashiCorp

One of the biggest challenges I faced during my internship was the migration of application secrets from GKE to Hashicorp Cloud. I was tasked with ingesting application secrets from a HashiCorp cloud service instead of the standard Kubernetes engine environment. I had to implement this migration for three features (frontend, middle service layer, backend). The migration for the frontend was quite simple since Next.js provides a method where secrets are defined, so the ingestion of secrets happened there. It was much tricker for the other two services. I faced an issue with Node.js hoisting and circular imports. The following snippets will help describe the problem.

For example, imagine the entry point to the server looked something like this.

// server.ts
import config from 'dotenv'
import logger from './logger'

config({
    // pull environment variables from hashicorp and set them here.
})

import someOtherModule from './moduleThatUsesSecrets'

// rest of server initialization

Due to hoisting, all the imports will be 'hoisted' to the top and will be executed before the config({... }) runs and ingests the secrets. Hence, the import from ./moduleThatUsesSecrets will execute first and the secrets inside that module will be undefined.

How do we fix this? We can put the ingestion logic into its own file, and import that file into the entry point before the secrets are used anywhere else to ensure that there are no undefined secrets when the modules are imported.

// config.ts
import config from 'dotenv'
config({
    // pull environment variables from hashicorp and set them here.
})
// server.ts
import './config.ts'
...

This way, the secrets will always be defined at runtime for any module that uses them.

Although this seemed like a simple fix, it was much harder to come to this solution when working with an enterprise codebase.