Xin chào! Tôi là Joseph, sinh viên ngành Khoa học Máy tính tại Đại học Waterloo, và tôi vừa kết thúc kỳ thực tập Kỹ sư Phần mềm tại Slash từ tháng 9 đến tháng 12 năm 2025. Nói ngắn gọn về blog này – tôi đã có một khoảng thời gian tuyệt vời và nghĩ rằng bạn nên tham gia. Cảm ơn bạn đã đọc.
Được rồi, lần này là thật đấy. Trước đây, tôi đã từng thực tập tại nhiều công ty khác nhau, từ những startup nhỏ liên quan đến âm nhạc cho đến các công ty công nghệ lớn, nhưng Slash mang đến một sự kết hợp độc đáo giữa sự căng thẳng và trách nhiệm mà tôi chưa từng tìm thấy ở nơi khác. Đội ngũ làm việc thông minh và gắn kết, và tôi đã học được rất nhiều kiến thức chuyên sâu về các chủ đề phức tạp như duy trì Kubernetes hay tối ưu hóa hiệu suất cơ sở dữ liệu. Quan trọng hơn, có những thách thức thực sự thú vị mà tôi được giải quyết, đó là lý do tôi quyết định viết một bài blog về trải nghiệm của mình!
Để tóm tắt nhanh về những gì Slash làm, ban đầu họ là một nền tảng tài chính dành cho những người như doanh nhân và người bán lại giày thể thao, nhưng hiện nay đã trở thành một công ty fintech ngân hàng tổng hợp cung cấp thẻ tín dụng doanh nghiệp, chuyển khoản quốc tế, tài khoản tiền điện tử và nhiều dịch vụ khác. Ban đầu, tôi không biết nhiều về điều này khi lần đầu tiên tiếp xúc với Slash. Dù sao, tôi không phải là người đam mê giày thể thao, cũng không am hiểu sâu về fintech, nên tôi đã dành nhiều thời gian để suy nghĩ xem cơ hội này có đáng để theo đuổi hay không. Tuy nhiên, như bạn có thể thấy qua bài viết này, quyết định gia nhập Slash của tôi đã trở thành một trong những quyết định tốt nhất mà tôi có thể đưa ra cho sự nghiệp ban đầu của mình.
Những lý do chính khiến tôi cuối cùng đã chọn Slash thay vì các công ty khác là vì:
- Đó là một công ty thuộc vòng gọi vốn Series B. – Tôi chưa bao giờ làm việc tại một startup có quy mô như vậy và muốn trải nghiệm môi trường đó.
- Họ đạt doanh thu hàng năm là 150 triệu USD, con số này vô cùng cao đối với một công ty ở vòng gọi vốn Series B. – Họ không chỉ đơn thuần là tồn tại hay cố gắng duy trì; họ đang tích cực mở rộng quy mô. Thêm vào đó, điều đó có nghĩa là họ có thể có chất lượng sản phẩm (DX) và quy trình kỹ thuật nghiêm ngặt mà nhiều startup nhỏ thiếu.
- Họ đang phát triển mạnh mẽ. – Họ đã tăng doanh thu gấp 6 lần trong một năm và gần đây đã huy động thành công vòng gọi vốn Series B. Công ty này đang ở giai đoạn phát triển bùng nổ, và tôi muốn làm việc tại một công ty đang trải qua đà tăng trưởng mạnh mẽ như vậy.
- Đó là một đội ngũ trẻ trung, tràn đầy năng lượng. – Qua các cuộc phỏng vấn của mình, tôi nhận thấy mọi người ở đây rất thoải mái và dễ chịu khi trò chuyện. Tôi rất hào hứng được hợp tác với những đồng nghiệp mà tôi có thể đồng cảm và chia sẻ.
- Đó là một công ty nhỏ gọn và hiệu quả. – Tôi đã đề cập rằng doanh thu định kỳ hàng năm (ARR) 150 triệu USD này được thực hiện bởi một đội ngũ khoảng 12 kỹ sư chưa? Đó là 12,5 triệu USD ARR. theo Kỹ sư, điều này thật đáng kinh ngạc. Rõ ràng, đội ngũ tại Slash là những nhân tài hàng đầu, và tôi sẽ có cả sự tham gia sâu sắc và sự hướng dẫn tuyệt vời.
- Chế độ đãi ngộ và các ưu đãi dành cho công ty nhỏ là hàng đầu cho các chương trình thực tập… 🤫
Tóm tắtTôi nghĩ rằng môi trường, những con người tài năng và năng lượng khởi nghiệp sẽ tạo nên một nơi tuyệt vời để phát triển. Tôi tin rằng mình sẽ có cơ hội được tham gia vào một dự án từ đầu đến cuối, từ việc xây dựng hạ tầng, lập kế hoạch cho khả năng mở rộng, đến thiết kế hệ thống và nhiều khía cạnh khác, và vì vậy tôi đã quyết định nắm bắt cơ hội này!
Dự án: Thông báo Phiên bản 2
Đây là một điều đặc biệt mà tôi đã nhanh chóng học được về Slash – họ giao các dự án quan trọng cho thực tập sinh và tin tưởng rằng họ có thể hoàn thành chúng. Trong tuần thứ hai của tôi, tôi được giao nhiệm vụ cải tiến hệ thống thông báo từ chối giao dịch thẻ của chúng tôi. Không có vẻ gì là khó khăn, phải không? Tuy nhiên, hệ thống thông báo hiện tại có một số vấn đề:
- Kết nối chặt chẽ với hệ thống sự kiện nội bộ của chúng tôi, với logic kinh doanh được tích hợp sẵn vào lõi của dịch vụ.
- Chỉ số email kém và khả năng giao hàng email thậm chí còn tệ hơn do nhà cung cấp mà chúng tôi đã sử dụng.
- Trải nghiệm phát triển khó khăn, khiến các kỹ sư phải bỏ qua hệ thống hoàn toàn và gọi trực tiếp các API của nhà cung cấp.
Và thế là nhiệm vụ đầy thách thức bắt đầu – để tạo ra những email thông báo về sự suy giảm tốt hơn, chúng tôi cần hơn cả một bản vá. Chúng tôi cần một hệ thống thông báo được thiết kế lại hoàn toàn, và tôi trở thành người chịu trách nhiệm chính (DRI) cho thiết kế, phát triển, triển khai và mở rộng quy mô cho toàn bộ dự án. Điều đó thực sự đáng sợ… nhưng cũng là một cơ hội tuyệt vời để kiến trúc một hệ thống có thể xử lý hàng triệu thông báo trong tương lai. Tôi rất hào hứng để bắt tay vào công việc.
Sau khi nghiên cứu hệ thống thông báo trước đây và thảo luận với các kỹ sư, tôi đã xác định được một số nguyên tắc mà hệ thống mới này cần tuân thủ:
- Thiết kế không phụ thuộc vào sự kiện – Dịch vụ nên có khả năng hoạt động ở bất kỳ đâu, dù là trong các skript một lần hay các trình xử lý sự kiện.
- Thiết kế không phụ thuộc vào nhà cung cấp – Khả năng dễ dàng loại bỏ và thêm các nhà cung cấp mới với nỗ lực tối thiểu sẽ là vô giá.
- Thiết kế ưu tiên nhà phát triển – Không còn việc phải can thiệp do bực bội. Trải nghiệm phát triển nên được thiết kế sao cho trực quan và dễ dàng nhất có thể.
- Có thể quan sát được và có khả năng mở rộng - Các thông báo nên có khả năng theo dõi toàn bộ vòng đời, và chúng ta nên có thể hỗ trợ 3 triệu email mỗi tháng!
Từ đó, thiết kế dựa trên trình xử lý (handler-based design) của Notifications V2 ra đời. Hệ thống này tập trung vào các trình xử lý thông báo (notification handlers), cung cấp các chức năng xử lý chung như gửi thông báo hoặc xử lý webhooks cho các nhà cung cấp kênh bên ngoài cụ thể (ví dụ: Resend cho email, Twilio cho SMS).

