---
slug: chatwoot-open-source-omnichannel-support-platform
title: Chatwoot 開源客服台怎麼看？開源範圍、VPS 規格、技術棧與高流量承載
author: Seer
author_role: Author
status: published
published_at: "2026-07-08T07:53:31Z"
excerpt: Chatwoot 是一套開源 self-hosted 客服平台。重點不只在多渠道 inbox，也在它開源哪些、企業版鎖哪些、最低 VPS、Rails / Vue / PostgreSQL / Redis / Sidekiq 架構，以及前端在長歷史聊天場景下怎麼做分頁載入、去重與 scroll 補償。
category: Productivity
tags: [chatwoot, customer-support, omnichannel, self-host, open-source, rails, vue, postgres, redis]
read_time: 16 min
cover: "/static/chatwoot-open-source-omnichannel-support-platform-cover.png"
closing_note: "Chatwoot 適合想把客服資料和部署控制權拿回來的團隊；它能扛流量，但要把 web、worker、PostgreSQL、Redis 和物件儲存分開看。"
updated_at: "2026-07-08T07:53:31Z"
---

Chatwoot 的重點是把客服入口收進同一個工作台，而且可以自己部署。

如果你現在有網站 live chat、email、WhatsApp、Telegram、Line、Instagram、Facebook、SMS，客服訊息很容易散在不同地方。Chatwoot 解的是這個問題：**把多渠道訊息收進同一個 inbox，讓客服、營運、管理者在同一套系統裡分派、回覆、協作、看報表。**

但如果要真的拿來自架，不能只看「開源客服台」這幾個字。要看五件事：

1. 它開源的是哪些部分？企業版又鎖哪些？
2. 最低 VPS 要多大？
3. 前後端技術棧是什麼？
4. 高併發流量能不能扛？
5. 它到底解決哪一類客服問題？

這篇就照這五層拆。

## 先講結論

| 問題 | 判斷 |
|---|---|
| Chatwoot 是不是開源？ | 是。Community Edition 是 MIT 授權，主要客服功能可免費自架。 |
| 開源範圍到哪裡？ | repo 可看完整程式碼，但 `enterprise/` 目錄屬於企業版授權；CE 可改、可部署，EE 裡的付費功能不能當 MIT 使用。 |
| 最低 VPS 怎麼抓？ | 官方最低記憶體是 4GB RAM；CPU 建議最低 4 cores，可支援到 10,000 conversations/day。實務上我會把 4 vCPU / 4GB RAM 當最低可用線。 |
| 8GB RAM 有沒有必要？ | 如果有多渠道、附件、AI、報表、多人同時用，8 vCPU / 8GB RAM 更穩。官方也寫 8 cores / 8GB RAM 約支援到 20,000 conversations/day。 |
| 能不能扛高併發？ | 能，但不是單機硬扛。要把 Rails web、Sidekiq worker、PostgreSQL、Redis、Object Storage 分開規劃，流量再大就水平擴 app servers。 |
| 技術棧 | 後端 Ruby on Rails、Puma、Sidekiq、PostgreSQL、Redis；前端 Vue、Vite、Pinia、Vue Router、Tailwind 相關工具。 |
| 適合誰 | 想自架客服台、集中多渠道 inbox、掌握客戶資料、替代 Intercom / Zendesk 基礎客服工作流的團隊。 |

你前面說「VPN」，我這裡按「VPS / 雲主機」理解。Chatwoot 不是 VPN 服務，它是要部署在 VPS、VM、Kubernetes 或雲端平台上的客服系統。

## 開源是開源哪些？

Chatwoot 有 Community Edition 和 Enterprise Edition。

官方 user guide 寫得很清楚：Community Edition 是 `MIT` licensed；Enterprise Edition 是 proprietary license。兩者從同一個 GitHub repo 建出來，但 `enterprise/` 目錄的內容受企業版授權限制。

更直接地說：

| 範圍 | 狀態 |
|---|---|
| Community Edition | 免費、開源、MIT，可自架、可修改。 |
| Repo 裡非 `enterprise/` 的核心程式碼 | MIT Expat license。 |
| `enterprise/` 目錄 | 程式碼公開可見，但內容有 copyright / proprietary license，不等於 MIT。 |
| Enterprise Edition 付費功能 | 用授權啟用，官方列出 whitelabeling、SLA management、audit logs、agent capacity management 等。 |
| CE 未來升 EE | 官方建議若未來可能升付費功能，可以裝 Enterprise Edition，因為不用重新安裝，只是 license 啟用。 |

