Rin Hsu — Backend Engineer, Taipei

Backend engineering, for games. 我致力於後端與遊戲產業 バックエンド開発を、ゲーム業界で。

Just over five years of backend work in C# / .NET and Rust. For each system below I've written down the trade-offs I made and the numbers I actually measured. 五年多的後端開發經驗,主要使用 C# / .NET 與 Rust。以下每一套系統,我都寫下了當時的取捨與實際量到的數字。 C# / .NET と Rust を中心に5年あまりのバックエンド開発経験。以下の各システムについて、その時の判断と実際に計測した数字を書き残しています。

Production · Live on Steam

ArcadeGalaxy

Sole backend engineer for a commercial party platformer — architecture, deployment, and operations, Oct 2022 to Feb 2025. 商業派對遊戲的唯一後端工程師——架構、部署與維運,2022.10 – 2025.02。 商業パーティーゲームの唯一のバックエンドエンジニアとして、設計・デプロイ・運用を担当(2022年10月〜2025年2月)。
Role
Sole backend owner 唯一的後端負責人 バックエンドを一人で担当
Stack
C# (.NET) · PostgreSQL · Redis · SQS · SignalR · AWS
Scope
10 game systems, from spec to live ops 10 項遊戲系統,從規格到上線維運 10のゲームシステムを仕様から運用まで

ArcadeGalaxy is a multiplayer party game on Steam. I owned the entire backend as the only server engineer on the team — every game system the designers specced, I designed, built, deployed, and kept running. ArcadeGalaxy 是 Steam 上的多人派對遊戲。我是團隊裡唯一的伺服器工程師——企劃規格書上的每一個遊戲系統,都由我設計、實作、部署並持續維運。 ArcadeGalaxy は Steam のマルチプレイパーティーゲームです。チーム唯一のサーバーエンジニアとして、企画が仕様化したすべてのゲームシステムを、設計から実装、デプロイ、運用まで担当しました。

Unity client players .NET API servers REST + SignalR (WS) OIDC IdP OpenIddict, custom SQS consumer on-chain writes Blockchain ledger records PostgreSQL RDS Redis ElastiCache Steam payments
core topology — auth, realtime, on-chain writes, and payments around one API tier

Decisions that mattered 關鍵決策 重要だった意思決定

  • Built the identity provider instead of buying it. Firebase Auth is unavailable in some player regions, so I implemented a custom OIDC IdP with OpenIddict. Players everywhere log in through the same flow, and the game owns its account system. 自建身分驗證系統,而不是採用現成服務。部分玩家地區無法使用 Firebase Auth,因此我以 OpenIddict 實作了自有的 OIDC IdP。所有地區的玩家走同一套登入流程,帳號系統也完全掌握在遊戲手上。 認証基盤は買わずに作る。一部地域では Firebase Auth が利用できないため、OpenIddict で独自の OIDC IdP を実装しました。全地域のプレイヤーが同じログインフローを利用でき、アカウント基盤を自社で保有できます。
  • Cut the AWS bill by 75% without cutting capacity. Iterative architecture work — right-sizing instances, caching with Redis, removing redundant workloads — brought operating cost down to a quarter of the original. 在不犧牲容量的前提下砍掉 75% 的 AWS 費用。透過持續的架構調整——instance 規格調整、Redis 快取、移除多餘的運算負載——將維運成本降到原本的四分之一。 性能を落とさず AWS コストを75%削減。インスタンスの適正化、Redis キャッシュ、冗長なワークロードの削減など、継続的なアーキテクチャ改善により運用コストを4分の1にしました。
  • SQS as the path to the chain, SignalR as the path to the player. On-chain records are written through an SQS consumer — the message broker absorbs blockchain latency and gives every write retries. Realtime features like the friend system go over SignalR instead. Keeping the two paths separate kept both simple. SQS 通往鏈上,SignalR 通往玩家。寫入鏈上紀錄時,一律透過 SQS consumer 送出——這個 message broker 吸收了區塊鏈的延遲,也讓每一筆寫入都帶有重試。好友系統之類的即時功能則走 SignalR。把兩條路徑分開,讓兩邊都保持簡單。 SQS はチェーンへの経路、SignalR はプレイヤーへの経路。オンチェーン記録の書き込みは SQS consumer 経由で行い、メッセージブローカーがブロックチェーンのレイテンシを吸収し、各書き込みにリトライを与えます。フレンド機能などのリアルタイム処理は SignalR へ。経路を分けることで、双方をシンプルに保ちました。
  • Steam payments handled server-side. Transaction flow, verification, and reconciliation live in the backend, not the client. Steam 金流全部在伺服器端處理。交易流程、驗證與對帳都放在後端,而不是客戶端。 Steam 決済はすべてサーバー側で処理。取引フロー、検証、照合はクライアントではなくバックエンドに置いています。
