Article

ワークフローシステムで承認速度を5倍にする方法

高田晃太郎
ワークフローシステムで承認速度を5倍にする方法

社内承認の待ち時間は業務プロセス全体の大半を占めやすく、公開事例ではデジタル化だけで30〜90%のサイクル短縮が報告されています。¹³各種の公開事例やベンダー資料を俯瞰すると、紙やメール主導の稟議は平均リードタイムが3〜10営業日にばらつく一方、設計を見直したワークフローでは、P50(中央値)が1営業日以内、P95(95%の案件がこの時間以内に完了)の目安が24〜48時間程度に収束する例がしばしば見られます。つまり、単にツールを導入するだけでなく、承認の設計原則と実装パターンを押さえれば、状況次第では「最大で5倍程度の速度向上」を狙える可能性があるということです。⁴

ポイントは、専門用語に頼らずに考えると理解が早まることです。承認の遅さは「人が遅い」からではなく、「直列化」「不必要な承認」「手戻り」「可視化不足」という設計の問題から生まれます。ここを分解し、並列化と自動化、SLA(Service Level Agreement: 目標応答時間)の設定とエスカレーション、ポリシー・アズ・コード(承認ルールをコード化して一貫性を担保)による統制、そして計測運用で閉じることが、大幅な短縮に直結します。

なぜ承認は遅くなるのかを構造で捉える

承認が遅い現場では、依頼が1列の行列になり、判断材料が不足したまま上位に送られ、差し戻しで往復が増えます。リトルの法則(平均処理時間 ≒ 仕掛品量WIP ÷ スループット)で見ると、WIPが多い直列プロセスはそれだけで遅くなります。²さらに、承認者の選定が曖昧だと誤ルーティングが発生し、往復回数が増えて実時間を侵食します。

メール稟議については、一般的なメール応答時間の調査(勤務時間帯平均約3時間25分)と整合するかたちで、就業時間中でも平均応答が数時間、休前日をまたぐと18〜36時間の停滞が発生しやすいという報告が多く、P95の尾(遅い方の案件)がこの「待ち」によって長引く傾向が指摘されています。⁶業種をまたいで観察されるパターンで、承認そのものの思考時間よりも搬送と待ちが支配的になりやすい。したがって、設計で待ちを潰すのが王道です。

直列から条件付き並列へ切り替える意味

多段承認は安心感を与えますが、価値を生まない待ちを増やします。金額やリスクが独立条件なら、一次審査(完全性チェック)と二次審査(リスク判断)を並列に流し、最後に軽い整合チェックだけ直列に残す方が合理的です。並列化だけで「ステージ数 × 稼働時間」の積が縮むため、結果として主要な指標で差が出やすくなります。⁴

「誰が承認するか」をコード化する

承認者選定を人に依存すると、属人化と誤ルーティングが避けられません。職務権限規程や金額テーブル、地域・法規制の例外をポリシー・アズ・コードで表現しておけば、変更はPull Requestで管理でき、監査証跡も残ります。これにより差し戻し回数とやり直し時間を削減できます。⁵

5倍を実現するワークフロー設計原則

短縮のカギは、入力の完全性を入口で自動検証し、条件付きで並列化し、SLAで待ちを強制的に動かし、承認そのものをポリシー化で自動承認に置き換えることです。加えて、失敗に強い非同期実装でスパイク時も滞留しないようにします。ここからは実装と具体例を交えます。

Temporal/Camunda等による並列・タイムアウト制御

イベントドリブンのオーケストレーション(ワークフローエンジン)を用いると、並列化、タイマー、タイムアウト、再試行、補償処理をコードで表現できます。⁷次はTemporalのTypeScriptワークフローの例です。一次審査とリスク審査を並列に投げ、SLA超過でエスカレーションする構成を示します。

// temporal/workflows/approval.ts
import { proxyActivities, defineSignal, setHandler, sleep } from '@temporalio/workflow';
import type { Activities } from '../activities';