這種模式接近 GitLab / Mattermost / Metabase 的 commercial open-source：核心功能開源，企業治理、SLA、稽核、白標、進階管理能力放在付費層。

對一般中小團隊來說，重點是：**多渠道 inbox、客服協作、help center、contacts、reports 這類客服主流程，Community Edition 已經能用。**

如果你需要：

- Whitelabeling
- SLA Management
- Audit Logs
- Agent scheduling
- IP blocklisting
- 更細的企業權限與支援

那就要看 Enterprise Edition。

## 最低 VPS 規格要怎麼抓？

官方 self-hosted requirements 給了很明確的底線：

| 資源 | 官方資訊 | 我會怎麼抓 |
|---|---|---|
| OS | 官方支援 Ubuntu 20.04；Linux-based 系統為主 | Ubuntu LTS，避免 Windows 直上 |
| CPU | 4 cores 是 recommended minimum，支援到 10,000 conversations/day | 最低 4 vCPU 起跳 |
| RAM | 4GB RAM 是 required minimum，支援到 10,000 conversations/day | 最低 4GB；正式用建議 8GB |
| Swap | 升級時至少加 1GB swap，避免資源耗盡 | 1–2GB swap |
| PostgreSQL | 唯一支援資料庫；至少 5–10GB storage，實際依資料量和附件成長 | DB 不要跟附件混在一起估，要預留成長 |
| Redis | 用於 background task queue 和 cache；官方說可從 100MB 開始，建議 Redis 7+ | 小型可同機，大一點建議獨立或 managed Redis |
| Sidekiq | 背景工作程序；很活躍的 server 可能吃 1GB+ RAM | 正式環境把 web 和 worker 拆開 |

所以最低不是「1 vCPU / 1GB RAM 能不能跑起來」這種問題。Chatwoot 是 Rails app，加上 PostgreSQL、Redis、Sidekiq、附件、即時訊息、報表，1GB 或 2GB 很容易卡在升級、背景任務或尖峰流量。

我會這樣分級：

| 場景 | VPS 等級 | 說明 |
|---|---|---|
| 測試 / demo | 4 vCPU / 4GB RAM / 40GB SSD | 對齊官方最低可用線；適合小流量驗證。 |
| 小型正式站 | 4 vCPU / 8GB RAM / 80GB SSD | 同機跑 Rails、Sidekiq、PostgreSQL、Redis 會比較穩。 |
| 中型客服 | 8 vCPU / 8GB RAM 起 | 官方寫 8 cores / 8GB RAM 可支援到 20,000 conversations/day。 |
| 成長型部署 | app server + worker + managed PostgreSQL + Redis + S3 | 別只加大單機；要拆服務。 |

如果你要省錢，最低可以從 4 vCPU / 4GB RAM 起手。但如果這是正式客服入口，我不會把 PostgreSQL、Redis、Sidekiq、Rails 全塞在 4GB RAM 裡長期跑。它能跑，但維運餘裕小。

## 自架架構長什麼樣？

官方 production architecture 列出 Chatwoot 需要這幾個服務：

- Chatwoot web servers
- Chatwoot workers
- PostgreSQL Database
- Redis Database
- Email service，例如 SMTP / SendGrid / Mailgun
- Object Storage，例如 S3、Azure Storage、GCS、MinIO、DigitalOcean Spaces、Linode Objects

Docker production guide 也把 web 和 worker 拆成兩個角色：

```text
rails   -> bundle exec rails s -p 3000 -b 0.0.0.0
sidekiq -> bundle exec sidekiq -C config/sidekiq.yml
```

它不是只有一個 container 就結束。真正的正式架構要這樣看：

| 角色 | 負責什麼 | 高流量時怎麼擴 |
|---|---|---|
| Rails web / Puma | 管理後台、API、inbox、即時互動入口 | 增加 app server，前面放 Nginx / LB |
| Sidekiq workers | 背景任務、通知、同步、郵件、整合處理 | 增加 worker 數量或獨立 worker 主機 |
| PostgreSQL | 對話、聯絡人、設定、報表資料 | 用 managed DB、調整連線池、備份、IOPS |
| Redis | queue、cache、部分即時狀態 | 獨立 Redis / managed Redis |
| Object Storage | 附件、圖片、檔案 | 用 S3-compatible storage，不要把附件都壓在主機硬碟 |
| Email service | outbound email、通知 | 用 SendGrid / Mailgun / SMTP provider |
| Reverse proxy | HTTPS、WebSocket、流量入口 | Nginx / ALB / Cloudflare 等 |

