監控與 pg_cron/pgmq:讓自架 Supabase 看得住、跑得動 | Supabase 完整教學

監控與 pg_cron/pgmq:讓自架 Supabase 看得住、跑得動 | Supabase 完整教學

上一篇我們補上了自架 Supabase 的備份、升級與上線檢查——讓系統「架得起來、養得好」。這一篇要補上最後一塊:看得住、跑得動。你會學到怎麼用 Studio Reports/Logs 與 pg_stat_statements 抓出拖垮效能的慢查詢、怎麼接 Prometheus/Grafana 的 metrics endpoint 監控連線數/CPU/磁碟並設告警;還有怎麼用 pg_cron 在資料庫內排程定時 SQL 任務、用 pgmq 把 PostgreSQL 當成訊息佇列,在資料庫層就把非同步背景工作處理掉。這是自架段(SB-5)的第三篇。

前言

先用一句話定義本篇的兩個主題:監控,是讓你在使用者發現問題之前就先發現問題;而 pg_cron 與 pgmq,則是讓你不必額外架 Redis 或 cron 伺服器,就能在資料庫內部把定時任務與非同步佇列處理掉。 前者關乎「看得住」,後者關乎「跑得動」。

用一個類比理解「監控」是什麼。如果說前一篇的備份是幫房子保火險,那監控就是裝煙霧偵測器加保全系統。 火險是出事之後把損失補回來,煙霧偵測器則是在火苗剛冒出來、還沒燒起來時就叫醒你。自架 Supabase 沒有雲端幫你盯著的儀表板與告警,磁碟悄悄滿了、某個容器半夜被 OOM Kill、慢查詢把連線池吃光——這些若沒有監控,你只會在使用者哀嚎「網站掛了」時才知道,而那通常已是數小時後。

再用一個類比理解 pg_cron 與 pgmq。它們讓 PostgreSQL 從「只會被動回答查詢的資料庫」,變成「會自己定時做家事、還能排隊處理待辦事項的員工」。 pg_cron 是那個會準時打卡、每天凌晨三點自動清垃圾的員工;pgmq 則是門口那個待辦事項的收件匣,訊息一筆筆排隊等 Worker 來領走處理。兩者搭起來,你就能在資料庫層組出一整套背景任務系統——而且少養一個要維運的元件。

本篇你會學到:

  • 監控三層:Studio Reports/Logs 日常巡檢、pg_stat_statements 抓慢查詢、Prometheus/Grafana 長期趨勢與告警
  • 關鍵告警:連線數、CPU、磁碟、慢查詢、容器重啟該在哪條線上設警戒
  • pg_cron 排程:用 cron.schedule 在資料庫內定義定時 SQL 任務,並管理與查看執行歷史
  • pgmq 佇列:用 send/read/archive 在 PostgreSQL 裡做非同步訊息佇列,搭配 pg_cron 組出完整 Worker 流程

本篇聚焦「監控」與「排程/佇列 extension」。Supabase 的 metrics endpoint 路徑、認證方式、Studio 各頁面的欄位,以及擴充功能的可用版本,都可能隨版本演進而變動;正式導入前一律以官方文件與你實際部署的版本為準,文中出現的具體路徑與 API 細節請當作方向而非逐字照抄。

核心概念

在動手之前,先建立三張心智圖:一是「監控該分成哪幾層、各層看什麼」,二是「pg_cron 在資料庫層扮演什麼角色」,三是「pgmq 為什麼能取代外部訊息佇列」。

一、監控的三個層次

自架 Supabase 的監控,務實地可以分成由淺到深的三層,對應不同的使用時機:

層次工具看什麼適用時機
內建儀表Studio Reports / LogsCPU、記憶體、連線數、請求量圖表;各服務日誌日常巡檢、臨時排錯
資料庫內部pg_stat_statements每種查詢的執行次數與累積耗時抓慢查詢、找效能瓶頸
外接可觀測性Prometheus + Grafanametrics endpoint 的約 200 個指標長期趨勢、自動告警