Tại trung tâm của hệ thống là Thông báo ý định, một đối tượng tạm thời chung được sử dụng để chứa tất cả dữ liệu cho một thông báo, bao gồm các tham số như nhà cung cấp, kênh và dữ liệu tải. Mỗi trình xử lý định nghĩa cấu trúc của các intent riêng của mình, và các đối tượng này được định kiểu mạnh mẽ, do đó hỗ trợ kiểm tra kiểu tĩnh và kiểm tra nội bộ. Điều này có nghĩa là các nhà phát triển không cần phải nắm rõ tất cả các chi tiết phức tạp của từng nhà cung cấp – họ có thể tận dụng tính năng tự động hoàn thành của IDE và tin tưởng rằng kiểm tra kiểu sẽ đảm bảo tính chính xác.
Để đảm bảo rằng logic kinh doanh, như kiểm tra sở thích của người dùng, được triển khai theo cách ít phụ thuộc, khi một nhà phát triển gọi hàm send, các intent sẽ được truyền qua một Trung gian thông báo Đường ống trước tiên. Các trung gian thông báo là các hàm cấp cao có bước tiền xử lý để cho phép tra cứu cơ sở dữ liệu chung, và một hàm xử lý cho phép chúng ta cho phép, chuyển đổi hoặc loại bỏ ý định thông báo. Với thiết kế này, chúng ta có thể định nghĩa các hàm gửi khác nhau sử dụng một hệ thống cơ sở để định nghĩa và chia sẻ logic xác thực. Ví dụ:
- Chúng ta có thể định nghĩa một chức năng cơ bản "gửi thông báo" cho phép các intent đi qua một
Người nhận bị cấmPhần mềm trung gian (middleware) sẽ loại bỏ các yêu cầu (intents) nếu thông tin người nhận (email, số điện thoại) có trong danh sách chặn tùy chỉnh. - Chúng ta có thể định nghĩa một chức năng "gửi cho người dùng" phức tạp hơn, trong đó các intent được truyền qua cùng một luồng.
Người nhận bị cấmphần mềm trung gian cũng như mộtTôn trọng sở thích của người dùngPhần mềm trung gian (middleware) sẽ loại bỏ các intent nếu người dùng đã tắt thông báo trên kênh đó.
Ngoài ra, điều này còn mang lại lợi ích là các nhà phát triển tương lai có thể dễ dàng thêm, xóa hoặc chỉnh sửa các chức năng gửi mới mà không cần phải theo dõi một mạng lưới phức tạp của các chức năng.