官方 Docker 文件也提醒：container 預設只 bind localhost，要用 Nginx 或其他 proxy 對外服務。這點很重要，因為 Chatwoot 有即時訊息和 API，proxy 設定要處理 `Upgrade` / `Connection`，不能只當一般靜態網站反代。

## 前後端技術棧

Chatwoot 是一個 Rails + Vue 的產品，不是 Node 全端 app。

從 repo 和原始檔可以拆成這樣：

| 層 | 技術 |
|---|---|
| 後端語言 | Ruby |
| 後端框架 | Ruby on Rails 7.1 |
| Ruby 版本 | repo Gemfile 目前是 Ruby 3.4.4；官方 requirements 寫 Ruby 3.2+ |
| Web server | Puma |
| Background jobs | Sidekiq 7.x |
| Database | PostgreSQL；Docker production compose 使用 `pgvector/pgvector:pg16` image |
| Cache / Queue | Redis；官方建議 Redis 7+ |
| Auth / security | Devise、rack-attack 等 Rails 生態工具 |
| 前端框架 | Vue 3 |
| Build / frontend tooling | Vite、vite_rails、pnpm |
| State / routing | Pinia、Vue Router |
| 即時能力 | Rails / ActionCable 相關前端套件 |
| 圖表 / UI | Chart.js、Tailwind typography、Radix colors、Iconify、VueUse 等 |
| 部署 | Docker、Linux VM、Kubernetes Helm、Heroku、DigitalOcean 等 |

這個技術棧的意思是：

- 如果你熟 Rails，Chatwoot 很好理解，因為它是典型 Rails monolith 加前端 app。
- 如果你只熟 Node，維運時要補 Ruby / Rails / Sidekiq / Bundler / migrations 這套知識。
- 如果你要改 UI，前端是 Vue 生態，不是 React。
- 如果你要扛流量，瓶頸不只在 web server，Sidekiq、PostgreSQL、Redis 都要看。

## 前端在長歷史聊天場景做了哪些優化？

Chatwoot 前端真正值得看的地方，不是單純有沒有用了某個 virtual scroll 套件，而是它怎麼處理「客服對話越累積越長」這件事。

我細看目前 `develop` 分支的前端程式碼後，結論是：**訊息流本身沒有使用 virtual scrolling；Chatwoot 用的是分頁載入、scroll 位置補償、訊息去重、暫存訊息替換、斷線後補訊息、reply message cache 這幾層來處理長歷史聊天。**

### 1. 有 virtual scroll，但主要用在 conversation list，不是 message stream

Chatwoot 的 `package.json` 有 `virtua`，也確實在前端使用 `Virtualizer`。

但目前明確看到的使用位置是：

- `dashboard/components/ConversationList.vue`
- emoji picker 相關元件

`ConversationList.vue` 裡用 `Virtualizer` 包住左側 conversation list：

```vue
<Virtualizer
  ref="virtualListRef"
  v-slot="{ item }"
  :data="conversationList"
>
  <ConversationItem :source="item" />
</Virtualizer>
```

這代表左側客服案件列表有做 windowing，適合大量 conversation 的 inbox。可是單一對話裡的訊息列表，`MessageList.vue` 是直接：

```vue
<template v-for="(message, index) in allMessages" :key="message.id">
  <Message v-bind="message" />
</template>
```

所以不能寫成「Chatwoot 的聊天訊息流用了 virtual scroll」。比較準確的寫法是：**Chatwoot 在 conversation list 使用 virtualized rendering；單一 message stream 仍是把已載入的 messages 全部渲染。**

| 判斷 | 支持程度 | 依據 |
|---|---|---|
| 左側 conversation list 有 virtual scroll | 強 | `ConversationList.vue` import `Virtualizer` from `virtua/vue`，並用 `:data="conversationList"`。 |
| 單一聊天訊息流有 virtual scroll | 弱 / 不支持 | `MessageList.vue` 用 `v-for="message in allMessages"` 直接渲染，沒有看到 `Virtualizer`。 |