const { validateCompleteness, riskAssess, notifyEscalation, finalize } = proxyActivities<Activities>({
  startToCloseTimeout: '5 minutes'
});

export interface ApprovalInput { id: string; amount: number; requester: string; }
const approveSignal = defineSignal<['approver', 'comment']>('approve');

export async function approvalWorkflow(input: ApprovalInput) {
  let approved = false;
  setHandler(approveSignal, () => { approved = true; });

  const validation = validateCompleteness(input);
  const risk = riskAssess(input);

  const slaMs = input.amount > 1000000 ? 12 * 60 * 60 * 1000 : 4 * 60 * 60 * 1000; // SLA by amount
  const escTimer = sleep(slaMs);

  const [v] = await Promise.all([validation, risk]);
  if (!v.ok) throw new Error('incomplete payload');

  const winner = await Promise.race([
    (async () => { while (!approved) await sleep(1000); return 'approved'; })(),
    (async () => { await escTimer; await notifyEscalation(input.id); return 'escalated'; })()
  ]);

  await finalize({ id: input.id, status: winner });
}

このパターンでは、内製・法務・財務のチェックを同時進行でき、SLAタイマーで停滞を可視化し、期限で自動通知されます。公開事例では、直列三段のプロセスを並列化とタイマー導入で見直すことで、平均が数日から1日以内のレンジに縮んだと紹介されることがあります。⁴

承認ルールをRegoで表現し、自動承認を増やす

OPA(Open Policy Agent)を使えば、金額やカテゴリ、サプライヤ評価などの条件をコードで定義できます。低リスク案件を自動承認に寄せると、人手承認が減り、上位のボトルネックが解消しやすくなります。⁵

# policy/approval.rego
package approval

default require_manual = true

low_risk { input.amount <= 500000; input.category == "office"; input.vendor_score >= 80 }
internal_budget { input.cost_center == "IT"; input.amount <= 2000000 }

require_manual = false { low_risk }
require_manual = false { internal_budget; input.sox_scope == false }

このポリシーを検証済みのテストと一緒にバージョン管理します。リリースごとに回帰テストを通せば、監査対応も容易です。公開されている複数の事例を俯瞰すると、自動承認比率が2〜6割程度まで高まると、人依存の待ちが顕著に減り、結果として中央値や長い尾の圧縮が期待できます。

正しいデータモデルとインデックスで滞留を防ぐ

滞留の多くはDB設計の粗さにも起因します。状態遷移とSLAを高速に引けるスキーマにし、未処理のキーセットを効率良く取得できる設計にします。

CREATE TABLE approvals (
  id BIGSERIAL PRIMARY KEY,
  business_id TEXT NOT NULL,
  amount BIGINT NOT NULL,
  state TEXT NOT NULL CHECK (state IN ('PENDING','APPROVED','REJECTED','ESCALATED')),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  sla_deadline TIMESTAMPTZ NOT NULL,
  approver_hint TEXT,
  etag TEXT NOT NULL
);

CREATE INDEX idx_approvals_sla ON approvals (state, sla_deadline);
CREATE INDEX idx_approvals_business ON approvals (business_id);

この構造なら、期限超過の検出とエスカレーションの走査が高速になります。さらに、ETagによる楽観的排他(同時更新を安全に弾く仕組み)を採用し、重複承認や競合を抑えます。

可用性と一貫性のためのアウトボックス+冪等性

承認は通知・会計・在庫などに連鎖するため、イベント配信の一貫性が重要です。アウトボックスパターン(トランザクション内に送信予定イベントを記録してから配信)と冪等性キー(同じイベントを重ねても副作用が増えない制御)で、配信の重複や取りこぼしに耐性を持たせます。

// Kafka consumer with idempotency and outbox
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.springframework.transaction.annotation.Transactional;