理解這三層的關鍵,是搞懂它們回答的問題不同:

  • Studio Reports/Logs 回答「現在系統健康嗎?剛剛那個錯誤是哪個服務噴的?」。Reports 頁提供資料庫層級的圖表(CPU、記憶體、磁碟 I/O、連線數等),Logs 頁能分別查 Postgres、Auth(GoTrue)、PostgREST、Realtime、Storage 各服務的日誌。這是最省事的第一站,適合每天掃一眼、出錯時快速定位。
  • pg_stat_statements 回答「到底是哪條查詢在拖慢我的資料庫?」。它是 PostgreSQL 的擴充功能,會累積記錄每一種查詢範式(query pattern)的呼叫次數、總耗時、平均耗時。當你的 API 開始變慢,答案幾乎都藏在這張表裡——通常是某條漏建索引、或 RLS 政策沒優化的查詢在做全表掃描。
  • Prometheus + Grafana 回答「過去一週的連線數趨勢如何?磁碟什麼時候會滿?」。Supabase 每個實例暴露一個 metrics endpoint(路徑約為 /customer/v1/privileged/metrics,實際路徑與認證方式以官方文件為準),裡面有約 200 個 PostgreSQL 效能指標。用 Prometheus 定期抓、Grafana 畫成儀表板,再對關鍵指標設告警規則,才能做到「在出事前主動通知你」。

一句話選型:先用 Studio Reports/Logs 建立日常感覺,把 pg_stat_statements 打開抓慢查詢,等上了正式流量再接 Prometheus/Grafana 做趨勢與告警。

二、pg_cron:把排程搬進資料庫

pg_cron 是 PostgreSQL 的排程擴充功能,讓你直接在資料庫內部定義 Cron 排程,不必在作業系統層另外設 crontab、也不必架一台專門跑排程的伺服器。Supabase 的 PostgreSQL 映像通常已預先包含此擴充功能。

它的語法核心就一個函式:

cron.schedule('任務名稱', '* * * * *', $$ 要執行的 SQL $$);

第二個參數是標準的 5 欄位 Cron 表達式(分、時、日、月、星期),第三個參數是任務名稱到期時要跑的 SQL。常見用途包括:定時清理過期資料、定期刷新 Materialized View、每分鐘觸發一次 Worker 去消費佇列。在資料庫層做排程的最大價值,是「少一個要維運的元件」——自架本來就有十幾個容器要顧,能用資料庫內建功能解決,就不必再多養一套排程系統。

三、pgmq:用 PostgreSQL 當訊息佇列

pgmq(PostgreSQL Message Queue)是以 PostgreSQL 原生資料表和函式實作的訊息佇列。過去你要做非同步任務(寄信、產報表、呼叫外部 API),常會架一套 Redis 或 RabbitMQ 當 message broker;pgmq 讓你不必多養這套基礎設施,直接在資料庫裡就有一個佇列。

它的核心是一組函式,對應佇列的生命週期:

動作函式說明
建立佇列pgmq.create('佇列名')建立一個持久佇列
送訊息pgmq.send('佇列名', jsonb)把一筆 JSON 訊息放進佇列
讀訊息pgmq.read('佇列名', vt, n)讀 n 筆,並鎖定 vt 秒(可見性超時)
確認完成pgmq.archive(...) / pgmq.delete(...)歸檔(保留審計)或刪除

其中最關鍵的概念是可見性超時(visibility timeout,vt):當 Worker read 出一筆訊息,這筆訊息會被「鎖定」vt 秒,期間其他 Worker 看不到它。如果 Worker 在 vt 秒內成功處理完並 archive/delete,訊息就消失;如果 Worker 崩潰或處理失敗、沒去確認,vt 到期後訊息會自動重新可見,被下一輪讀取——這就是佇列的「至少一次(at-least-once)」重試機制。

把 pgmq 與 pg_cron 組起來,就是一套完整的背景任務系統:pgmq 當收件匣存待辦訊息,pg_cron 每分鐘觸發一個 Worker 函式去 read 佇列、處理、archive。 下面實作會把這套流程完整攤開。

實作範例

這一節把監控與排程/佇列拆成可執行的步驟:① pg_stat_statements 抓慢查詢 → ② 連線/資源即時監控 SQL → ③ Prometheus/Grafana 與告警 → ④ pg_cron 定時任務 → ⑤ pgmq 佇列 + Worker。以下 SQL 可在 Studio 的 SQL Editor 或連進資料庫後執行。

