このチュートリアルでは、Cloudflare Pipelines、R2 Data Catalog、R2 SQL を使って、一連のデータパイプラインを構築します。不正パターンを含む金融トランザクションデータを作成し、Pipeline へ送るサンプル Python スクリプトも含みます。送ったデータは、R2 SQL または任意の Apache Iceberg 互換クエリエンジンでクエリできます。
このチュートリアルでは、次を行います。
- R2 Data Catalog をセットアップし、トランザクションイベントを Apache Iceberg テーブルに保存する
- Cloudflare Pipeline をセットアップする
- 不正パターンを含むトランザクションデータを作成し、Pipeline へ送る
- 不正分析のために R2 SQL でデータをクエリする
- Cloudflare アカウント ↗ に登録します。
- Wrangler がサポートするバージョンの Node.js をインストールします。
- データ生成スクリプト用に Python 3.8+ ↗ をインストールします。
Cloudflare の各サービスを操作するには、API トークンが必要です。
-
Cloudflare ダッシュボードで API tokens ページを開きます。
Account API tokens を開く ↗ -
Create Token を選びます。
-
Create Custom Token の横にある Get started を選びます。
-
API トークンの名前を入力します。
-
Permissions で、次を選びます。
- Workers Pipelines に Read、Send、Edit の権限
- Workers R2 Data Catalog に Read と Edit の権限
- Workers R2 SQL に Read の権限
- Workers R2 Storage に Read と Edit の権限
-
任意で、このトークンに TTL を追加します。
-
Continue to summary を選びます。
-
Create Token を選びます。
-
Token value を控えます。
新しいトークンを環境変数としてエクスポートします。
export WRANGLER_R2_SQL_AUTH_TOKEN= #paste your token hereWrangler を初めて使う場合は、ログインしてください。
npx wrangler loginR2 バケットを作成します。
npx wrangler r2 bucket create fraud-pipeline-
Cloudflare ダッシュボードで R2 object storage ページを開きます。
Overview を開く ↗ -
Create bucket を選びます。
-
バケット名を入力します:
fraud-pipeline -
Create bucket を選びます。
R2 バケットでカタログを有効にします。
npx wrangler r2 bucket catalog enable fraud-pipelineこのコマンドを実行したら、「Warehouse」と「Catalog URI」を控えてください。あとで使います。
-
Cloudflare ダッシュボードで R2 object storage ページを開きます。
Overview を開く ↗ -
バケット
fraud-pipelineを選びます。 -
Settings タブに切り替え、R2 Data Catalog までスクロールし、Enable を選びます。
-
有効にしたら、Catalog URI と Warehouse name を控えます。
export WAREHOUSE= #Paste your warehouse hereR2 Data Catalog は、テーブルのコンパクションを自動で行えます。本番のイベントストリーミングでは小さなファイルがたくさん残ることが多いため、コンパクションの有効化を推奨します。このチュートリアルはサンプル用途のため、この手順は任意です。
npx wrangler r2 bucket catalog compaction enable fraud-pipeline --token $WRANGLER_R2_SQL_AUTH_TOKEN-
Cloudflare ダッシュボードで R2 object storage ページを開きます。
Overview を開く ↗ -
バケット
fraud-pipelineを選びます。 -
Settings タブに切り替え、R2 Data Catalog までスクロールし、編集アイコンをクリックして Enable を選びます。
-
ターゲットのファイルサイズを選ぶか、デフォルトのままにします。保存します。
まず、次の json スキーマで raw_transactions_schema.json というスキーマファイルを作成します。
{
"fields": [
{ "name": "transaction_id", "type": "string", "required": true },
{ "name": "user_id", "type": "int64", "required": true },
{ "name": "amount", "type": "float64", "required": false },
{ "name": "transaction_timestamp", "type": "string", "required": false },
{ "name": "location", "type": "string", "required": false },
{ "name": "merchant_category", "type": "string", "required": false },
{ "name": "is_fraud", "type": "bool", "required": false }
]
}不正検知イベントを受け取る stream を作成します。
npx wrangler pipelines streams create raw_events_stream \
--schema-file raw_transactions_schema.json \
--http-enabled true \
--http-auth false# The http ingest endpoint from the output (see example below)
export STREAM_ENDPOINT= #the http ingest endpoint from the output (see example below)出力は次のようになります。
🌀 Creating stream 'raw_events_stream'...
✨ Successfully created stream 'raw_events_stream' with id 'stream_id'.
Creation Summary:
General:
Name: raw_events_stream
HTTP Ingest:
Enabled: Yes
Authentication: Yes
Endpoint: https://stream_id.ingest.cloudflare.com
CORS Origins: None
Input Schema:
┌───────────────────────┬────────┬────────────┬──────────┐
│ Field Name │ Type │ Unit/Items │ Required │
├───────────────────────┼────────┼────────────┼──────────┤
│ transaction_id │ string │ │ Yes │
├───────────────────────┼────────┼────────────┼──────────┤
│ user_id │ int64 │ │ Yes │
├───────────────────────┼────────┼────────────┼──────────┤
│ amount │float64 │ │ No │
├───────────────────────┼────────┼────────────┼──────────┤
│ transaction_timestamp │ string │ │ No │
├───────────────────────┼────────┼────────────┼──────────┤
│ location │ string │ │ No │
├───────────────────────┼────────┼────────────┼──────────┤
│ merchant_category │ string │ │ No │
├───────────────────────┼────────┼────────────┼──────────┤
│ is_fraud │ bool │ │ No │
└───────────────────────┴────────┴────────────┴──────────┘データを Apache Iceberg テーブルとして R2 バケットへ書き込む sink を作成します。
npx wrangler pipelines sinks create raw_events_sink \
--type "r2-data-catalog" \
--bucket "fraud-pipeline" \
--roll-interval 30 \
--namespace "fraud_detection" \
--table "transactions" \
--catalog-token $WRANGLER_R2_SQL_AUTH_TOKENSQL で stream と sink を接続します。
npx wrangler pipelines create raw_events_pipeline \
--sql "INSERT INTO raw_events_sink SELECT * FROM raw_events_stream"-
Cloudflare ダッシュボードで Pipelines > Pipelines を開きます。
Pipelines を開く ↗ -
Create Pipeline を選びます。
-
Connect to a Stream:
- Pipeline name:
raw_events - Enable HTTP endpoint for sending data: Enabled
- HTTP authentication: Disabled(デフォルト)
- Next を選びます
- Pipeline name:
-
Define Input Schema:
-
JSON editor を選びます
-
次のスキーマをコピーします。
{ "fields": [ { "name": "transaction_id", "type": "string", "required": true }, { "name": "user_id", "type": "int64", "required": true }, { "name": "amount", "type": "float64", "required": false }, { "name": "transaction_timestamp", "type": "string", "required": false }, { "name": "location", "type": "string", "required": false }, { "name": "merchant_category", "type": "string", "required": false }, { "name": "is_fraud", "type": "bool", "required": false } ] } -
Next を選びます
-
-
Define Sink:
- R2 バケットを選びます:
fraud-pipeline - Storage type: R2 Data Catalog
- Namespace:
fraud_detection - Table name:
transactions - Advanced Settings: Maximum Time Interval を
30 secondsに変更します - Next を選びます
- R2 バケットを選びます:
-
Credentials:
- Automatically create an Account API token for your sink を無効にします
- 手順 1 の Catalog Token を入力します
- Next を選びます
-
Pipeline Definition:
- デフォルトの SQL クエリのままにします。
INSERT INTO raw_events_sink SELECT * FROM raw_events_stream; - Create Pipeline を選びます
- デフォルトの SQL クエリのままにします。
-
パイプライン作成後、次の手順用に Stream ID を控えます。
不正パターンを含む現実的なトランザクションデータを生成する Python スクリプトを作成します。
import requests
import json
import uuid
import random
import time
import os
from datetime import datetime, timezone, timedelta
# Configuration - exported from the prior steps
STREAM_ENDPOINT = os.environ["STREAM_ENDPOINT"]# From the stream you created
API_TOKEN = os.environ["WRANGLER_R2_SQL_AUTH_TOKEN"] #the same one created earlier
EVENTS_TO_SEND = 1000 # Feel free to adjust this
def generate_transaction():
"""Generate some random transactions with occasional fraud"""
# User IDs
high_risk_users = [1001, 1002, 1003, 1004, 1005]
normal_users = list(range(1006, 2000))
user_id = random.choice(high_risk_users + normal_users)
is_high_risk_user = user_id in high_risk_users
# Generate amounts
if random.random() < 0.05:
amount = round(random.uniform(5000, 50000), 2)
elif random.random() < 0.03:
amount = round(random.uniform(0.01, 1.00), 2)
else:
amount = round(random.uniform(10, 500), 2)
# Locations
normal_locations = ["NEW_YORK", "LOS_ANGELES", "CHICAGO", "MIAMI", "SEATTLE", "SAN FRANCISCO"]
high_risk_locations = ["UNKNOWN_LOCATION", "VPN_EXIT", "MARS", "BAT_CAVE"]
if is_high_risk_user and random.random() < 0.3:
location = random.choice(high_risk_locations)
else:
location = random.choice(normal_locations)
# Merchant categories
normal_merchants = ["GROCERY", "GAS_STATION", "RESTAURANT", "RETAIL"]
high_risk_merchants = ["GAMBLING", "CRYPTO", "MONEY_TRANSFER", "GIFT_CARDS"]
if random.random() < 0.1: # 10% high-risk merchants
merchant_category = random.choice(high_risk_merchants)
else:
merchant_category = random.choice(normal_merchants)
# Series of checks to either increase fraud score by a certain margin
fraud_score = 0
if amount > 2000: fraud_score += 0.4
if amount < 1: fraud_score += 0.3
if location in high_risk_locations: fraud_score += 0.5
if merchant_category in high_risk_merchants: fraud_score += 0.3
if is_high_risk_user: fraud_score += 0.2
# Compare the fraud scores
is_fraud = random.random() < min(fraud_score * 0.3, 0.8)
# Generate timestamps (some fraud happens at unusual hours)
base_time = datetime.now(timezone.utc)
if is_fraud and random.random() < 0.4: # 40% of fraud at night
hour = random.randint(0, 5) # Late night/early morning
transaction_time = base_time.replace(hour=hour)
else:
transaction_time = base_time - timedelta(
hours=random.randint(0, 168) # Last week
)
return {
"transaction_id": str(uuid.uuid4()),
"user_id": user_id,
"amount": amount,
"transaction_timestamp": transaction_time.isoformat(),
"location": location,
"merchant_category": merchant_category,
"is_fraud": True if is_fraud else False
}
def send_batch_to_stream(events, batch_size=100):
"""Send events to Cloudflare Stream in batches"""
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
total_sent = 0
fraud_count = 0
for i in range(0, len(events), batch_size):
batch = events[i:i + batch_size]
fraud_in_batch = sum(1 for event in batch if event["is_fraud"] == True)
try:
response = requests.post(STREAM_ENDPOINT, headers=headers, json=batch)
if response.status_code in [200, 201]:
total_sent += len(batch)
fraud_count += fraud_in_batch
print(f"Sent batch of {len(batch)} events (Total: {total_sent})")
else:
print(f"Failed to send batch: {response.status_code} - {response.text}")
except Exception as e:
print(f"Error sending batch: {e}")
time.sleep(0.1)
return total_sent, fraud_count
def main():
print("Generating fraud detection data...")
# Generate events
events = []
for i in range(EVENTS_TO_SEND):
events.append(generate_transaction())
if (i + 1) % 100 == 0:
print(f"Generated {i + 1} events...")
fraud_events = sum(1 for event in events if event["is_fraud"] == True)
print(f"📊 Generated {len(events)} total events ({fraud_events} fraud, {fraud_events/len(events)*100:.1f}%)")
# Send to stream
print("Sending data to Pipeline stream...")
sent, fraud_sent = send_batch_to_stream(events)
print(f"\nComplete!")
print(f" Events sent: {sent:,}")
print(f" Fraud events: {fraud_sent:,} ({fraud_sent/sent*100:.1f}%)")
print(f" Data is now flowing through your pipeline!")
if __name__ == "__main__":
main()必要な Python 依存関係をインストールし、スクリプトを実行します。
pip install requests
python fraud_data_generator.pyR2 SQL で不正検知データを分析できます。次はクエリの例です。
npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
transaction_id,
user_id,
amount,
location,
merchant_category,
is_fraud,
transaction_timestamp
FROM fraud_detection.transactions
WHERE __ingest_ts > '2025-09-24T01:00:00Z'
AND is_fraud = true
LIMIT 10"絞り込んだデータを、R2 Data Catalog の新しい Apache Iceberg テーブルへ書き込む sink を作成します。
npx wrangler pipelines sinks create fraud_filter_sink \
--type "r2-data-catalog" \
--bucket "fraud-pipeline" \
--roll-interval 30 \
--namespace "fraud_detection" \
--table "fraud_transactions" \
--catalog-token $WRANGLER_R2_SQL_AUTH_TOKEN次に、元の raw_events_stream からデータを処理し、amount が 1,000 を超えるフラグ付きトランザクションだけを書き込む新しい SQL クエリを作成します。
npx wrangler pipelines create fraud_events_pipeline \
--sql "INSERT INTO fraud_filter_sink SELECT * FROM raw_events_stream WHERE is_fraud=true and amount > 1000"テーブルをクエリして結果を確認します。
npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
transaction_id,
user_id,
amount,
location,
merchant_category,
is_fraud,
transaction_timestamp
FROM fraud_detection.fraud_transactions
LIMIT 10"不正ではないイベントが除外されていることも確認します。
npx wrangler r2 sql query "$WAREHOUSE" "
SELECT
transaction_id,
user_id,
amount,
location,
merchant_category,
is_fraud,
transaction_timestamp
FROM fraud_detection.fraud_transactions
WHERE is_fraud = false
LIMIT 10"次の出力になるはずです。
Query executed successfully with no resultsCloudflare のデータプラットフォームを使い、エンドツーエンドのデータパイプラインを構築できました。このチュートリアルでは、次を学びました。
- R2 Data Catalog を使う: Apache Iceberg テーブルで、データを効率よく保存します
- Cloudflare Pipelines をセットアップする: データ取り込み用の stream、sink、pipeline を作成します
- サンプルデータを生成する: 基本的な不正パターンを含むトランザクションデータを作成します
- R2 SQL でテーブルをクエリする: R2 Data Catalog に保存した生データと加工済みデータのテーブルにアクセスします