@Transactional
public void onApprovalEvent(ConsumerRecord<String, String> record) {
  String key = record.key();
  if (processedKeysRepository.exists(key)) return; // idempotent
  ApprovalEvent evt = parse(record.value());
  accountingService.book(evt);
  inventoryService.reserve(evt);
  processedKeysRepository.save(key);
}

この実装により、障害時の再配信でも副作用が安定します。スパイク時のバックプレッシャもキューで吸収でき、ピーク時の滞留を抑えられます。

フロントの応答性と安全性を両立するAPI

ユーザ操作は即時応答しつつ、競合と二重送信を防ぐ必要があります。ETagとIf-Match、リトライセーフな設計を意識します。

// Node.js Express: approve endpoint with optimistic concurrency
import express from 'express';
import { db } from './db';
const app = express();

app.post('/approvals/:id/approve', async (req, res) => {
  const id = req.params.id;
  const etag = req.header('If-Match');
  try {
    const r = await db.query(
      'UPDATE approvals SET state = $1, updated_at = now() WHERE id = $2 AND etag = $3 RETURNING etag',
      ['APPROVED', id, etag]
    );
    if (r.rowCount === 0) return res.status(412).send('Precondition Failed');
    res.status(200).send('OK');
  } catch (e) {
    res.status(500).send('ERROR');
  }
});

現場では、承認画面をモバイルに対応させ、プッシュ通知でSLA内の反応率を高めると効果が出やすく、業務時間外のボトルネックを小さくできます。³

計測と運用でスピードを固める

仕組みは入れた瞬間が最速ではありません。ダッシュボードでリードタイムを分解して監視し、ボトルネックを潰し続けることが大切です。特に、P50とP95、各ステージの滞留、エスカレーション率、差し戻し率を追い、施策ごとに改善効果を記録します。

PrometheusでSLI/SLOを可視化する

承認SLOを時間で定義し、違反検知と自動アラートを構成します。次のメトリクスは、承認の待ちと処理時間を分けて観測するための一例です。

# counters and histograms for approvals
approval_created_total{flow="purchase"}
approval_completed_total{flow="purchase",status="APPROVED"}
approval_wait_seconds_bucket{stage="review"}
approval_process_seconds_bucket{stage="review"}

通知は業務チャットに流し、エスカレーションと同一チャンネルで扱うと現場での行動につながります。実務では、SLO違反検知から迅速に再割当する運用が、P95の長い尾を圧縮するのに有効とされます。

ダッシュボードのKPI構成と意志決定

経営と現場で見る指標を分けます。経営は全体のリードタイム、処理量、エスカレーション率、差し戻し率、金額帯別のP95を重視し、現場はステージ別の処理時間、待ち時間、担当者別WIP、期限超過件数に焦点を当てます。施策を打つ際は、ベースラインの数値を確定させ、変更差分を公開します。可視化と公開のサイクル自体が、ボトルネックを生みづらい文化を育てます。

事例で学ぶ5倍化の現実解

以下は、公開事例でしばしば報告されるパターンを踏まえた「モデルケース」です。メールとExcelの直列三段が主流だった稟議に対し、入口の入力チェックと証憑自動抽出、リスク審査の並列化、OPAの自動承認、SLA12時間で一次エスカレーション・24時間で上位代行の段取りを組み、モバイルのワンタップ承認を併用します。こうした構成では、P50が半日〜1日台、P95が1〜2日台に収まるレンジへ改善するケースが報告されています。寄与の大きい要素は並列化と自動承認で、手戻し率も二桁から一桁台へ下がりやすいのが特徴です。

別のモデルケースとして、承認者の割当が属人的で誤ルーティングが頻発していた状況に、職務権限のコード化と例外ルールの整備、エビデンス自動添付の標準化を組み合わせると、誤ルーティングが大幅に減少し、差し戻し由来の待ちがほぼ消滅します。いずれも「単発のテクニック」ではなく、入口・流れ・出口の一貫した設計が効いています。

落とし穴と対策