Sau bước trung gian, dịch vụ tạo ra Thông báo Các đối tượng vòng đời trước khi bắt đầu một luồng làm việc Temporal. Temporal rất tuyệt vời vì nó cung cấp các tính năng tự động thử lại khi workflow thất bại, trạng thái bền vững và đảm bảo điều phối. Những tính năng này đều quan trọng để đảm bảo khả năng giao hàng của các thông báo. Workflow xếp hàng các thông báo, giới hạn tốc độ gửi để tuân thủ giới hạn tốc độ của nhà cung cấp và tránh làm phiền người dùng, sau đó chuyển các lô thông báo đến các trình xử lý của nhà cung cấp. Các trình xử lý này chịu trách nhiệm gửi thông báo đến nhà cung cấp và dịch vụ cập nhật vòng đời tương ứng.
Khi bất kỳ nhà cung cấp bên ngoài nào gửi cho chúng ta phản hồi webhook, các trình xử lý sẽ chuyển đổi chúng thành một loại dữ liệu chuẩn hóa và phát ra các hành động có kiểu. Các hành động cung cấp cho chúng ta một cách thức có cấu trúc và an toàn về kiểu để phản hồi các sự kiện khi nhận được thông báo, đồng thời giữ cho dịch vụ càng trung lập càng tốt. Ví dụ:
- Chúng tôi có một tính năng cho phép cập nhật danh sách người nhận – Nhờ đó, các quản trị viên có thể cập nhật trạng thái của người nhận thành "bị cấm vĩnh viễn" hoặc không, tùy thuộc vào quyết định của nhà cung cấp và kênh về việc ai bị coi là "bị cấm".
- Chúng tôi có một hành động để thử lại thông báo – ví dụ: nếu email bị trả lại tạm thời, chúng tôi muốn thử lại email theo cấp số nhân. Nếu trình xử lý xác định rằng phản hồi từ nhà cung cấp email là “bounced”, nó có thể kích hoạt hành động này.
Phew! Đó là phần lớn quy trình. Trên đường đi, tôi đã gặp phải một số thách thức kỹ thuật thú vị khác, như...
- Hỗ trợ thử lại theo cấp số nhân – Chúng tôi lên lịch các tác vụ thử lại trong tương lai bên trong Temporal dựa trên số lần thử lại đã thực hiện.
- Khả năng truy vết tốt – Ví dụ: Chúng tôi lưu trữ các ID truy vết, cũng như các thông báo và các lần thử lại của chúng, trong một
Bộ thông báothực thể - Gửi theo lô – Kết hợp cả gửi từng cái một và gửi theo lô cho phép chúng ta tránh vượt quá giới hạn tỷ lệ của nhà cung cấp và cung cấp cho nhà phát triển quyền kiểm soát cách họ muốn gửi thông báo.
Tôi sẽ để các kỹ sư mới tiềm năng tự khám phá chi tiết trong mã nguồn sau khi họ gia nhập 😉
Dự án: Nâng cấp giao diện
Dự án Facelift là quá trình thiết kế lại toàn diện trải nghiệm người dùng trên trang web Slash của đội ngũ chúng tôi (xem blog kỹ thuật). Bởi Albert Tian, cha đẻ của phẫu thuật nâng cơ mặt.). Bây giờ tôi sẽ không đi sâu vào chi tiết về Facelift là gì (lại một lần nữa, hãy xem bài viết tuyệt vời trên blog kỹ thuật), nhưng về cơ bản, nó là việc giới thiệu một thư viện thành phần mới + Tailwind cho toàn bộ hệ thống frontend khổng lồ của chúng tôi. Để chuẩn bị cho việc ra mắt, đội ngũ kỹ thuật đã quyết định có một chút vui vẻ và tổ chức một tuần hackweek tập trung! Tuy nhiên, đây không phải là một hackweek thông thường tại văn phòng – chúng tôi đã lên xe, lái ba giờ đến một căn nhà gỗ bên hồ Bass Lake gần Yosemite, và dành cả tuần để xây dựng, tái cấu trúc và thực sự tận hưởng thời gian bên nhau.