−75%
aws operating cost
10
game systems shipped
1
backend engineer
Open source · Apache Software Foundation

Apache OpenDAL — .NET binding

Committer. I implement the C# binding of a Rust data-access layer used across the Apache ecosystem. Committer。實作這套 Rust 資料存取層的 C# binding,OpenDAL 廣泛應用於 Apache 生態系。 Committer。Apache エコシステムで広く使われる Rust 製データアクセス層の C# バインディングを実装。
Role
Committer · C# binding implementer Committer · C# binding 實作者 Committer · C# バインディング実装
Stack
Rust · C# · FFI / interop · GitHub Actions
Collaboration
Worldwide maintainers, English, async reviews 跨國維護者、英文溝通、非同步 review 世界中のメンテナーと英語で非同期レビュー

OpenDAL gives applications one API for many storage services — S3, GCS, Azure Blob, local filesystems, and dozens more. The core is Rust; my work is the layer that makes it feel native to .NET developers, which means everything that lives on the boundary between the two runtimes. OpenDAL 讓應用程式用同一套 API 存取多種儲存服務——S3、GCS、Azure Blob、本地檔案系統等數十種。核心是 Rust;我的工作是讓它對 .NET 開發者來說像原生套件一樣自然,也就是兩個 runtime 邊界上的所有事情。 OpenDAL は S3、GCS、Azure Blob、ローカルファイルシステムなど数十種類のストレージを単一の API で扱えるライブラリです。コアは Rust 製。私の仕事は、それを .NET 開発者にとってネイティブに感じられるものにすること、つまり2つのランタイムの境界に存在するすべてです。

.NET app any C# codebase C# API surface idiomatic types, errors, async — my layer FFI boundary ownership, lifetimes, marshalling — my layer Rust core opendal S3 GCS 40+ more
the binding owns everything between the app and the rust core

What the work looks like 這份工作的實際樣貌 具体的な仕事内容

  • API design across a language boundary. Rust's ownership model and C#'s garbage collector disagree about who frees memory and when. The binding resolves that argument so users never have to think about it. 跨語言邊界的 API 設計。Rust 的所有權模型和 C# 的 GC 對「誰、在什麼時候釋放記憶體」意見不合。binding 的工作就是調停這場爭論,讓使用者完全不用去想。 言語境界をまたぐ API 設計。Rust の所有権モデルと C# の GC は「誰がいつメモリを解放するか」で意見が合いません。その調停を binding が担い、利用者は何も意識せずに済みます。
  • When a reviewer asked how fast it was, I went and measured. A review comment on the FFI-boundary rework asked how the binding compares with .NET's native IO, so I built a benchmark suite against System.IO and AWSSDK.S3. The answer was uncomfortable at small payloads — fixed FFI cost makes 16 KiB reads several times slower — and good at large ones: chunked reads reach 0.91× of FileStream at 128 MiB, and the callback form allocates 6 KB where the native path allocates 134 MB. Both halves are published. Reviewer 問它有多快,我就去量。FFI 邊界重構的 PR 上有人問「這個 binding 跟 .NET 原生 IO 比如何?」,於是我寫了一整套對照 System.IOAWSSDK.S3 的 benchmark。小 payload 的答案並不好看——固定的 FFI 成本讓 16 KiB 讀取慢上數倍;大 payload 則相反:128 MiB 的分塊讀取達到 FileStream 的 0.91×,而 callback 形式只配置 6 KB,原生路徑則要 134 MB。兩半數據我都公開。 レビューで速度を問われたので、測りに行った。FFI 境界の刷新 PR で「このバインディングは .NET ネイティブ IO と比べてどうなのか」と聞かれ、System.IOAWSSDK.S3 を対照するベンチマーク一式を書きました。小さいペイロードでの答えは芳しくなく——固定の FFI コストにより 16 KiB 読み取りは数倍遅い——大きいペイロードでは逆転します。128 MiB のチャンク読み取りは FileStream の 0.91× に達し、コールバック形式の確保は 6 KB、ネイティブ側は 134 MB。どちらの結果も公開しています。
  • Keyless release pipeline. I set up NuGet Trusted Publishing for the package — releases authenticate with OIDC instead of long-lived API keys, which removes a whole class of supply-chain risk. 無金鑰的發布流程。我為套件建置了 NuGet Trusted Publishing——發布改用 OIDC 驗證而非長期 API key,直接消除一整類供應鏈風險。 キーレスなリリースパイプライン。NuGet Trusted Publishing を導入し、リリース認証を長期 API キーから OIDC に置き換え、サプライチェーンリスクを一類まるごと排除しました。
  • Apache-style collaboration. Design discussions, reviews, and releases all happen in public, in English, across time zones. Every decision has a paper trail anyone can read. Apache 式的協作。設計討論、review 與發布全部公開進行,使用英文、跨時區。每個決策都留下任何人可查的紀錄。 Apache 流のコラボレーション。設計議論、レビュー、リリースはすべて公開の場で、英語で、タイムゾーンを越えて行われます。すべての意思決定に、誰でも読める記録が残ります。
