MessagePack 什麼時候該用?什麼時候不該用?
一篇給實務工程師的使用場景指南
MessagePack 常常被拿來跟 JSON、Protobuf、gRPC 一起比較,但這其實是個錯誤的起點。
因為 MessagePack 不是要取代 JSON,也不是要跟 Protobuf 正面競爭;它真正厲害的地方,在於它填補了一個非常關鍵、但常被忽略的區間:
「我不想要 JSON 的冗餘,但我也不想要 gRPC 的複雜度。」
這篇文章會用場景導向的方式,說明 MessagePack 最適合用在哪裡、什麼情況下它是神兵利器,以及什麼時候你根本不該考慮它。
一、先給結論:MessagePack 的「甜蜜點」
一句話總結 MessagePack 的定位:
MessagePack =「結構化資料 + 二進制內容 + 高頻傳輸」的最佳折衷方案
如果你的資料同時滿足以下任兩點,MessagePack 幾乎一定值得考慮:
- 資料是結構化的(Object / Array)
- 資料中包含Binary(圖片、音訊、Buffer、Float Array)
- 傳輸頻率高、或總流量大
- 機器對機器(而不是人類)在溝通
二、TypeScript / JavaScript 對 MessagePack 的支援其實非常成熟
很多人對 MessagePack 的第一個誤解是:
「在 TS / 前端用 MessagePack 會不會很痛苦?」
實際上完全不會。
官方維護的 @msgpack/msgpack 是純 TS/JS 實作,支援:
- Browser
- Node.js
- Bun
- Deno
而且透過 TypeScript Generics,開發體驗非常順。
import { encode, decode } from "@msgpack/msgpack";
interface User {
id: number;
name: string;
tags: string[];
}
// Encode
const binary = encode<User>({
id: 1,
name: "Alice",
tags: ["admin"],
});
// Decode(型別推斷)
const user = decode<User>(binary);
user.name; // string
⚠️ 注意:
decode<T>() 不是 runtime validation,而是型別轉型(casting)。
如果你需要 runtime 驗證,MessagePack 應該搭配 schema validator 使用,而不是單獨承擔型別安全。
三、最容易被低估的殺手級應用:混合資料傳輸(文字 + 檔案)
傳統方案的問題
Web 世界中,我們經常要同時傳送:
- 表單資料(JSON 結構)
- 圖片 / 音檔 / Buffer
常見做法只有兩種:
-
multipart/form-data- 結構複雜
- 巢狀資料難維護
- 型別難對齊
-
JSON + Base64
- 體積膨脹 33%
- CPU 浪費在 Base64 encode/decode
MessagePack 的解法
MessagePack 原生支援 Binary Type。
const payload = {
user: {
id: 123,
name: "Alice",
},
avatar: imageUint8Array, // 直接放 binary
};
fetch("/api/profile", {
method: "POST",
headers: { "Content-Type": "application/x-msgpack" },
body: encode(payload),
});
後端 decode 後,avatar 就是 bytes,沒有任何轉換成本。
👉 這個場景下,MessagePack 幾乎是目前 Web 世界最優雅的解法。
四、不要誤會:MessagePack 在「大量文字資料」並不佔優
假設你要下載:
1 萬筆歷史訂單(主要是文字)
直覺可能會想:「MessagePack 不是比較小嗎?」
但現實是:
- JSON + Gzip / Brotli
- 幾乎已經把重複 key 壓到極限
| 格式 | 壓縮後體積 |
|---|---|
| JSON + Brotli | ~2.0 MB |
| MessagePack + Brotli | ~1.9 MB |
為了省那一點點流量:
- 前端多一個解碼 library
- Network panel 不可讀
- Debug 成本上升
👉 完全不值得
真正該優化的是「資料結構」,不是格式
{
"columns": ["id", "name", "price"],
"rows": [
[1, "A", 100],
[2, "B", 200]
]
}
這種結構,比換 MessagePack 有效 10 倍。
五、MessagePack 在 BFF / 微服務內部通訊是高 CP 值選擇
在 Client ↔ Server 使用 JSON 是對的,但在:
- BFF ↔ Service
- Service ↔ Service
- Service ↔ Redis
MessagePack 非常適合。
為什麼?
- 沒有人需要讀它
- 傳輸頻率高
- CPU 與頻寬都是真實成本
與 gRPC 的實際取捨
| gRPC | MessagePack | |
|---|---|---|
| Schema | 嚴格 | 無 |
| 開發成本 | 高 | 低 |
| 變更彈性 | 低 | 高 |
| 適合語言 | Go / Java | Node / Python |
👉 如果你覺得 .proto 太重、JSON 太慢,MessagePack 是完美中間解。
六、被忽略但非常重要的用法:Redis / Cache 儲存
很多系統還在這樣存 Redis:
redis.set(key, JSON.stringify(obj));
這其實是:
- 浪費記憶體
- 浪費 CPU
- 浪費 UTF-8 parsing
改成:
redis.setBuffer(key, encode(obj));
你會得到:
- ~30% 記憶體節省
- 更快的序列化
- 更少 GC 壓力
👉 在高流量系統中,這個改動「非常值錢」。
七、什麼時候「不該」用 MessagePack?
請直接用別的方案:
❌ 單一超大檔案(影片 / ZIP / Backup)
- 用 HTTP stream
- 用 multipart
- 不要包一層 MessagePack
❌ 公開 API(給第三方開發者)
- JSON 可讀性太重要
- MessagePack 會提高使用門檻
八、總結:一個實務導向的決策表
| 使用場景 | 推薦 |
|---|---|
| 前端 API | JSON |
| 混合資料上傳 | MessagePack 👑 |
| BFF / 微服務內部 | MessagePack |
| Redis / Cache | MessagePack(強烈) |
| 大量文字列表 | JSON + Gzip |
| 超大檔案 | Stream / Multipart |
最後一句話
MessagePack 不是「到處都該用」的銀彈,但在對的地方用對它,它會是:
最少侵入、最高回報的效能優化之一
如果你的系統正卡在:
- JSON 太肥
- gRPC 太重
- Binary 處理太痛苦
那你現在正站在 MessagePack 的甜蜜點上。