Being a Software Developer at Ownr (RBCx)

First fulltime job at Ownr included working on a new email system, refer a friend and a handful of onboarding flow fixes. It was a fun experience being apart of a startup within the bank.

Alec Di Vito
Alec Di Vito 5 min read
Being a Software Developer at Ownr (RBCx)

Ownr is a website that helps you setup a business in Canada. It automates the creation process with pre-created legal documents and submits them to the government system automatically.

I joined in January 2022 as a Full-Stack JavaScript Developer. The stack was Node.js, TypeScript, React, Heroku, RabbitMQ, PostgreSQL, CircleCI, and Jest.

This was my first full-time role after completing school. I had done a handful of co-ops up to this point, with 2 being within RBC, however this was the first role I got to work on a larger project that severed thousands of customers.

Building an email platform

The largest project I worked on at Ownr was a new email platform.

Before I built this platform, emails were managed as a separate library. Emails were pug templates that were rendered at the time of sending an email in application code. If a change was required, it would always depend on a developer to make a change, deploy the library then update it's uses across many different projects. Getting email changes into production took upwards of a day.

To drive faster updates, we decided to move all of the emails onto a new microservice. The platform needed to support:

  1. Building and sending transactional emails
  2. Scheduling emails for later
  3. Creating recurring email campaigns
  4. Tracking delivery and analytics
  5. Giving marketing a UI so they could manage campaigns themselves

I led the project with two junior developers. I focused mainly on the backend email API while they worked on scheduling and the frontend used by the business.

The service was built with Node.js and TypeScript. RabbitMQ handled queued work, PostgreSQL stored the data and Jest was used for automated testing. We maintained around 90% test coverage throughout the project.

The end result was updates to emails taking seconds rather then 2+ peoples time and a day of waiting.

Scheduling campaigns

One of the more interesting parts was building the scheduling system.

We wanted the recurrence options to feel similar to Outlook. A user should be able to send something once, every day, every week or on a more complicated schedule without needing a developer to write a new cron job every time.

We built a shared scheduling library that could be used by both the frontend and backend. The backend used cron and queues to find scheduled campaigns and send the work through RabbitMQ. The frontend used it to show the example schedule that would be followed.

Selecting users was based on a SQL query that the data team would provide to marketing so that only the users that matched certain attributes would get the then scheduled email.

This gave marketing a way to create and manage campaigns without having to ask the development team for help.

Migrating off the old email system

Building the new service was only half of the job. We also had to migrate away from using the pug library we developed.

During my review, I found 75 email call sites across two codebases that needed to be updated to API calls now. Some of the emails were easy to reproduce locally and test. Others happened during very specific part of the business registration process though.

I spent about a week testing the production cutover and was able to manually trigger around 65 of the email paths. The last were difficult to trigger because I needed specific application state to get them to trigger in a normal way.

The result was after release, 3 of those difficult paths failed, because of unexpected null values. But quick fixes followed and emails were re-triggered and the day was saved. Not exactly a prefect launch but I was happy to have been able to support it and get the system working.

Improving tracing in the new email system

The result of this microservice deployment was that sending an email might be the result of a message being passed around 3 systems before it gets trigger. To help with debugging in the future, I updated all the systems to start sharing correlation ID's.

The result was a small win which allowed us to see how a request was shared between our application server, job system and email server so we could trace back why an email was sent for a particular case.

Disagree and committing

During the early planning process of reasoning about the end system, I fought hard to have the first version of the email system to have a drag and drop editor for designing emails. The reason for this was because all of our emails were made up of blocks already and having a drag and drop system would be easier for non technical users.

However, after repeated attempts, the idea never caught hold for a version 1 implementation and instead we went with just updating the pug templates directly.

It was still a success but adoption was more difficult as there was now a bit of a learning curve because of the need to learn pug.


The email system was the only system I worked on at ownr that had a big impact on day to day operations. My other work was smaller in scope. Some was other feature work, exploratory and fixes to issues that arised.

Heroku review apps stopped working

Ownr used Heroku review apps to create temporary environments for pull requests. One day, the GitHub integration was disabled during a security incident and we suddenly could not create them.

Our team heavily depended on Heroku review apps, sometimes to an extream degree to where we would max out our 100 review app limit!

Waiting for the integration to return wasn't a great plan, so I wrote an approximately 200-line Bash script that recreated the important parts of the workflow. The script would:

  1. Copy an existing Heroku application
  2. Push the pull request's Git repository
  3. Run the required database migrations
  4. Leave us with a working review environment

We used the script to create roughly 20 review apps, and I estimated that it saved around 20 hours of engineering time.

Was it the cleanest tool I've ever written? No.

Did it unblock the team while the normal path was unavailable? Yes, and that was the point.

Testing Ownr on Kubernetes

I had been interested in Kubernetes ever since my previous co-op working on RBC cloud team. Because of my frustration with Heroku, I thought it would be cool to do a POC of running Ownr on Kubernetes which I did using Kind.

I documented the setup and presented it to the team as a proof of concept.

Ownr did not move to Kubernetes while I was there, so I won't pretend that I migrated the company. The project was a PoC. However, it gave the team a working example and gave me practical Kubernetes experience that became very useful in my next role.

Hiring and mentoring

After about six months, I started participating in hiring. I reviewed resumes and projects, joined interviews and helped hire three engineers.

I also onboarded and mentored co-op students while we worked on the refer-a-friend feature. This was my first real experience helping newer developers work through a production codebase.

Final thoughts

I left Ownr in April 2023 to return to RBC as a Staff Cloud Engineer.

The biggest lesson I took from Ownr was that ownership is incredibly important and you want to make sure that everyone on the project feels like they own it. It was my first taste of working in a startup and was a lot of fun!