14
merged prs upstream
0.91×
vs filestream at 128 mib
6 KB
alloc where native takes 134 mb
Open source · Unity client

MacacaViewSystem — Addressables

Adding a second asset-loading mode to a Unity UI framework that was already in production, without asking anyone already using it to change a thing. 替一套已經在線上跑的 Unity UI 框架加上第二種資產載入模式,而且不要求任何既有使用者改動什麼。 すでに運用中の Unity UI フレームワークに、第二の読み込みモードを追加する。既存の利用者には何ひとつ変更を求めずに。
Role
Feature contributor 功能貢獻者 機能コントリビューター
Stack
C# · Unity · Addressables · editor tooling
Shipped
15 commits on master, Nov 2025 – Apr 2026 15 個 commit 進 master,2025.11 – 2026.04 master へ15コミット、2025年11月〜2026年4月

MacacaViewSystem is my former employer's open-source Unity UI system — views are composed from reusable elements, and the framework decides what to show and when. It loaded every view asset directly, which meant all of them shipped inside the build. I added Addressables as a second loading mode, so views can be packed into bundles and fetched on demand instead. MacacaViewSystem 是前公司開源的 Unity UI 系統——畫面由可重用的元件組成,框架負責決定何時顯示什麼。它原本每個 view 資產都直接載入,等於全部打進 build 裡。我加上 Addressables 作為第二種載入模式,讓 view 改成打包成 bundle、需要時再抓。 MacacaViewSystem は前職の会社が公開している Unity の UI システムです。画面は再利用可能な要素から構成され、何をいつ表示するかはフレームワークが決めます。従来は view のアセットを直接読み込む方式で、すべてがビルドに同梱されていました。そこへ Addressables を第二の読み込みモードとして追加し、view をバンドル化して必要時に取得できるようにしました。

view element requested by the ui direct load original path, untouched addressables added — async inside the build every view ships asset bundles fetched on demand a setting picks the path editor tooling assigns addresses and packs bundles at build time · page state, transitions and pools had to learn to wait
two paths, one of them new — and the old one still the default