一、用 pg_stat_statements 抓慢查詢

第一步先把擴充功能打開(Supabase 通常已在 shared_preload_libraries 預載,若沒有需在 postgresql.conf 加入後重啟 db 容器):

-- 啟用查詢統計擴充功能
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

接著就能找出「最花時間」的查詢。下面這條是效能調校最常用的一句 SQL——按總累積執行時間排序,揪出真正拖垮資料庫的查詢:

-- 找出最慢的前 20 條查詢(按總執行時間排序)
SELECT
  round(total_exec_time::numeric, 2)          AS total_time_ms,   -- 累積總耗時
  calls,                                                          -- 被呼叫幾次
  round(mean_exec_time::numeric, 2)           AS mean_time_ms,    -- 平均每次耗時
  round((100 * total_exec_time
        / sum(total_exec_time) OVER ())::numeric, 2) AS pct,      -- 佔總耗時百分比
  query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 20;

判讀的訣竅:不要只看「平均耗時最高」的查詢,更要看「總耗時最高」的。 一條平均只要 5ms、但一天被呼叫一百萬次的查詢,對系統的壓力遠大於一條平均 500ms、但一天只跑三次的報表查詢。pct 欄位直接告訴你「這條查詢吃掉了資料庫多少比例的時間」,最上面幾條就是你該優先優化的對象。

想進一步確認某張表是不是在做全表掃描(通常代表漏建索引),可以查 pg_stat_user_tables:

-- 找出 seq scan(全表掃描)次數偏高的資料表
SELECT
  relname          AS table_name,
  seq_scan,                        -- 全表掃描次數
  seq_tup_read,                    -- 全表掃描讀了幾列
  idx_scan                         -- 用索引掃描的次數
FROM pg_stat_user_tables
ORDER BY seq_scan DESC
LIMIT 20;

如果某張大表的 seq_scan 遠高於 idx_scan,通常就是該建索引了——特別是 RLS 政策裡拿來比對的 user_id 這種欄位。

二、即時監控連線與資源

慢查詢之外,「現在系統的即時狀態」也要能隨手查。下面幾條 SQL 是自架維運的常備工具。

連線數是自架最容易爆的資源之一(Supavisor + 各服務會吃掉不少連線),先看目前連線分布:

-- 依連線狀態統計目前連線數
SELECT
  state,
  count(*)                          AS conn_count,
  max(now() - state_change)         AS max_duration   -- 該狀態最久的一條停多久
FROM pg_stat_activity
WHERE pid <> pg_backend_pid()       -- 排除這條查詢自己
GROUP BY state
ORDER BY conn_count DESC;

如果 idle in transaction 的連線很多、又停很久,那是應用程式開了交易卻忘了收尾,會白白佔住連線,是自架常見的隱形殺手:

-- 揪出停在 idle in transaction 超過 5 分鐘的連線
SELECT pid, usename, now() - state_change AS idle_duration, query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
  AND now() - state_change > interval '5 minutes'
ORDER BY idle_duration DESC;

磁碟空間則是另一條該盯的線。查各資料表(含索引)佔用大小,提早發現異常膨脹:

-- 列出佔空間最大的前 10 張表(含索引)
SELECT
  relname AS table_name,
  pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

容器層的即時資源(CPU/記憶體/OOM),則用 Docker 指令看——這在前一篇也提過,是自架監控的基本功:

# 即時監控所有容器資源使用
docker stats

# 過濾最近一小時的錯誤日誌
docker compose logs --since 1h 2>&1 | grep -E "(ERROR|FATAL|PANIC)"

三、Prometheus/Grafana 與告警

當你要做「長期趨勢」與「自動告警」,就得把指標吐給 Prometheus。Supabase 每個實例會暴露一個 metrics endpoint,路徑約為 /customer/v1/privileged/metrics(實際路徑與認證方式請以你部署的版本與官方文件為準),回傳 Prometheus 格式的約 200 個 PostgreSQL 指標。

Prometheus 的抓取設定大致長這樣(示意,認證方式依你的部署調整):