Trong tuần này, tôi đã chuyển hoàn toàn từ công việc backend sang hỗ trợ cải thiện quy trình giao dịch và giải quyết tranh chấp. Đây chủ yếu là công việc frontend, mang lại một sự thay đổi nhịp độ mới mẻ so với công việc trước đây của tôi, đồng thời cũng cho phép tôi làm việc trên hầu hết cơ sở hạ tầng thiết kế frontend của chúng tôi, bao gồm:
- Các nguyên thủy cơ bảnVí dụ: Cách chúng tôi tạo các thanh bên, cửa sổ modal và cửa sổ popup.
- Các thành phần có thể tái sử dụng và có thể ghép nốiVí dụ:
Tìm kiếm có thể chọn - Quản lý bảng: thành phần tùy chỉnh của chúng tôi để tạo bảng với các tính năng sắp xếp, lọc, phân trang và tìm kiếm dễ dàng.
- Xác thực biểu mẫu con mạnh mẽSử dụng Arktype, biểu mẫu Tanstack và hệ thống tạo mô hình của riêng chúng tôi.
Công việc nâng cấp giao diện (Facelifting) không chỉ đơn thuần là về logic sản phẩm phức tạp, mà còn là cơ hội để chứng kiến tốc độ làm việc của đội ngũ khi tập trung và đồng lòng hướng tới một dự án chung. Việc chứng kiến toàn bộ trang web thay đổi trong suốt tuần, đồng thời xây dựng mối quan hệ và gắn kết với đồng nghiệp trong cabin đó, chắc chắn là điểm nhấn đáng nhớ trong kỳ thực tập của tôi. Tuy nhiên, công việc nâng cấp giao diện không kết thúc vào tuần đó – trong vài tuần tiếp theo, chúng tôi đã hợp tác với bộ phận hỗ trợ để đảm bảo việc ra mắt diễn ra suôn sẻ bằng cách khắc phục các lỗi nhỏ xung quanh sản phẩm!