What the work involved 這份工作實際做了什麼 実際に取り組んだこと

  • The loading call was the easy part. An element-based UI system built on synchronous instantiation assumes the asset is simply there when a page opens. Once assets start arriving late, that assumption breaks everywhere it was quietly relied on — page state, overlay registration, transition flags, and the element pools all had to tolerate a view that hasn't materialised yet. Most of the commits are that, not the Addressables API. 載入那一行是最簡單的部分。一套建立在同步實例化之上的元件式 UI 系統,預設「開頁面的時候資產就在那裡」。一旦資產開始晚一點才到,這個假設會在所有默默依賴它的地方一起垮掉——page 狀態、overlay 註冊、轉場旗標、element pool,全都得能容忍一個還沒生出來的 view。大部分的 commit 都花在這裡,而不是 Addressables 的 API。 読み込みの呼び出しは、いちばん簡単な部分。同期的なインスタンス化を前提に組まれた要素ベースの UI システムは、「ページを開く時点でアセットはそこにある」と想定しています。アセットが後から届くようになると、その前提は暗黙に依存していたあらゆる箇所で崩れます——ページ状態、オーバーレイの登録、トランジションのフラグ、エレメントプール。どれも「まだ実体化していない view」を許容できなければなりません。コミットの大半は Addressables の API ではなく、こちらに費やされています。
  • The old path stays the default. This is a framework other people's projects already depend on, so a migration nobody asked for is a bug. Addressables is a setting: leave it off and the original loading path behaves exactly as before. Turn it on and the editor tooling assigns addresses and packs the bundles at build time, so the new mode doesn't cost anyone a manual asset-management chore either. 舊路徑仍然是預設。這是一套已經有別人的專案在依賴的框架,所以「沒人要求的遷移」本身就是一個 bug。Addressables 是一個設定:不打開,原本的載入路徑行為完全不變;打開,editor 工具會在 build 時自動配址與打包——新模式也不會換來一份手動管理資產的雜事。 既存の経路が、あくまで既定。他者のプロジェクトがすでに依存しているフレームワークである以上、誰も望んでいない移行作業はそれ自体がバグです。Addressables は設定のひとつ。オフのままなら従来の読み込み経路は以前とまったく同じ挙動をします。オンにすれば、エディタ側のツールがビルド時にアドレス割り当てとバンドル化を行うため、新モードが手作業のアセット管理を増やすこともありません。
  • A generated asset that churns is everyone's problem. The addressable configuration is written into a file that lives in version control, and the first version rewrote enough of it on every build to produce noisy diffs and merge conflicts for the whole team. Narrowing what actually gets written was a small change that only matters if you think past your own machine. 一份每次都在變動的產生檔,是整個團隊的問題。Addressable 的設定會寫進一個進版控的檔案,而第一版每次 build 都改寫掉太多內容,替整個團隊製造出雜訊很大的 diff 與合併衝突。把「實際會被寫入的範圍」縮小是個很小的改動——但它只有在你想到自己這台機器以外的地方時才會發生。 毎回書き換わる生成物は、チーム全体の問題になる。Addressable の設定はバージョン管理下のファイルに書き込まれますが、最初の実装はビルドのたびに書き換える範囲が広すぎ、チーム全体にノイズの多い差分とマージ衝突を生んでいました。実際に書き込む範囲を絞るのは小さな変更です——ただし、自分のマシンの外側まで考えて初めて出てくる変更でもあります。
15
commits on master
2
loading modes, old one default
0
migration asked of users

These commits are under rin-macaca, the account I used at MacacaGames — my personal work is under Fatorin. 這些 commit 掛在 rin-macaca 名下,那是我在 MacacaGames 使用的帳號;個人專案則在 Fatorin これらのコミットは MacacaGames 在籍時に使用していた rin-macaca 名義です。個人の作業は Fatorin にあります。

Community infrastructure · 2020 – present

Warcraft III, kept alive

A community still plays a game from 2002. I've built and maintained its entire server stack for six years — hosting bot, account system, ladder, and the protocol libraries underneath. 有一群人到今天還在玩 2002 年的遊戲。這六年來,這個社群的整套伺服器架構由我打造與維護——開房機器人、帳號系統、積分系統,以及底下的協定函式庫。 2002年のゲームを、今も遊び続けているコミュニティがあります。この6年間、そのサーバー基盤一式を私が作り、支えてきました——ホスティングボット、アカウント基盤、レーティング、そしてその下のプロトコルライブラリまで。
Role
Solo, every layer of it 獨立負責每一層 全レイヤーを単独で担当
Stack
Rust · Tokio · Go · C++ · C# · binary protocols
Span
12 repositories, 2020 to now 12 個 repo,2020 年至今 12リポジトリ、2020年から現在まで

