Hallo! Ik ben Joseph, een student informatica aan de Universiteit van Waterloo, en ik heb onlangs een stage Software Engineering bij Slash afgerond, die liep van september tot december 2025. Om dit blog kort samen te vatten: ik heb een geweldige tijd gehad en ik vind dat je ook mee moet doen. Bedankt voor het lezen.
Oké, nu echt. Ik heb eerder stage gelopen bij verschillende bedrijven, van kleine muziekgerelateerde start-ups tot grote techbedrijven, maar Slash bood een unieke combinatie van intensiteit en verantwoordelijkheid die ik nergens anders had gevonden. Het team was slim en hecht, en ik heb veel diepgaande kennis opgedaan over complexe onderwerpen, van het onderhoud van Kubernetes tot DB-prestaties. Maar nog belangrijker was dat ik een aantal heel interessante uitdagingen mocht oplossen, en daarom heb ik besloten om een blog te schrijven over mijn ervaringen!
Om kort samen te vatten wat Slash doet: ze zijn begonnen als een financieel platform voor mensen zoals ondernemers en sneakerverkopers, maar zijn nu een algemeen fintech-bedrijf dat bedrijfskaarten, internationale overschrijvingen, crypto-accounts en meer aanbiedt. Toen ik Slash voor het eerst tegenkwam, wist ik hier nog niet veel van. Ik ben immers geen sneakerhead en ik was ook niet erg thuis in fintech, dus ik heb lang nagedacht of deze kans het wel waard was. Maar zoals je aan deze blogpost kunt zien, was mijn keuze om mee te doen uiteindelijk een van de beste beslissingen die ik in het begin van mijn carrière had kunnen nemen.
De belangrijkste redenen waarom ik uiteindelijk voor Slash heb gekozen in plaats van voor de andere bedrijven, waren:
- Het was een serie B-bedrijf. – Ik heb nog nooit bij een start-up van deze omvang gewerkt en wilde die omgeving graag eens ervaren.
- Ze hadden een jaaromzet van 150 miljoen, wat ongelooflijk hoog is voor een bedrijf in serie B. – ze overleven niet alleen of houden zich niet alleen staande; ze waren actief aan het opschalen. Als extra bonus betekende dat dat ze waarschijnlijk over goede DX en technische nauwkeurigheid beschikten, iets wat veel kleine startups ontberen.
- Ze groeiden actief. – Ze hebben hun omzet in één jaar tijd verzesvoudigd en onlangs hun serie B-financiering opgehaald. Dit bedrijf bevond zich in een gouden tijdperk van groei en ik wilde graag werken bij een bedrijf dat zo'n momentum doormaakte.
- Het is een jong, energiek team. – Uit mijn sollicitatiegesprekken bleek dat de mensen hier relaxed waren en dat het prettig was om met ze te praten. Ik vond het spannend om samen te werken met collega's waarmee ik me kon identificeren.
- Het is een klein en slank bedrijf. – Had ik al gezegd dat deze 150 miljoen ARR door een team van ongeveer 12 ingenieurs is gerealiseerd? Dat is 12,5 miljoen ARR. per ingenieur, wat echt te gek is. Het is duidelijk dat de mensen bij Slash toptalent zijn, en ik zou zowel een groot aandeel in het bedrijf hebben als geweldige begeleiding krijgen.
- De vergoeding en extraatjes voor kleine bedrijven zijn top voor stages... 🤫
TLDRIk dacht dat de omgeving, de getalenteerde mensen en de startup-energie een geweldige plek zouden zijn om te groeien. Ik dacht dat ik de kans zou krijgen om een project van begin tot eind te leiden, van het opzetten van de infrastructuur tot het plannen van schaalbaarheid en het bedenken van het systeemontwerp en nog veel meer, dus ik heb de kans gegrepen!
Project: Meldingen V2
Hier is iets bijzonders dat ik meteen heb geleerd over Slash: ze wijzen belangrijke projecten toe aan stagiaires en vertrouwen erop dat ze die tot een goed einde brengen. In mijn tweede week kreeg ik de opdracht om onze meldingen over geweigerde kaarttransacties te vernieuwen. Dat lijkt niet zo moeilijk, toch? Het bestaande meldingssysteem had echter een paar problemen:
- Nauwe koppeling met ons interne eventsysteem, met bedrijfslogica ingebouwd in de kern van de dienst.
- Slechte e-mailstatistieken en nog slechtere e-mailbezorgbaarheid vanwege de provider die we gebruikten
- Moeilijke ontwikkelaarservaring, waardoor ingenieurs het systeem volledig omzeilden en rechtstreeks de API's van providers aanriepen.
En zo kwam de verraderlijke taak – om betere afwijzingsmails te maken, hadden we meer nodig dan een patch. We hadden een volledig opnieuw ontworpen meldingssysteem nodig, en ik werd de DRI voor het ontwerp, de ontwikkeling, de uitrol en de schaalbaarheid van het hele project. Dat was super intimiderend... maar ook een ongelooflijke kans om iets te ontwerpen dat uiteindelijk miljoenen meldingen zou verwerken. Ik had er zin in om ermee aan de slag te gaan.
Door het vorige meldingssysteem te bestuderen en met ingenieurs te overleggen, heb ik een aantal principes ontdekt waaraan dit nieuwe systeem moet voldoen:
- Een evenementonafhankelijk ontwerp – de service moet overal kunnen werken, zowel in eenmalige scripts als in gebeurtenishandlers
- Een leveranciersonafhankelijk ontwerp – De mogelijkheid om met minimale inspanning eenvoudig nieuwe providers te verwijderen en toe te voegen zou van onschatbare waarde zijn.
- Een ontwerp waarbij de ontwikkelaar centraal staat – geen overheersing meer door frustratie. De ontwikkelervaring moet zo intuïtief en eenvoudig mogelijk zijn.
- Waarneembaar en schaalbaar - De meldingen moeten gedurende hun volledige levenscyclus kunnen worden gevolgd en uiteindelijk moeten we 3 miljoen e-mails per maand kunnen ondersteunen!
En zo ontstond het handler-gebaseerde ontwerp van Notifications V2. Het systeem is gecentreerd rond notificatiehandlers, die algemene handlerfuncties blootstellen, zoals het verzenden van notificaties of het verwerken van webhooks, voor specifieke externe providers van kanalen (bijvoorbeeld Resend voor e-mails, Twilio voor sms'jes).

De kern van het systeem wordt gevormd door de NotificationIntent, een generiek tijdelijk object dat wordt gebruikt om alle gegevens voor een melding te vervoeren, zoals provider-, kanaal- en payload-argumenten. Elke handler definieert de vorm van zijn eigen intenties, en deze objecten zijn sterk getypeerd en ondersteunen dus statische typecontroles en introspectie. Dit betekent dat ontwikkelaars niet alle fijne kneepjes van elke provider hoeven te kennen – ze kunnen profiteren van de automatische aanvulfunctie van de IDE en erop vertrouwen dat de typecontrole hen door het proces loodst.
Om ervoor te zorgen dat bedrijfslogica, zoals het controleren van gebruikersvoorkeuren, op een laaggekoppelde manier werd geïmplementeerd, gaan de intenties, zodra een ontwikkelaar een verzendfunctie aanroept, door een Notificatie-middleware pipeline eerst. Notificatie-middlewares zijn hogere-orde functies die een voorbewerkingsstap hebben om gedeelde DB-lookups mogelijk te maken, en een procesfunctie waarmee we notificatie-intents kunnen toestaan, transformeren of verwijderen. Met dit ontwerp kunnen we nu verschillende verzendfuncties definiëren die één onderliggend systeem gebruiken om validatielogica te definiëren en te delen. Bijvoorbeeld:
- We kunnen een basisfunctie 'melding verzenden' definiëren die intenties door een
Ontvanger verbannenmiddleware, die intenties verwijdert als de ontvangersinformatie (e-mail, telefoonnummer) op een aangepaste banlijst staat - We kunnen een complexere functie 'naar gebruiker verzenden' definiëren die intents door dezelfde
Ontvanger verbannenmiddleware en eenRespecteer gebruikersvoorkeurenmiddleware, die intenties verwijdert als de gebruiker zich heeft afgemeld voor meldingen op dat kanaal
Als bijkomend voordeel is het voor toekomstige ontwikkelaars eenvoudig om nieuwe verzendfuncties toe te voegen, te verwijderen of te wijzigen zonder een wirwar van functies te hoeven doorzoeken.

Na de middleware-stap maakt de service Kennisgeving levenscyclusobjecten voordat een Temporal-workflow wordt gestart. Temporal is geweldig omdat het ons ingebouwde herhalingspogingen biedt voor workflowfouten, duurzame status en orkestratiegaranties. Deze zijn allemaal belangrijk om de leverbaarheid van de meldingen te garanderen. De workflow zet de meldingen in de wachtrij, beperkt het aantal verzendingen om de limieten van de provider te respecteren en zodat we gebruikers niet spammen, en geeft vervolgens batches door aan de providers. De providers nemen vervolgens de verantwoordelijkheid op zich om de melding naar de provider te verzenden en de service werkt de levenscyclus dienovereenkomstig bij.
Zodra een externe provider ons een webhook-respons stuurt, zetten de handlers deze om in een gestandaardiseerd gegevenstype en geven ze getypeerde acties af. Acties bieden ons een gestructureerde en typeveilige manier om op gebeurtenissen te reageren wanneer we een melding ontvangen, terwijl de service zo neutraal mogelijk blijft. Bijvoorbeeld:
- We hebben een actie voor het bijwerken van ontvangers – Op deze manier kunnen beheerders ontvangers bijwerken als "permanent verbannen" of niet, afhankelijk van wat de provider en het kanaal als "verbannen" beschouwen.
- We hebben een actie voor het opnieuw verzenden van een melding. Als een e-mail bijvoorbeeld tijdelijk wordt geweigerd, willen we de e-mail exponentieel opnieuw verzenden. Als de handler vaststelt dat de e-mailprovider de e-mail heeft geweigerd, kan deze actie worden geactiveerd.
Pfff! Dat is het grootste deel van het proces. Onderweg kwam ik nog een aantal andere interessante technische uitdagingen tegen, zoals
- Ondersteuning van exponentiële herhalingen – We plannen toekomstige herhalingsopdrachten in Temporal, afhankelijk van het aantal reeds uitgevoerde herhalingen.
- Goede traceerbaarheid – We slaan bijvoorbeeld trace-id's op, evenals meldingen en hun herhalingspogingen, in een
NotificationSetentiteit - Batching – Door zowel individuele als batchverzending te integreren, kunnen we voorkomen dat de limieten van providers worden overschreden en krijgen ontwikkelaars controle over hoe ze meldingen willen versturen.
Ik laat toekomstige nieuwe ingenieurs de details in de code zelf ontdekken zodra ze bij ons komen werken 😉
Project: Facelift
Project Facelift was het complete herontwerp van de Slash-webervaring door ons team (zie de eng blog hier door Albert Tian, de vader van de facelift). Ik zal niet te diep ingaan op wat Facelift precies was (zie opnieuw de geweldige eng blog), maar in essentie ging het om de introductie van een nieuwe componentbibliotheek + Tailwind in onze hele omvangrijke frontend. Ter voorbereiding op de lancering besloot het engineeringteam om er een leuke hackweek van te maken! Dit was echter geen typische hackweek op kantoor – we stapten in een paar auto's, reden drie uur naar een hut aan Bass Lake naast Yosemite en brachten de week door met bouwen, refactoren en oprecht plezier maken met elkaar.


Deze week ben ik volledig overgestapt van backend-werk naar het helpen vernieuwen van de transacties en geschillenprocessen. Dit was voornamelijk frontend-werk, wat een verfrissende afwisseling was ten opzichte van mijn vorige werk. Het betekende ook dat ik aan een groot deel van onze frontend-ontwerpinfrastructuur heb kunnen werken, zoals:
- Kernprimitieven: bijvoorbeeld hoe we onze zijpanelen, modals en pop-ups genereren
- Herbruikbare samenstelbare componentenbijvoorbeeld,
Selecteerbare zoekfunctie - Tabelbeheerder: onze aangepaste component om tabellen te maken met eenvoudige sorteer-, filter-, paginering- en zoekfuncties
- Robuuste validatie van subformulieren: met behulp van Arktype, Tanstack-formulieren en ons eigen modelgeneratiesysteem
Bij de facelift ging het niet zozeer om complexe productlogica, maar meer om te zien hoe snel ons team kan werken als het gefocust is en zich richt op één gezamenlijk project. Het was absoluut een hoogtepunt van mijn stage om te zien hoe de hele site in een week tijd transformeerde, terwijl ik samen met mijn collega's in die hut aan het bouwen was en een band met hen opbouwde. Het faceliftwerk was die week echter nog niet afgerond. De weken daarna hebben we ervoor gezorgd dat de lancering soepel verliep door samen met de supportafdeling de laatste puntjes op de i te zetten!

Project: Sjablonen
Aan het einde van elke werkperiode stuurt mijn universiteit graag een klein formulier met een eenvoudige vraag: "In hoeverre was je studie relevant voor je werk?". Nou, tijdens mijn tijd bij Slash heb ik een aantal concepten die ik in de les heb geleerd daadwerkelijk direct kunnen toepassen! We wilden namelijk dat onze transactionele e-mails zouden aansluiten bij ons nieuwe Facelift-ontwerp, dus was het logisch dat ons meldingssysteem aangepaste sjablonen zou ondersteunen. Om ervoor te zorgen dat we dezelfde kleuren en spaties gebruikten als onze frontend, hebben we deze sjablonen uiteindelijk in code gebouwd met React Email, een sjabloonbibliotheek voor e-mails waarmee we JSX voor deze sjablonen konden gebruiken. Dit was perfect voor ons; aangezien ons team zeer vertrouwd is met React JSX, konden we de consistentie van ons merk waarborgen door hetzelfde Tailwind CSS v4-ontwerpsysteem te gebruiken voor zowel web als e-mail.
Er was echter één addertje onder het gras: een van de belangrijkste voordelen van TailwindCSS 4 is de mogelijkheid om aangepaste CSS-bestanden te gebruiken in plaats van het traditionele JS-configuratieobject, waar ons team gebruik van heeft gemaakt. De Tailwind-component van React Email is echter eigenlijk vereist het JS-configuratieobject.
Dit betekende dat ik een transpiler moest bouwen!
Om het nauwkeuriger te beschrijven: tijdens de bouwfase heb ik een script toegevoegd om een Abstract Syntax Tree (AST) te bouwen op basis van de CSS-bestanden van het ontwerpsysteem. Deze AST zorgde voor een gestructureerde weergave van de CSS-regels, waardoor ik het bestand gemakkelijk kon parseren om:
- Filter niet-ondersteunde CSS-klassen eruit: bijvoorbeeld, hover-stijlen en pointer-hulpprogramma's werken niet in de meeste e-mailclients.
- Converteer naar een compatibel kleursysteemWe hebben OKLCH gebruikt om onze kleuren te definiëren, maar e-mailclients kunnen dat niet weergeven, dus worden deze geconverteerd naar HEX.
- Bouw het TS-configuratieobjectDit wordt gecompileerd naar JS en kan vervolgens eenvoudig overal in de codebase worden geïmporteerd.
Deze transpilatiestap was een snelle manier om één enkele bron van waarheid voor ons ontwerpsysteem te implementeren. Als een kleur werd aangepast, zou deze consistent zijn in al onze media – web of e-mail – omdat deze onmiddellijk zou worden getranspileerd zodra deze opnieuw werd opgebouwd. Bovendien konden andere clients, zoals onze mobiele applicatie, dit getranspileerde object naar behoefte gebruiken. Met het gegenereerde configuratieobject kon ik een set gemeenschappelijke React-componenten voor onze e-mails bouwen die onze webcomponenten weerspiegelden, zoals Typografie en Knop componenten, met vrijwel identieke props. Dit alles heeft bijgedragen aan een betere ontwikkelaarservaring, waardoor het maken van sjablonen minder vervelend is geworden!
Tot slot heb ik ook meldingssjablonen gemaakt die gebruikmaken van ons interne registratiekader, een aangepaste gegevensstructuur die we zelf hebben ontwikkeld (zie deze blogpost). Kort samengevat bieden registers ons een typeveilige manier om sjablonen te definiëren, deze te serialiseren en deserialiseren vanuit de database, en de bedrijfslogica bij elkaar te houden. Bijvoorbeeld, de kaart-autorisatie.meldingssjabloon.tsx staat direct naast de code voor de gebeurtenisverwerker voor kaartautorisatie, wat handig is om snel te zien welke gebeurtenissen meldingen hebben! Het was geweldig om registers in dit project te kunnen gebruiken – het illustreerde echt de toewijding van het team om goede, herbruikbare code te schrijven.
Wat heb ik ervan geleerd?
Ik kwam hier met het idee dat dit een unieke ervaring zou worden, en ik ben blij dat ik heb besloten om mee te doen – Slash heeft me meer geleerd over eigendom, platformontwerp en engineering velocity dan welke functie ik ook eerder heb gehad. Enkele belangrijke lessen die ik heb geleerd zijn:
- Vertrouwen is van onschatbare waarde – Slash heeft geen dagelijkse stand-ups. Slash heeft geen wekelijkse sprints of backlog grooming. We hebben één vergadering per week, en dat is alleen om dingen die we hebben gebouwd aan het hele team te demonstreren. Dit werkt omdat het team over het algemeen sterk communiceert en indrukwekkende verantwoordelijkheidsvaardigheden heeft. Dat wil niet zeggen dat er geen mentorschap is – ik heb wekelijkse één-op-één-gesprekken om mezelf te deblokkeren – maar in plaats daarvan vertrouwt Slash erop dat je je best doet en cultiveert het een omgeving waarin je je zoveel mogelijk kunt concentreren.
- Het team is ongelooflijk. – Bij mijn andere coöperaties waren mijn collega's professioneel, maar hier waren mijn collega's mijn volkHet is duidelijk dat Slash een geweldige bedrijfscultuur heeft met leuke, behulpzame en prettige collega's – er was niemand met wie ik niet graag samenwerkte of door wie ik me geïntimideerd voelde, en ze behandelen je net als een fulltime medewerker. Bovendien kun je in het weekend met ze gaan basketballen 😃
- Als stagiair zul je hier exponentieel groeien in vergelijking met waar dan ook. – Bij elk ander bedrijf zou de stagiair niet het volledige kernmeldingssysteem als project hebben gekregen. De moeilijke, groeibevorderende problemen zouden zijn opgelost of worden opgelost door een senior engineer. Wat Slash uniek maakt, is de combinatie van kleine teams, echte bedrijfskritische problemen en een cultuur waarin zelfs stagiairs belangrijke taken toevertrouwd krijgen.
Hier zijn nog enkele andere leuke herinneringen aan deze stage:
- We hebben in één week tijd samen zo'n 20 pond steak gegeten... bedankt, hackweek!
- Ik versloeg mijn collega-stagiair in een poolwedstrijd en werd vervolgens meteen vernederd door een fulltimer.
- Ik heb eindelijk één plaat kunnen bankdrukken!
- Ik draag in belangrijke mate bij aan de 'slijmerigheid op kantoor' (en mogelijk gerelateerd daaraan: ik ben dol op Shake Shack).

Deze vier maanden zijn sneller voorbijgegaan dan ik had verwacht, en ik ben dankbaar voor de ervaring die ik bij Slash heb opgedaan. Ik studeer binnenkort af, en wat het leven mij ook te bieden heeft over een maand, een jaar of tien jaar, ik weet dat mijn stage bij Slash mij de kennis en het zelfvertrouwen heeft gegeven om te slagen, waar ik ook terechtkom.
Als je geïnteresseerd bent om verder te praten, Neem gerust contact met mij op via LinkedIn! Graag beantwoord ik al uw vragen.