### 2. 長歷史聊天靠「往上捲載入舊訊息」

Dashboard 端的 `MessagesView.vue` 會監聽 `.conversation-panel` 的 scroll。當使用者捲到頂部附近，也就是 `scrollTop < 100`，才去抓更舊的訊息：

```js
if (scrollTop < 100 && !this.isLoadingPrevious && shouldLoadMoreMessages) {
  await this.$store.dispatch('fetchPreviousMessages', {
    conversationId: this.currentChat.id,
    before: this.currentChat.messages[0].id,
  });
}
```

API 端則透過 `MessageApi.getPreviousMessages({ conversationId, after, before })`，把 `before` 和可選的 `after` 傳到 `/conversations/:id/messages`。

Store 收到 payload 後，不是重抓整個對話，而是把舊訊息 prepend 到目前 messages 前面：

```js
chat.messages.unshift(...data);
```

這對長歷史聊天很重要。它把「載入全部歷史」改成「先載近期，再按需往前拉」。

| 優化 | 支持程度 | 說明 |
|---|---|---|
| 舊訊息分頁載入 | 強 | `fetchPreviousMessages` 使用 `before: currentChat.messages[0].id`。 |
| 捲到頂部才載入 | 強 | `scrollTop < 100` 才觸發。 |
| 舊訊息 prepend | 強 | `SET_PREVIOUS_CONVERSATIONS` 用 `unshift(...data)`。 |
| 避免重複載入到底 | 強 | payload 空時設 `allMessagesLoaded = true`。 |

### 3. prepend 舊訊息後，用 scroll height 補償避免畫面跳掉

長聊天列表最容易出現的問題是：使用者往上看舊訊息，一載入更舊的訊息，整個畫面突然跳走。

Chatwoot 在載入前記下：

```js
this.heightBeforeLoad = this.conversationPanel.scrollHeight;
this.scrollTopBeforeLoad = this.conversationPanel.scrollTop;
```

載入後算高度差：

```js
const heightDifference =
  this.conversationPanel.scrollHeight - this.heightBeforeLoad;
this.conversationPanel.scrollTop =
  this.scrollTopBeforeLoad + heightDifference;
```

這段的效果是：舊訊息加到上方後，把 scrollTop 往下補同樣高度，讓使用者原本看的訊息仍停在相近位置。

這不是 virtual scroll，但它是長歷史聊天室必備的體驗優化。

### 4. 新訊息與暫存訊息用 echo / pending replacement 去重

客服回覆時，前端會先建立 pending message，讓畫面立刻出現送出中的訊息。API 回來後，再把 pending message 換成正式訊息。

Dashboard store 裡的 `findPendingMessageIndex` 會用正式 message 的 `id` 或 `echo_id` 找暫存訊息：

```js
m => m.id === message.id || m.id === tempMessageId
```

`ADD_MESSAGE` 找到 pending message 時會直接替換：

```js
if (pendingMessageIndex !== -1) {
  chat.messages[pendingMessageIndex] = message;
} else {
  chat.messages.push(message);
}
```

Widget 端也有類似邏輯。它用 object map 存 messages，`pushMessageToConversation` 會用 message id 寫入；如果是 incoming 且找到同 content 的 `in_progress` message，會刪掉暫存訊息再放正式訊息。

這裡能支持的說法是：**Chatwoot 有 optimistic UI，也有 pending message replacement，避免同一則訊息在送出後重複出現。**

不能過度寫成「多則訊息批次合併渲染」。我沒有看到 message.created websocket 事件被 coalescing 成一個批次再 render；ActionCable 的 `message.created` 仍是事件來了就 dispatch `addMessage`。

| 說法 | 支持程度 | 判斷 |
|---|---|---|
| 有 pending message replacement | 強 | `findPendingMessageIndex` + `ADD_MESSAGE` 替換。 |
| 有基本去重 | 強 | pending / echo id、WhatsApp source id、missing messages filter。 |
| websocket 多則訊息合併成批次 render | 弱 | 沒看到明確 batching；`message.created` 逐則 dispatch。 |

### 5. WhatsApp 有 source_id 去重

在 WhatsApp channel，`MessagesView.vue` 會先跑：