承認速度だけを追うと、品質やコンプライアンスが犠牲になる懸念があります。ここで効くのが、ルールのテスト自動化と監査証跡の自動保存です。RegoのユニットテストをCIで回し、ポリシー変更の差分とテスト結果をPull Requestで可視化すれば、スピードと統制を同時に満たせます。もう一つの落とし穴は、人の心理的負担です。承認者が「最後の砦」だと感じると、遅延が発生します。自動承認と並列化で案件の難易度分布を平準化し、難件だけに集中してもらう設計にすれば、心理的安全性が上がり、結果として速度も安定します。

導入プロジェクトの進め方とROIの出し方

計画はシンプルで十分です。まず、現行の承認フローをイベントログとして抽出し、ステージごとのP50/P95を確定させます。次に、入口の完全性チェックと自動承認のポリシーから着手し、並列化とSLAエスカレーションをワークフローエンジンで表現します。移行は段階的に、金額やリスクの低い領域から広げます。

ROIは、サイクル短縮によるキャッシュコンバージョンサイクル改善、人件費の再配置、機会損失の減少で示せます。簡単な試算として、月間1000件・平均工数30分/件の承認で、自動承認を4割まで高め、残りの人手承認を並列化などで半減できれば、月間で数百時間規模の削減が見込めます。短縮されたリードタイムが売上計上や発注着手を早める効果は、部門をまたぐ指標として共有すると合意形成が早まります。

最後にもうひとつのコード例: 監査証跡の自動化

承認の透明性を高めるには、すべての状態遷移とポリシー決定理由を一箇所に残します。次のような簡易的な監査ログの保存は、後日の説明責任を支えます。

CREATE TABLE approval_audits (
  id BIGSERIAL PRIMARY KEY,
  approval_id BIGINT NOT NULL,
  actor TEXT NOT NULL,
  action TEXT NOT NULL,
  reason JSONB,
  occurred_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

フロントからは、承認・却下の理由とポリシー評価結果をそのままJSONで投入します。後からBIで分析すれば、どの条件がボトルネックかも掴みやすくなります。

まとめ: 速度は設計で作れるし、測定で守れる

承認の速度は、個人の努力ではなく、プロセス設計と実装で決まります。入口で完全性を自動検証し、条件付きで並列化し、SLAで待ちを動かし、ポリシー・アズ・コードで自動承認を広げ、イベント駆動で失敗に強い配信を確保する。これらをダッシュボードで継続的に測り、P50とP95の尾を管理すれば、状況によっては数倍の短縮も十分に狙えます。

あなたの現場では、最初にどの待ちを潰せばインパクトが最大でしょうか。まずは今週、トップ3の遅延ステージを可視化し、1つだけ施策を入れて効果を測ることから始めませんか。実装と運用の両輪で回せば、数字は嘘をつきません。このメディアの他記事も参考に、次の一歩を小さく速く踏み出してみてください。

参考文献

  1. 経済産業省ジャーナル(METI Journal): https://journal.meti.go.jp/p/26409/
  2. ニッセイ基礎研究所「リトルの法則に関する解説」: https://www.nli-research.co.jp/report/detail/id%3D53307
  3. NTT東日本ビジネス公式「ワークフロー承認のデジタル化」: https://business.ntt-east.co.jp/content/digital-work/column/workflow-approval
  4. 日立ソリューションズ東日本 コラム「デザインレビューの課題解決3『ワークフローで一気に承認!』」: https://www.hitachi-solutions-east.co.jp/products/synviz_s2/column2/vol02/index.html
  5. COEL manageブログ「ワークフロー自動化」: https://manage.coel-inc.jp/blog/workflow-automation/
  6. Affde: How to find your average email response time(EmailAnalytics調査の紹介): https://www.affde.com/ja/how-to-find-your-average-email-response-time-and-your-employees.html
  7. J-STAGE(電気学会論文誌E等、ワークフロー/システム工学関連): https://www.jstage.jst.go.jp/article/ieejeiss1987/120/7/120_7_1043/_article/-char/ja/