Warcraft III custom-map communities survive on infrastructure nobody is paid to run: a Battle.net-compatible realm, a bot that hosts the games, an account system, a ladder. When the software that does this is fifteen years old and unmaintained, somebody has to keep it working. For this community, that has been me — and over six years the work grew from patching the original C++ to owning every piece of the stack. Warcraft III 自訂地圖社群靠的是一套沒人付錢維護的基礎設施:一台相容 Battle.net 的伺服器、一個負責開房的機器人、一套帳號系統、一套積分系統。當這些軟體已經十五年沒人維護,總得有人讓它繼續動。這個社群的那個人是我——六年下來,工作從替原本的 C++ 打補丁,長成了掌握整條技術棧的每一塊。 Warcraft III のカスタムマップコミュニティは、誰も対価を受け取っていないインフラの上に成り立っています。Battle.net 互換のレルム、ゲームを立てるボット、アカウント基盤、レーティング。それらのソフトウェアが15年放置されていれば、誰かが動かし続けるしかありません。このコミュニティではそれが私でした。6年かけて、仕事は元の C++ にパッチを当てることから、スタックのすべてを自分で持つことへと育ちました。

WC3 client 1.26 – 1.28 ghostpp-rs hosting · lobby replay · rust PvPGN realm battle.net v1 third-party bn_manager accounts · maps bans · rust Discord players game records games · players · bans mmr-tracker ladder · go tcp telnet shared crates I wrote pvpgn-hash-rs — xsha1 + cd-key decoding, pure rust · stormlib-rs — mpq map archives
one community, four services, six years — everything solid-lined is mine