```js
if (this.isAWhatsAppChannel) {
  return filterDuplicateSourceMessages(messages);
}
```

`filterDuplicateSourceMessages` 會用 `source_id` 去重，遇到重複 source id 時保留前面那則。測試也明確驗證：`wa_1` 多則只留 id 較小、較早進入陣列的那則。

這段屬於 channel-specific 的資料清理，不是通用效能優化。但在長歷史聊天裡，它能避免同一來源訊息重複渲染，也能減少列表雜訊。

### 6. 斷線重連後會補缺訊息，不只靠 websocket

長時間開著客服台，websocket 斷線是常態。Chatwoot 有 `ReconnectService`：

- disconnect 時記下目前 active conversation 的 last message id
- reconnect 後對目前 conversation dispatch `syncActiveConversationMessages`
- API 用 `after: lastMessageId` 抓斷線期間的新訊息
- 前端 filter 掉已存在 message id
- 再依 `created_at` 排序後寫回 store

核心邏輯是：

```js
const missingMessages = payload.filter(
  message => !messages.find(item => item.id === message.id)
);
selectedChat.messages.push(...missingMessages);
const sortedMessages = selectedChat.messages.sort((a, b) => {
  return new Date(a.created_at) - new Date(b.created_at);
});
```

這段對長歷史場景很有用，因為它不是假設 websocket 永遠可靠，而是在重連時補齊缺口。

### 7. Reply message 有 cache，避免引用訊息重複打 API

`MessageList.vue` 裡有 `fetchedReplyMessages = reactive(new Map())`。當某則 message 是 reply，但被引用的原訊息不在目前已載入 messages 裡，就會用 `MessageApi.getPreviousMessages` 去抓附近訊息。

抓過之後會放進 Map：

```js
if (fetchedReplyMessages.has(messageId)) {
  return fetchedReplyMessages.get(messageId);
}
```

找不到也 cache `null`，避免同一個缺失 reply 反覆打 API。

這是小但實際的優化：長歷史聊天裡，reply 可能指向很久以前的訊息；Chatwoot 不會為每次 render 重複查同一個引用。

### 8. 未讀數與統計有節流 / debounce

ActionCable 裡 `conversation.unread_count_changed` 不會每次都直接打 unread counts API。它有 5 秒 throttle：

```js
const UNREAD_COUNTS_REFETCH_THROTTLE_MS = 5000;
```

Conversation stats 也會依總 conversation 數調整 debounce：

```js
if ($state.allCount > 2000) {
  superLongDebouncedFetchMetaData(commit, params);
} else if ($state.allCount > 100) {
  longDebouncedFetchMetaData(commit, params);
} else {
  debouncedFetchMetaData(commit, params);
}
```

這不是單一 message list 的優化，但對客服台整體很重要：conversation 很多時，統計和未讀數更新不能每個事件都打 API。

### 9. Widget 端也沒有 virtual scroll，但有同樣的舊訊息載入邏輯

網站 chat widget 的 `ConversationWrap.vue` 也是直接依 grouped messages render：

```vue
<ChatMessage
  v-for="message in groupedMessage.messages"
  :key="message.id"
  :message="message"
/>
```

它在使用者捲到頂部附近時抓舊訊息：

```js
if (this.$el.scrollTop < 100) {
  this.fetchOldConversations({ before: this.earliestMessage.id });
  this.previousScrollHeight = this.$el.scrollHeight;
}
```

Widget store 用 object map 存訊息：

```js
$state.conversations[message.id] = message;
```

這比 array append 更容易用 id 覆蓋更新，也能避免同 id 訊息重複。但 getter 會 `Object.values(_state.conversations)` 再 group by date，所以載入量太大時仍會有整批轉換與分組成本。

## 這段能支持到什麼程度？

如果要寫進文章，我會這樣下判斷：

> Chatwoot 的前端沒有把單一聊天訊息流做成 virtualized message list。它的長歷史聊天優化主要靠 cursor pagination、往上捲載入舊訊息、prepend 後 scrollTop 補償、pending message replacement、channel-specific 去重、斷線重連補訊息，以及 reply message cache。這些設計讓日常客服長對話可以穩定使用，但如果同一個 conversation 已載入非常大量 messages，前端仍會把已載入的訊息完整渲染，效能上限取決於一次載入多少、訊息內容多複雜、附件多不多，以及瀏覽器 DOM 負載。

