I've been working at XtendOps for a year and a half now and we've seen tremendous growth in that time frame. When I joined, the company was around 600 employees and now we're closing in on 2000. I was hired to help achieve this growth, and it's been a wild ride so far.
XtendOps is a Business Processes Outsourcing company aimed at disrupting that industry. We help companies like HelloFresh and J Crew provide excellent Customer Experience. Engineering at XtendOps helps support that goal, supporting both our People and Clients.
Our Tech Stack
Part of achieving that growth has been centered around our move to Svelte. We aim to make our Application process more accessible by using a framework that compiles away all of the extra pieces that frameworks with Virtual DOMs include.
Up to this point, we've depended on Meteor which I am still quite fond of. It comes with its own challenges though. Recently our builds have started slowing, we are perpetually looking for good documentation, and it feels sluggish running in Development compared with newer build systems like Vite.
Evolution of our Tech Stack
I still love Meteor. I've been using it for nearly 10 years.
It is particularly well suited to situations where you are doing more Product Development and the solution needs to be evolved. That's where we were for the ATS when I joined the company.
That's not the case anymore. The data model and processes for the ATS have molded into a shape that is well-suited for the company and we're preparing for exponential growth this year.
So is Meteor the way for us anymore? What is the cost of switching?
I knew a better way. Our team was already using SvelteKit for other projects like xtendops.com so we were faced with a dilemma.
Can we build our bigger applications in SvelteKit and take advantage of all of the benefits it has?
Feasibility check and my role in the process
Part of my role at XtendOps is kicking tires. I explore new technologies and ways of working before moving the teams to it to make sure it works for us and makes sense to do at that time.
I hypothesized that any technical performance gains, increases in accessibility on mobile devices, and simplifications in the Developer Experience would translate to an improved Business Experience. This is crucially important with the scaling our company is going through at the moment.
I set out to determine whether SvelteKit was a viable solution for our Applications system which is set to start receiving thousands of applications per month.
There were four key questions I needed to answer before I could suggest that we move to SvelteKit:
Can we reauthor Meteor Authentication in SvelteKit?
Can we build our most complicated Assessments?
Can we manage Flow Transitions?
How will we handle our Data Model?
Reauthoring Meteor Authentication
One of the great things about Meteor is its Accounts system. The base system is built in and it has several closely integrated packages you can use for passwordless, oAuth, and Roles authorization. It probably saved us a couple of weeks of work over the past year.
I wasn't prepared for implementing a completely new Authentication system at the same time as changing the platform we were using. That's too much change.
So how could we use our existing authentication system, but reimplement it in SvelteKit?
The great thing about Open Source is you can open the source. That's exactly what I did. I wrote custom handling for tokens and users in SvelteKit.
It seems there is some growth in this part of SvelteKit for managing Client-Server communication of tokens and users. Checkout:
Building our Voice Assessment
The next piece I needed to prove was our most complicated assessment: Voice
We are building an Application process similar to TopTal or Terminal.io, but directed at Customer Experience. At the scale we are hiring, we need to provide our Talent Acquisition teams with prioritized lists of candidates to interview.
The Voice Assessment is integral to this process and is used in our ML algorithms to determine a candidate's fit for a particular role.
To sum up, if this doesn't work then we stop right here.
We're using a combination of recording, NLP, and Google Cloud Services to emit a fit score for a candidate's voice for an Account.
The key question here is whether our current processes would work within SvelteKit Endpoints. Ideally, we would get back a score for the Voice Assessment after completing the assessment.
The good news is that I confirmed that this stood up to SvelteKit Endpoints. I didn't need to break the process out into a separate Serverful Application watching for new Voice assessments being added.
Managing Flow Transitions
Another core idea in our Applications system is the concept of Flows. The way to think about these is different Jobs or Offices have different requirements for the position.
Instead of having a fixed Flow of candidates go through, we can have different configurations based on the Job, Office, Client, or whatever we choose.
I was particularly concerned about the transition between Assessments and other components working in SvelteKit. Would we lose state between transitions or have a FOUC?
Luckily, SvelteKit supported several solutions for handling this. We're currently using a SPA-like router that's internal to the page running our Flows. We have plans to explore handling this in an SSR way in the future using redirects.
Handling our Data Model
The big elephant for us was handling the Data Model. First, you have to understand how Meteor handles data.
One of Meteor's unique selling points is the ease with which you can provide Pub/Sub infrastructure. Before working for XtendOps (and during COVID), my business partner David and I ran a bunch of virtual events. We needed the real-time functionality that Meteor provides to handle chats, one on ones, feed transitions, live donations, and more.
This functionality is provided over DDP in Meteor. We weren't planning to leave the current application running as a backend for the new process so how do we handle Backend?
Prisma saves the day
I had been following Prisma from the sidelines for the past five years from its GraphCool days. I'm continuously impressed with what that team puts out.
To make a long story short, they provide a CLI that now does Introspection on MongoDB. Introspection navigates through your database and works out most of your schema for you.
npx prisma db pull
The Prisma file output had 1200 lines 🤯 which I can tell you, I would not have written myself in one sitting.
So after generating the schema, did it work?
No. It didn't, but after a few hours and a few coffees, it did. 🎉
Did this solve everything?
No. Importantly we have a collection that is loosely typed and we could easily have spent a month organizing it into a uniform data model.
I counter that with this is the exact argument for MongoDB. The flexibility we gain by allowing this collection to grow as it needs to and enforce schema in the backend and frontend has been what let this Product evolve to where it is now.
We will strongly type it one day, but today is not the day. So how do we account for this with the Prisma?
Mongo Client saves the day. We have an escape hatch with Mongo Client that lets us not be dogmatic where it doesn't make sense.
In summary, our data management strategy is a combination of Prisma Client and Mongo Client. Prisma is our default case, providing a solid data structure, while Mongo allows us to handle unstructured data and evolve our product as needed. By using both technologies, we can achieve the perfect balance between structure and flexibility.
How we implemented SvelteKit in our tech stack
Having proven feasibility, the next step was to Shape this into work for my teams.
I work with a team of ten wonderful developers. They are the primary reason we have our SvelteKit application portal we have today.
The team was already fluent in Svelte as we were using a Serverful version of it. This wasn't a transition from React to Svelte. We did that over a year ago. They just needed to understand the core concepts of SvelteKit to get started.
The first part of this project was getting oriented. I did share resources before we started, but it was really up to them if they looked at them before the sprint.
At the particular time, we started this endeavor, SvelteKit had just gone 1.0 and many of the resources out there were slightly outdated. I ended up recording internal videos that I shared with the team walking them through the technical arguments for SvelteKit and how to do many of the things in the SvelteKit Documentation.
We split the project up into reasonably separate chunks. We had to recreate the entire backend, authentication, ten assessments, and our registration process.
The team was intimately familiar with how the current application process worked, and we were creating a near replica in a different platform so there weren't many questions about business logic. It was pretty much all technical implementation.
We integrated the various pieces as they became available. Our UI/UX team would go through the application process and call out any missing pieces. We had Playwright E2E testing in place, but we also depended heavily on User feedback.
The impact SvelteKit has had on our builds and experience
The move to SvelteKit was the right one. It is a joy to work with and has my team eyeing two other ServerFul Svelte applications for migration.
Our builds have gone from 30 minutes down to around 1 minute
Development startup times have also decreased by a factor of 20
Documentation seems easier to come by as the SvelteKit ecosystem is maturing
In other words, the Dev Experience has improved dramatically for my team. 🤩
So how long did it take to migrate?
What a win!
SvelteKit has also been lauded for its technical performance over other platforms. That does become a bit of a pissing contest sometimes, but it is safe to say we found notable performance benefits in switching to SvelteKit from Meteor.
Our migration was pretty much the same application reimagined in SvelteKit, so we could do a direct comparison between the two.
There were two key pages on the applications site at the time we released it. The Landing page and the Assessments page. We ran Lighthouse scores on both.
You can see notable improvements in Performance on both pages with a direct refactor into SvelteKit. As we know, these are just high-level views and I tend to lean more heavily on the components that make up these scores when making decisions.
These charts speak to two things.
We experienced huge improvements in performance metrics on devices which opens up our platform for use on older devices and in areas with reduced bandwidth.
We perhaps weren't utilizing everything we could have been using with Meteor, but the ease with which we get these performance boosts with SvelteKit cannot be denied.
Even if the Speed Index on the Assessments page pre Migration was an outlier, we have realized incredible performance benefits with the move to SvelteKit.
It's also important to note that this was our starting point with the move to SvelteKit. There are further Product and Development improvements we are currently working on to take this even further.
We have an "exact" clone of our Serverful application, so what?
We have better Developer Experience and Technical Performance.
How does this help the business?
It's dangerous to only focus on Dev Experience and Technical Performance
Though easy to explain the benefits of Dev Experience and Technical Performance to this audience, it's dangerous to only focus on these to the larger business.
Engineering Leaders need to connect this type of migration to business impacts to get buy-in from the larger business.
I aim to provide one of those data points.
It's difficult to connect performance improvements with a business impact in an evolving application. It needs to be the same business logic on both sides of the migration for you to be able to compare.
We had a tight window where each application was close enough to the other that comparison was relevant. Additionally, we couldn't compare the raw numbers of Applications as there were different advertising efforts before and after the change.
So we have the Assessment Completion Rate, one of our key KPIs. We use these Assessments in our Machine Learning models to help Talent Acquisition prioritize which candidates to reach out to first.
A 5% lift here has a real business impact for us and translates to more top-of-funnel candidates we can offer Interviews to. We can directly attribute this lift to the switch to SvelteKit.
It completely justifies the 2 weeks we spent migrating and has a payback period of about 4 weeks (which we've already hit).
Our experience with SvelteKit and its potential for other companies
Looking back at our migration, the only thing I would have changed was doing it sooner. It was on my radar to do a Spike of SvelteKit for our Applications Process for a few months as it started to near 1.0. The reason I didn't was more of a function of time and attention than anything else, but I probably would have been able to get some of that time back had we moved sooner.
Our migration from a Serverful application to SvelteKit was relatively smooth and we are planning to do this in a few more of our applications.
We have experienced:
an increase in a significant KPI for our business
an improved Developer Experience with Svelte and SvelteKit
a simpler CI/CD process
an increased velocity from a Project Management perspective
We aim to now realize these benefits in other parts of our platform increasing our users' experience and top of the funnel.
Want to do this?
Our process for migrating to SvelteKit was unique to our company and the time we chose to attempt it. Had we completed it a few months earlier, we would have had a slightly different experience, just as if we did it today we would.
Your experience will need to be tailored to your unique position. If you want to do this for your company, I strongly recommend you do a Spike and choose the hard things first.
Build your business use case
Prove out your most difficult parts
Plan for Authentication and Data Model
Feel free to reach out to me on LinkedIn or Twitter if you have questions.