Dự án: Mẫu
Cuối mỗi kỳ học, trường đại học của tôi thường gửi một biểu mẫu nhỏ với câu hỏi đơn giản: “Mức độ áp dụng của bài giảng vào công việc của bạn như thế nào?”. Trong thời gian làm việc tại Slash, tôi thực sự đã áp dụng một số khái niệm học được trong lớp vào công việc! Cụ thể, chúng tôi muốn các email giao dịch của mình phù hợp với thiết kế Facelift mới, vì vậy việc hệ thống thông báo hỗ trợ các mẫu tùy chỉnh là điều hợp lý. Để đảm bảo sử dụng cùng màu sắc và khoảng cách như giao diện người dùng, chúng tôi đã xây dựng các mẫu này bằng mã nguồn sử dụng React Email, một thư viện mẫu email cho phép sử dụng JSX cho các mẫu này. Điều này hoàn hảo cho chúng tôi; vì đội ngũ của chúng tôi rất quen thuộc với React JSX, chúng tôi có thể đảm bảo tính nhất quán về thương hiệu bằng cách sử dụng cùng hệ thống thiết kế Tailwind CSS v4 trên cả web và email.
Tuy nhiên, có một điểm cần lưu ý – một trong những tính năng nổi bật của TailwindCSS 4 là khả năng sử dụng các tệp CSS tùy chỉnh thay vì đối tượng cấu hình JS truyền thống, điều mà đội ngũ của chúng tôi đã tận dụng. Tuy nhiên, thành phần Tailwind của React Email thực tế... yêu cầu Đối tượng cấu hình JS.
Điều này có nghĩa là tôi đã có cơ hội xây dựng một trình biên dịch!
Để mô tả chi tiết hơn, trong quá trình xây dựng, tôi đã thêm một skript để tạo ra Cây Cú pháp Trừu tượng (AST) từ các tệp CSS của hệ thống thiết kế. AST này cung cấp một biểu diễn có cấu trúc của các quy tắc CSS, cho phép tôi dễ dàng phân tích tệp để:
- Loại bỏ các lớp CSS không được hỗ trợVí dụ: các hiệu ứng di chuột và công cụ chỉ báo không hoạt động trong hầu hết các trình duyệt email.
- Chuyển đổi sang hệ thống màu tương thíchChúng tôi đã sử dụng OKLCH để định nghĩa màu sắc của mình, nhưng các trình duyệt email không thể hiển thị định dạng đó, vì vậy chúng được chuyển đổi sang định dạng HEX.
- Tạo đối tượng cấu hình TSĐiều này được biên dịch thành JavaScript và sau đó có thể dễ dàng nhập vào bất kỳ đâu trong mã nguồn.
Bước chuyển đổi này là một cách nhanh chóng để triển khai một nguồn dữ liệu duy nhất cho hệ thống thiết kế của chúng tôi. Nếu một màu sắc được điều chỉnh, nó sẽ được đồng bộ hóa trên tất cả các nền tảng của chúng tôi – web hoặc email – vì nó sẽ được chuyển đổi ngay lập tức sau khi được xây dựng lại. Ngoài ra, các ứng dụng khác, như ứng dụng di động của chúng tôi, có thể sử dụng đối tượng đã được chuyển đổi này khi cần thiết. Với đối tượng cấu hình được tạo ra, tôi đã có thể xây dựng một bộ thành phần React chung cho email của chúng tôi, tương tự như các thành phần web của chúng tôi, như Thiết kế chữ và Nút Các thành phần, với các thuộc tính gần như giống hệt nhau. Tất cả điều này đã giúp cải thiện trải nghiệm của nhà phát triển, khiến việc tạo mẫu trở nên dễ dàng hơn!
Cuối cùng, tôi cũng đã thiết kế các mẫu thông báo để tận dụng khung đăng ký nội bộ của chúng tôi, một cấu trúc dữ liệu tùy chỉnh mà chúng tôi đã phát triển (xem Bài viết trên blog nàyTóm tắt nhanh, các registry cung cấp cho chúng ta một cách an toàn về kiểu dữ liệu để định nghĩa các mẫu, serialize và deserialize chúng từ cơ sở dữ liệu, đồng thời giữ cho logic kinh doanh được định nghĩa cùng nhau. Ví dụ, Mẫu thông báo xác thực thẻ.tsx Mã xử lý sự kiện xác thực thẻ nằm ngay bên cạnh mã xử lý sự kiện xác thực thẻ, điều này rất tiện lợi để nhanh chóng xem các sự kiện nào có thông báo! Thật tuyệt vời khi có thể sử dụng các registry trong dự án này – điều này thực sự thể hiện cam kết của đội ngũ trong việc viết mã tốt, có thể tái sử dụng.
Tôi đã học được điều gì?
Tôi đến đây với suy nghĩ đây sẽ là một trải nghiệm độc đáo, và tôi rất vui vì đã quyết định tham gia – Slash đã dạy tôi nhiều hơn về quyền sở hữu, thiết kế nền tảng và tốc độ phát triển kỹ thuật so với bất kỳ vị trí nào tôi từng đảm nhận trước đây. Một số bài học quan trọng mà tôi rút ra được là:
- Niềm tin là vô giá. – Slash không có các cuộc họp hàng ngày. Slash không có các sprint hàng tuần hoặc việc quản lý backlog. Chúng tôi có một cuộc họp mỗi tuần, và đó chỉ để trình diễn những gì chúng tôi đã xây dựng cho toàn đội. Điều này hoạt động vì đội ngũ nói chung có khả năng giao tiếp mạnh mẽ và kỹ năng chịu trách nhiệm ấn tượng. Điều đó không có nghĩa là không có sự hướng dẫn – tôi có các cuộc họp một-một hàng tuần để giải quyết các vấn đề của mình – nhưng thay vào đó, Slash tin tưởng bạn sẽ làm việc tốt nhất và tạo ra một môi trường nơi bạn có thể tập trung tối đa.
- Đội ngũ này thật tuyệt vời! – Trong các chương trình thực tập khác của tôi, đồng nghiệp của tôi rất chuyên nghiệp, nhưng ở đây, đồng nghiệp của tôi là người của tôiRõ ràng Slash có một văn hóa tuyệt vời với những con người vui vẻ, hỗ trợ và dễ làm việc cùng – không có ai mà tôi không thích làm việc cùng hay cảm thấy e dè, và họ đối xử với bạn như một nhân viên chính thức. Hơn nữa, bạn có thể đi chơi bóng rổ cùng họ vào cuối tuần 😃
- Với tư cách là thực tập sinh, bạn sẽ phát triển vượt bậc tại đây so với bất kỳ nơi nào khác. – Tại bất kỳ công ty nào khác, thực tập sinh sẽ không được giao toàn bộ hệ thống thông báo cốt lõi làm dự án. Những vấn đề khó khăn, thúc đẩy sự phát triển sẽ hoặc đã được giải quyết hoặc đang được giải quyết bởi một kỹ sư cấp cao. Điều làm nên sự khác biệt của Slash chính là sự kết hợp giữa các đội ngũ gọn nhẹ, những vấn đề kinh doanh quan trọng thực sự và một văn hóa tin tưởng giao phó công việc quan trọng ngay cả cho thực tập sinh.
Dưới đây là một số kỷ niệm thú vị khác từ kỳ thực tập này:
- Chúng tôi đã ăn tổng cộng khoảng 20 pound thịt bò trong một tuần… cảm ơn Hack Week!
- Tôi đã đánh bại đồng nghiệp thực tập của mình trong một cuộc thi bơi lội, nhưng ngay sau đó đã bị một nhân viên chính thức đánh bại.
- Cuối cùng tôi cũng đã nâng được một đĩa tạ!
- Tôi là một trong những người đóng góp chính cho "sự tham lam chung của văn phòng" (và có thể liên quan, tôi phát hiện ra mình rất thích Shake Shack).

Bốn tháng qua trôi qua nhanh hơn tôi tưởng, và tôi rất biết ơn những trải nghiệm mà tôi đã có tại Slash. Sắp tới, tôi sẽ tốt nghiệp, và dù cuộc sống sẽ mang đến cho tôi điều gì trong một tháng, một năm hay một thập kỷ tới, tôi biết rằng việc thực tập tại Slash đã trang bị cho tôi kiến thức và sự tự tin để thành công dù tôi đi đâu.
Nếu bạn quan tâm đến việc trò chuyện thêm, Hãy thoải mái liên hệ với tôi trên LinkedIn! Rất sẵn lòng trả lời bất kỳ câu hỏi nào của bạn.