證據強度可以分成三層：

| 層級 | 可寫內容 | 支持程度 |
|---|---|---|
| 明確程式碼支持 | conversation list 使用 `virtua`、message stream 分頁載入、scroll 補償、pending replacement、reconnect 補訊息、reply cache、unread counts throttle | 強 |
| 合理推論 | 這些設計能改善長歷史聊天體驗，降低初始載入量，避免 prepend 跳動，減少重複 API 和重複訊息 | 中 |
| 不該寫死 | 「Chatwoot message stream 有 virtual scrolling」、「多則 websocket 訊息會批次合併 render」、「官方保證某個前端可承載訊息數」 | 弱 / 不支持 |

所以這段最好的寫法不是直接寫「高併發前端很強」，而是寫成：**Chatwoot 在客服台前端做了很多務實的長對話保護，但它的 message stream 還不是 virtualized rendering；真正的大量歷史訊息承載，仍要靠後端 pagination 和前端不要一次載入太多。**

## 高併發流量能不能扛？

能，但要先定義「高併發」是什麼。

Chatwoot 官方用 conversations/day 給硬體參考：

| 官方參考 | 可支援量 |
|---|---|
| 4 cores / 4GB RAM | up to 10,000 conversations/day |
| 8 cores / 8GB RAM | up to 20,000 conversations/day |
| 更高量 | 水平擴充 app servers |

這表示 Chatwoot 不是只能給小團隊用。它的架構有 web servers、workers、PostgreSQL、Redis，可以水平擴。

但要注意，客服系統的壓力不是單純 page view：

- 客戶開 live chat widget
- 多個 agent 同時看 inbox
- conversation 事件持續更新
- email / webhook / channel integration 進來
- attachment 上傳
- automation / notification / report 在背景跑
- AI agent 或 bot 額外打外部 API

所以高流量下要分開看：

| 壓力來源 | 主要瓶頸 | 做法 |
|---|---|---|
| 很多訪客載入 widget | Rails web / CDN / proxy | 前面放 CDN / LB，增加 web server |
| 很多訊息同時進來 | Sidekiq / Redis / DB writes | worker 獨立擴，Redis 不要太小 |
| 多客服同時操作 inbox | Rails / PostgreSQL / WebSocket | app server 水平擴，DB 連線池和索引要看 |
| 大量附件 | local disk / object storage | 用 S3-compatible storage |
| 報表查詢 | PostgreSQL | DB 規格、索引、讀寫壓力要監控 |
| AI / bot | 外部 API latency + background jobs | 把 AI 工作丟 worker，不要卡住 web request |

如果只是 4 vCPU / 4GB RAM 單機，它適合小型到中小型使用。但如果是對外大站客服入口，我會直接設計成：

```text
Nginx / Load Balancer
  -> Chatwoot Rails web x N
  -> Chatwoot Sidekiq workers x N
  -> PostgreSQL managed / dedicated
  -> Redis managed / dedicated
  -> S3-compatible object storage
  -> SMTP provider
```

也就是說：**Chatwoot 能扛，但不能期待一台小 VPS 同時扛所有事。**

## 它能解決什麼問題？

Chatwoot 最適合解的是「客服訊息分散」和「客服流程沒有中樞」。

### 1. 多渠道訊息集中

它支援 live chat、email、Facebook、Instagram、Twitter / X、WhatsApp、Telegram、Line、SMS 等入口。

這讓客服不用在不同平台切來切去，同一個客戶的互動也更容易被集中整理。

### 2. 支援團隊協作

Chatwoot 不是只收訊息。它還有：

- Private Notes
- @mentions
- Labels
- Canned Responses
- Auto-Assignment
- Teams and Automation
- Agent Capacity Management
- Custom Views and Filters
- Business Hours
- Auto-Responders

這些功能解的是客服團隊日常問題：誰接、誰回、怎麼分類、怎麼交接、怎麼追蹤。

### 3. Help center 和客服 inbox 接在一起

Chatwoot 有 help center portal，可以放 FAQ、教學文章、操作指南。

這讓它不只是「等客戶來問」，也能把重複問題導到自助內容，降低客服負擔。

### 4. 客戶資料和互動歷史

Chatwoot 有 contact profiles、interaction history、segments、notes、custom attributes、pre-chat forms。