What it demonstrates 這條線證明了什麼 この積み重ねが示すもの

  • Reading systems I didn't write, then replacing them. ghost++ encodes years of accumulated protocol quirks in C++ built around a single-threaded 50 ms select loop. I ported the protocol layer byte-for-byte and rebuilt everything above it as Tokio async actors, so each connection and each game is a task with explicit failure modes. Understanding the original well enough to reproduce it was most of the project. 讀懂不是自己寫的系統,然後取代它。ghost++ 用 C++ 寫成,圍繞著一個單執行緒的 50ms select loop,裡面沉積了多年累積的協定細節。我把協定層 byte-for-byte 移植過來,上層則全部改建為 Tokio async actor——每個連線、每場遊戲都是一個 task,失敗模式明確可見。把原版理解到能重現的程度,本身就佔了這個專案的大半。 自分が書いていないシステムを読み、そして置き換える。ghost++ は単一スレッドの 50ms select ループを中心に組まれた C++ で、長年積み重なったプロトコルの癖が詰まっています。プロトコル層はバイト単位で移植し、その上を Tokio の async アクターとして作り直しました。各接続、各ゲームがタスクとなり、障害モードが明示的になります。元の実装を再現できるまで理解すること自体が、このプロジェクトの大半でした。
  • I wrote the same system twice, in two languages. The account and map-upload service started as War3Tool in Go. Living with it taught me what the shape should actually be, so the second version — bn_manager, in Rust — folded in Discord-driven registration, password resets, player reports, live room monitoring, and the ladder tables. The rewrite wasn't about the language; it was about finally knowing the requirements. 同一套系統,我用兩種語言寫了兩次。帳號與地圖上傳服務最早是 Go 寫的 War3Tool。用久了才明白它真正該長什麼樣,所以第二版 bn_manager 改用 Rust,並把 Discord 註冊、密碼重設、玩家檢舉、即時房間監控與積分資料表全部收進來。重寫的重點從來不是語言,而是我終於搞清楚需求了。 同じシステムを、二つの言語で二度書いた。アカウントとマップアップロードのサービスは、最初 Go の War3Tool でした。使い続けるうちに本来あるべき形が見え、二代目の bn_manager は Rust で書き直し、Discord 経由の登録、パスワード再設定、プレイヤー通報、ルームのリアルタイム監視、レーティングのテーブルまで取り込みました。書き直しの本質は言語ではなく、ようやく要件が分かったことでした。
  • Protocol work all the way to the bottom. Battle.net's login path needs CD-key decoding, XSHA1 password hashing, and executable-revision checks. Rather than link an old C library, I ported them to pure Rust as pvpgn-hash-rs, and contributed the implementation back to the upstream pvpgn project. Map handling goes through stormlib-rs, which I also contribute to. 協定工作一路做到最底層。Battle.net 的登入流程需要 CD-key 解碼、XSHA1 密碼雜湊與執行檔版本檢查。我沒有去連結一個老舊的 C 函式庫,而是把它們以純 Rust 重寫為 pvpgn-hash-rs,並把實作回饋給上游的 pvpgn 專案。地圖處理則走 stormlib-rs,我同樣有貢獻。 プロトコルの仕事を、最下層まで。Battle.net のログイン経路には CD キーのデコード、XSHA1 パスワードハッシュ、実行ファイルのリビジョン検証が必要です。古い C ライブラリをリンクする代わりに、これらを純 Rust の pvpgn-hash-rs として移植し、上流の pvpgn プロジェクトへ還元しました。マップ処理は stormlib-rs を通し、こちらにも貢献しています。
  • Built for the people actually using it. Reliable reconnects keep players in a match through a dropped connection. Every game is saved as a replay the client can open directly. And nothing user-facing is locked to one language — English, Korean, and Chinese all get spoken here. It matters most in the Discord bot, since that is where players actually register, reset passwords, and file reports; the hosting bot carries the same language catalog. Either can be extended to a new language by whoever runs it, without needing me. 是為了真的在用的人而做的。可靠重連讓玩家斷線後還能回到同一場遊戲。每一場都存成 client 可以直接打開的錄影檔。而且沒有任何面向使用者的文字被鎖死在單一語言——這裡英文、韓文、中文都有人講。最吃緊的是 Discord 機器人,因為註冊、重設密碼、檢舉這些事玩家都是在那裡完成的;開房機器人也帶著同一套語言檔。兩邊都能由架設的人自行擴充新語言,不需要來找我。 実際に使う人のために作る。信頼性のある再接続により、回線が切れてもプレイヤーは同じ試合に戻れます。すべての試合はクライアントで直接開けるリプレイとして保存されます。そしてユーザー向けの文言はどれも単一言語に固定されていません——ここでは英語・韓国語・中国語が飛び交います。とりわけ効いてくるのが Discord ボットで、登録・パスワード再設定・通報はすべてそこで行われるからです。ホスティングボットも同じ言語カタログを持ち、どちらも運営者自身が新しい言語を追加できます。私を介さずに。
  • And now the map itself. Alongside the servers I help maintain the custom map this community plays, which means its ceiling is whatever a 2002 engine allows. So I've started rebuilding it as a standalone game — prototypes in Godot and Unity first to find out which one fit, and now a real build in Unity. It's unfinished and not public, but it's the reason I care about the client side of a game and not only the servers behind it. 現在輪到地圖本身。除了伺服器,我也在維護這個社群在玩的那張自訂地圖——也就是說,它的天花板就是 2002 年那顆引擎能給的極限。所以我開始把它重建成一款獨立遊戲:先用 Godot 和 Unity 各做原型確認哪個合適,現在定案 Unity 正式製作中。它還沒完成,也還不公開,但這就是我在意遊戲客戶端、而不只是背後伺服器的原因。 そして次は、マップそのもの。サーバーと並行して、このコミュニティが遊ぶカスタムマップの保守にも関わっています。つまりその天井は、2002年のエンジンが許す範囲でしかない。そこで、独立したゲームとして作り直し始めました。まず Godot と Unity でプロトタイプを作って適性を見極め、現在は Unity で本制作中です。未完成で非公開ですが、サーバーだけでなくゲームのクライアント側にも関心を持つ理由が、ここにあります。
6
years maintained
12
repos in the stack
4
languages across it
Smaller work

Also built