# prometheus.yml(示意)
scrape_configs:
  - job_name: 'supabase'
    metrics_path: '/customer/v1/privileged/metrics'
    scheme: https
    basic_auth:
      username: 'service_role'
      password: 'your-service-role-key'   # 依官方文件的認證方式設定
    static_configs:
      - targets: ['supabase.yourdomain.com']

抓到指標後,重點是設對告警線。以下是自架 Supabase 最該設的幾條關鍵告警,把它們當成你的「煙霧偵測器」:

告警項目建議警戒線為什麼重要
連線數超過 max_connections 的 90%(如 200 的 180)連線耗盡後新請求全部被拒
平均查詢時間持續超過 1000ms效能劣化,通常是慢查詢或缺索引
磁碟使用率超過 80%磁碟滿了 PostgreSQL 會直接停擺
CPU 使用率持續超過 85%資源不足,需優化查詢或升級
容器重啟15 分鐘內重啟超過 2 次通常是 OOM Kill 或崩潰迴圈

Grafana 端則是把 Prometheus 當資料源,匯入或自建 PostgreSQL 儀表板,把上面這些指標畫成時序圖。若你不想一開始就上 Prometheus/Grafana 這套,至少也要接一個外部 uptime 監控(如 UptimeRobot、Better Uptime)定時打你的健康檢查端點,加上磁碟與憑證到期的告警——這是「出事有人通知」的最低門檻。

四、pg_cron:資料庫內的定時任務

接著換排程。先啟用擴充功能(Supabase 映像通常已含):

CREATE EXTENSION IF NOT EXISTS pg_cron;

建立排程任務就靠 cron.schedule。下面示範三個典型任務:

-- 每天凌晨 3 點清理過期 session
SELECT cron.schedule(
  'clean-expired-sessions',
  '0 3 * * *',
  $$DELETE FROM auth.sessions WHERE expires_at < NOW()$$
);

-- 每 15 分鐘刷新 Materialized View(把重運算結果快取起來)
SELECT cron.schedule(
  'refresh-user-stats',
  '*/15 * * * *',
  'REFRESH MATERIALIZED VIEW CONCURRENTLY public.user_stats'
);

-- 每分鐘觸發一次佇列 Worker(下一節會用到)
SELECT cron.schedule(
  'process-email-queue',
  '* * * * *',
  'SELECT public.process_email_queue()'
);

$$ ... $$ 是 PostgreSQL 的 dollar-quoting,讓你在 SQL 字串裡放單引號不必跳脫,寫 DELETE/UPDATE 這種帶條件的任務時特別方便。

排程建好後,一定要會管理與查看執行狀況——這是「cron 任務失敗有沒有告警」的關鍵:

-- 列出所有已排程任務
SELECT * FROM cron.job;

-- 查看最近的執行歷史(status 會顯示 succeeded / failed)
SELECT jobid, status, return_message, start_time, end_time
FROM cron.job_run_details
ORDER BY start_time DESC
LIMIT 20;

-- 暫停 / 刪除任務
SELECT cron.alter_job((SELECT jobid FROM cron.job WHERE jobname = 'refresh-user-stats'), active := false);
SELECT cron.unschedule('clean-expired-sessions');

一個 Docker 自架必踩的坑:如果 pg_cron 任務要透過 pg_net 呼叫 Edge Function,URL 不能用 localhost——因為在 db 容器內 localhost 指的是 db 容器自己,到不了 Kong。要用 Docker 服務名稱:

CREATE EXTENSION IF NOT EXISTS pg_net;

-- ✅ 正確:用容器服務名 kong,不是 localhost
SELECT cron.schedule(
  'trigger-edge-function',
  '*/5 * * * *',
  $$
    SELECT net.http_post(
      url := 'http://kong:8000/functions/v1/process',
      headers := jsonb_build_object(
        'Content-Type', 'application/json',
        'Authorization', 'Bearer ' || current_setting('app.service_role_key')
      ),
      body := '{"trigger": "cron"}'::jsonb
    );
  $$
);

pg_cron 有兩個限制要記住:最多同時執行 32 個任務;且不支援跨 Replica 的分散式鎖(所以任務要設計成冪等,避免重疊執行出問題)。

五、pgmq:資料庫層的訊息佇列 + Worker

最後把非同步佇列組起來。啟用擴充功能後,建佇列、送訊息:

CREATE EXTENSION IF NOT EXISTS pgmq;

-- 建立一個持久佇列
SELECT pgmq.create('email_notifications');

-- 送一筆訊息(JSON 內容)
SELECT pgmq.send(
  'email_notifications',
  '{"to": "user@example.com", "template": "welcome"}'::jsonb
);

消費端的關鍵是 read 的可見性超時與消費後的確認:

-- 讀 1 筆,鎖定 30 秒(30 秒內其他 Worker 看不到這筆)
SELECT * FROM pgmq.read('email_notifications', 30, 1);

-- 處理成功後二選一:
SELECT pgmq.archive('email_notifications', 123);  -- 歸檔(移到 archive 表,可審計)
SELECT pgmq.delete('email_notifications', 123);   -- 直接刪除(不需保留)

把讀取、處理、確認包成一個 Worker 函式,再用前面 pg_cron 的 process-email-queue 每分鐘觸發它,就是完整的背景任務流程:

CREATE OR REPLACE FUNCTION public.process_email_queue()
RETURNS void AS $$
DECLARE
  msg RECORD;
BEGIN
  -- 一次最多處理 10 筆,每筆鎖定 30 秒
  FOR msg IN SELECT * FROM pgmq.read('email_notifications', 30, 10)
  LOOP
    BEGIN
      -- 呼叫 Edge Function 實際寄信(注意用容器名 kong,不是 localhost)
      PERFORM net.http_post(
        url := 'http://kong:8000/functions/v1/send-email',
        headers := jsonb_build_object(
          'Content-Type', 'application/json',
          'Authorization', 'Bearer ' || current_setting('app.service_role_key')
        ),
        body := msg.message
      );

      -- 成功 → 歸檔
      PERFORM pgmq.archive('email_notifications', msg.msg_id);

    EXCEPTION WHEN OTHERS THEN
      -- 失敗 → 不確認,讓可見性超時到期後自動重試
      RAISE WARNING '處理訊息 % 失敗:%', msg.msg_id, SQLERRM;
    END;
  END LOOP;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

這段的設計精髓在於 EXCEPTION 區塊:成功才 archive,失敗就什麼都不做,讓那筆訊息在 vt(30 秒)到期後重新可見、下一輪再試。 這就是佇列「失敗自動重試」的本質。

最後,佇列本身也要監控。用 pgmq.metrics 看佇列長度與最舊訊息年齡,避免訊息默默積壓:

-- 查看單一佇列健康:queue_length(待處理數)、oldest_msg_age_sec(最舊訊息年齡)
SELECT * FROM pgmq.metrics('email_notifications');

如果 queue_length 一直往上、oldest_msg_age_sec 越來越大,代表 Worker 消費不過來(或一直失敗重試),該去查 Worker 的錯誤日誌了。

常見錯誤與最佳實踐

坑一:上線後從不看慢查詢。 很多人把 pg_stat_statements 打開就忘了它的存在,直到資料量長大、某條查詢卡到 API 逾時,才回頭發現有條 RLS 政策或漏建索引的查詢一直在做全表掃描。正確做法:把「看 pg_stat_statements 前二十條」排進每週例行巡檢;看到 pct 高、又是全表掃描的查詢,優先建索引或用 (SELECT auth.uid()) 優化 RLS 政策。監控的價值,在於你真的定期去看它。

坑二:cron 任務沒做冪等,失敗也沒告警。 排程任務可能因為前一次還沒跑完就重疊執行,或中途失敗。如果任務不是冪等(重跑一次會出錯或產生重複資料)、又沒人監看 cron.job_run_details,問題會默默累積成資料錯亂。正確做法:任務設計成可安全重跑——刪除類用 WHERE 條件過濾、寫入類用 ON CONFLICT ... DO UPDATE;並定期(或用另一個監控任務)檢查 cron.job_run_details 裡 status = 'failed' 的紀錄,接上告警。記住 pg_cron 沒有分散式鎖,別假設任務一定不會重疊。