這讓客服不是只看一則訊息，而是能看到客戶是誰、之前問過什麼、屬於哪個分類。

### 5. 報表與營運管理

官方 README 列出 conversation、agent、inbox、label、team、CSAT、downloadable reports 等報表能力。

對主管來說，這代表可以看：

- 哪個渠道訊息最多
- 哪個 inbox 最忙
- 哪些 agent 回覆量高
- 客戶滿意度如何
- 哪些標籤或問題類型重複出現

## 什麼情境適合 Chatwoot？

我會把 Chatwoot 放在這些情境：

| 情境 | 適合度 |
|---|---|
| 想自架客服台，不想把客戶資料全放 SaaS | 高 |
| 已經有多個客服渠道，訊息分散 | 高 |
| 想找 Intercom / Zendesk 的開源替代品 | 高 |
| 有內部工程能力維運 Rails / Docker / DB | 高 |
| 只有一個簡單聯絡表單 | 低 |
| 不想碰 server、備份、升級、proxy | 低，直接用 SaaS 比較省事 |
| 需要大型企業治理、SLA、audit logs、白標 | CE 不夠，要看 EE |

Chatwoot 的價值不是「免費客服軟體」，而是你能把客服工作流和資料控制權拿回來。

## 自架要注意哪些維運責任？

自架 Chatwoot 不是裝完就結束。你要負責：

- HTTPS / reverse proxy
- Docker image 更新
- Rails database migration
- PostgreSQL 備份與還原
- Redis 密碼和可用性
- Sidekiq queue 堆積監控
- SMTP / channel integration 設定
- Object storage 權限和容量
- 環境變數管理
- security updates

官方 Docker 文件也提醒，升級時要跑：

```bash
docker compose pull
docker compose up -d
docker compose run --rm rails bundle exec rails db:chatwoot_prepare
```

如果你的安裝很舊，官方建議不要直接跳到最新版，要逐版看 release notes 和中間版本。

這代表 Chatwoot 的門檻不在產品使用，而在維運。

## 我會怎麼部署

如果是小團隊試用，我會這樣起手：

```text
一台 4 vCPU / 4GB RAM VPS
Ubuntu LTS
Docker Compose
Nginx + Let’s Encrypt
PostgreSQL + Redis 同機
S3-compatible object storage
SMTP provider
```

如果是正式客服入口，我會改成：

```text
Nginx / Load Balancer
Rails web server x 2+
Sidekiq worker x 1+
Managed PostgreSQL
Managed Redis
S3-compatible object storage
SMTP provider
Monitoring + backup
```

如果 conversations/day 接近 10,000，我不會再用「單台 VPS 什麼都包」的想法。這時候要先拆 Sidekiq 和 database，再看 web server 要不要水平擴。

## 結論

Chatwoot 是一套成熟的開源客服平台。它能把 live chat、email、WhatsApp、Telegram、Line、社群訊息、help center、客服協作、報表放進同一個系統。

它開源的核心很夠用：Community Edition 是 MIT 授權，適合大多數想自架客服台的團隊。企業治理、SLA、audit logs、白標、進階支援這些功能則在 Enterprise Edition。

最低 VPS 我會抓 4 vCPU / 4GB RAM；正式環境建議 4 vCPU / 8GB RAM 起，流量再上去就拆 Rails web、Sidekiq、PostgreSQL、Redis 和 object storage。

如果你要的是「省事」，SaaS 會更快。如果你要的是「客服資料、部署、整合、流程都自己掌握」，Chatwoot 很值得看。

## 參考

1. GitHub repo：<https://github.com/chatwoot/chatwoot>
2. Chatwoot README：<https://github.com/chatwoot/chatwoot/blob/develop/README.md>
3. System Requirements：<https://developers.chatwoot.com/self-hosted/deployment/requirements>
4. Production Architecture：<https://developers.chatwoot.com/self-hosted/deployment/architecture>
5. Docker Production Deployment：<https://developers.chatwoot.com/self-hosted/deployment/docker>
6. Enterprise Edition docs：<https://developers.chatwoot.com/self-hosted/enterprise-edition>
7. Enterprise Edition user guide：<https://www.chatwoot.com/hc/user-guide/articles/1677776492-enterprise-edition>
8. LICENSE：<https://github.com/chatwoot/chatwoot/blob/develop/LICENSE>