Some of this has no public repo to link. Each is here for one decision worth describing. 有些東西沒有可以公開的 repo。放在這裡是因為它們各有一個值得講的決策。 公開リポジトリのないものもあります。それぞれ、語る価値のある判断がひとつあるので挙げています。
  • A lottery-draw display, in Tauri 2. The control panel and the display board are two separate OS windows, so a stream can capture the board alone and the operator's clicks never appear on camera. Both windows render from one source of truth held in Rust and broadcast on a state event, which means the operator's preview and what the audience sees can never drift apart. 樂透開獎顯示器,用 Tauri 2 做的。控制台與顯示盤是兩個獨立的作業系統視窗,所以直播只要擷取顯示視窗,操作過程不會入鏡。兩個視窗都從 Rust 端唯一的真相來源渲染,變更透過狀態事件廣播——操作者看到的預覽與觀眾看到的畫面不可能不一致。 抽選番号ディスプレイ、Tauri 2 製。操作パネルと表示ボードは別々の OS ウィンドウなので、配信では表示ウィンドウだけを取り込めば、操作の様子は画面に映りません。両ウィンドウは Rust 側に置いた唯一の真実からレンダリングされ、変更は状態イベントで配信されます。操作者のプレビューと観客の画面がずれることはありません。
  • A streamer's site with a CMS underneath it. Go backend on MySQL and Redis, Next.js front end. The site shows the channel's emotes, cheermotes and badges, but the request path never calls Twitch: a scheduled job refreshes them into Redis and the endpoints read from cache only, so a Twitch outage can't take the page down with it. The admin side is the other half — rather than hard-coding the pages, I built a small content editor so every block and every string can be edited per language without a deploy. 一個實況主的網站,底下是自己做的 CMS。Go 後端接 MySQL 與 Redis,前端是 Next.js。網站會顯示頻道的表情符號、歡呼圖示與徽章,但請求路徑完全不會去打 Twitch:排程工作定期把資料刷進 Redis,端點只從快取讀,所以 Twitch 掛掉不會把頁面一起拖下水。另一半是後台——我沒有把頁面寫死,而是做了一套小型內容編輯器,每個區塊、每段文字都能分語言編輯,不用重新部署。 配信者のサイトと、その下の自作 CMS。Go のバックエンドが MySQL と Redis を扱い、フロントは Next.js。サイトはチャンネルのエモート、チアモート、バッジを表示しますが、リクエスト経路から Twitch を叩くことはありません。定期ジョブが Redis に反映し、エンドポイントはキャッシュのみを読むため、Twitch の障害がページを道連れにすることがありません。もう半分は管理画面で、ページを直書きせず小さなコンテンツエディタを作ったため、各ブロック・各文言を言語ごとにデプロイなしで編集できます。
  • Contributions to other projects. A dead-code removal in apache/kafka; an allow-list addition in apache/infrastructure-actions so ASF repos can use NuGet's login action; .NET 10 support for the NuGetForUnity CLI; and seven Traditional Chinese localisation pull requests for a Hearthstone deck tracker. 其他專案貢獻。apache/kafka 的死碼移除;替 apache/infrastructure-actions 加上允許清單,讓 ASF 專案能使用 NuGet 的 login action;替 NuGetForUnity 的 CLI 加上 .NET 10 支援;以及一個爐石卡組追蹤器的七個正體中文在地化 PR。 他プロジェクトへの貢献。apache/kafka の未使用コード削除、apache/infrastructure-actions への許可リスト追加(ASF リポジトリが NuGet の login アクションを使えるように)、NuGetForUnity CLI の .NET 10 対応、そして Hearthstone デッキトラッカーの繁体字中国語ローカライズ7件。

About 關於我 自己紹介

I'm a software engineer who loves games. My career started in QA, testing games other people had made — and it was there that I started wanting to build the one I had in my head, which is what moved me into development. 一個熱愛遊戲的軟體工程師。我的職涯從 QA 開始,測試別人做出來的遊戲——也是在那段時間裡,我開始想做出心目中的那一款,於是走向開發。 ゲームが好きなソフトウェアエンジニアです。キャリアは QA から始まり、他の人が作ったゲームをテストしていました。その日々のなかで、自分の思い描く一本を作りたいと思うようになり、開発の側へ移りました。

From QA to engineering and on to today, I've kept learning and kept sharpening what I can build. 從 QA 到 RD 到現在,我持續不斷學習並加強自己的技術。 QA から開発へ、そして今に至るまで、学び続け、技術を磨き続けてきました。

What I'm working towards is specific: a game tens of thousands of people can play at the same time, and the high-concurrency, high-traffic systems that hold it up. 我想做到的事很具體:做出能讓數萬人同時遊玩的遊戲,以及撐得住它的高併發、高流量系統。 目指しているものははっきりしています。数万人が同時に遊べるゲームと、それを支える高並行・高トラフィックなシステムです。

Skills
C# (.NET) · Rust · PostgreSQL · Redis · Docker · Kubernetes · GitHub Actions · GitLab CI/CD · AWS · GCP
Languages
中文 · 日本語 (JLPT N1) · English (intermediate)