坑三:pgmq 訊息讀出來卻沒 archive/delete。 這是佇列最典型的錯誤:Worker read 出訊息、也處理完了,卻忘記 archive 或 delete。結果可見性超時一到,那筆訊息又冒出來被重複處理(重複寄信、重複扣款),佇列還會越積越大。正確做法:處理成功一定要 archive(需要審計就歸檔)或 delete(不需保留就刪掉);只有處理失敗時才「不確認」,讓它自然重試。並且用 pgmq.metrics 盯住 queue_length 與 oldest_msg_age_sec,積壓就是警訊。

坑四:只靠 Studio 看當下,沒有長期趨勢與主動告警。 Studio Reports/Logs 很好用,但它是「你去看它才有用」的被動工具。磁碟在你睡覺時滿了、連線在你放假時爆了,Studio 不會叫你。正確做法:至少接一個外部 uptime 監控加資源告警;上了正式流量就接 Prometheus/Grafana,把連線數、CPU、磁碟、慢查詢、容器重啟這五條線設成告警規則,做到「出事前主動通知」。

坑五:Docker 網路內用 localhost 呼叫服務。 在 pg_cron/pgmq 的 Worker 裡用 net.http_post 打 http://localhost:8000 呼叫 Edge Function,會失敗——因為 db 容器的 localhost 是它自己,到不了 Kong。正確做法:一律用 Docker 服務名稱 http://kong:8000,並把 service_role key 用 ALTER DATABASE postgres SET app.service_role_key = '...' 存進資料庫設定,避免硬編碼。

最佳實踐總結:

  • 監控分三層:Studio Reports/Logs 巡檢、pg_stat_statements 抓慢查詢、Prometheus/Grafana 做趨勢與告警
  • 告警設對線:連線數 90%、查詢 >1s、磁碟 80%、CPU 85%、容器重啟——五條線是自架的煙霧偵測器
  • 慢查詢定期看:看總耗時(不只平均),優先優化 pct 最高又全表掃描的查詢
  • cron 任務要冪等:ON CONFLICT/WHERE 保護,並監看 cron.job_run_details 的失敗紀錄
  • pgmq 一定要確認:成功 archive/delete、失敗才重試,並用 pgmq.metrics 盯佇列長度
  • Docker 內用服務名:呼叫 Edge Function 用 http://kong:8000,不用 localhost
  • 細節以官方為準:metrics endpoint 路徑、擴充功能版本、Studio 欄位都可能隨版本調整

小結

這是 Supabase 系列教學的第 045 篇,也是自架段(SB-5)的第三篇。上一篇《備份、升級與上線檢查》教你把自架 Supabase 的維運三支柱做齊——備份、還原演練、安全升級與上線清單;這一篇補上了最後兩塊拼圖:看得住(監控) 與 跑得動(排程與佇列)。

核心觀念濃縮成一句話:監控要分三層做——Studio Reports/Logs 日常巡檢、pg_stat_statements 抓慢查詢、Prometheus/Grafana 對連線/CPU/磁碟/慢查詢/容器重啟設告警;而 pg_cron 讓你用 cron.schedule 在資料庫內排定時 SQL 任務、pgmq 讓你用 send/read/archive 把 PostgreSQL 當訊息佇列,兩者搭起來就能在資料庫層做完整的非同步背景任務,少養一個要維運的元件。

  • 監控三層:內建儀表(Reports/Logs)→ 資料庫內部(pg_stat_statements)→ 外接可觀測性(Prometheus/Grafana),由淺到深
  • 關鍵告警:連線數、查詢時間、磁碟、CPU、容器重啟——出事前主動通知,而不是等使用者回報
  • pg_cron:cron.schedule 排程、cron.job_run_details 看歷史;任務要冪等、Docker 內用服務名
  • pgmq:create/send/read/archive/delete 的佇列生命週期,靠可見性超時做失敗重試,搭 pg_cron 組 Worker

到這裡,你的自架 Supabase 已經能「架起來、養得好、看得住、跑得動」了。自架段走到監控與擴充功能,技術面的維運能力已經齊備。下一篇《最佳實踐與反模式》,我們會把整個 Supabase 系列橫跨資料庫、Auth、Storage、Realtime、Edge Functions 到自架的關鍵原則收斂成一份可對照的「該做 vs 別做」總表,幫你把散落各篇的最佳實踐串成一套完整的心智檢查清單。把該做的變成習慣、把反模式變成警訊,才是讓 Supabase 專案長期健康的最後一哩路。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →