
Sat Sep 05 2026

Merhaba! 👋
Önce kendimi tanıyalım: ben tek başıma bir SaaS projesini geliştirip, dağıtıp, canlıda tutan bir geliştiriciyim. Evet, sadece ben — backend, frontend, infrastructure, CI/CD, monitoring… hepsi benim masamda.
Hikaye şöyle başladı: mikroservis diye bir hayal kurdum. "Her servis kendi reposunda, bağımsız deploy, temiz ayrım" diye düşündüm. Sonra gerçeklik kapıyı çaldı:
Bunun için bir "strateji" yoktu. Sadece acil ihtiyaçlar, bug fix'leri, "yarın canlıya almalıyız" anları vardı. Her push'ta "bu seferlik" diyordum, ama o "bu seferlik" birikti gitti.
| Depo | Sürüm Sayısı | Ana Sebep |
|---|---|---|
api |
18 | Breaking change'ler, migration'lar |
worker |
9 | Kuyruk yapısı değişti, retry mantığı |
web |
10 | UI revizyonları, performans |
mobile |
5 | Store onayı, push sertifikaları |
Toplam: 42 — ve hepsi manuel koordinasyonla.
Bu seride somut verilerle anlatacağım:
Hazırsan gerçek masraflar ve çözüm yolları üzerine dalışa geçelim. İlk durağumuz: maliyet analizi — çünkü para konuşurken herkes dinler. 💸
Hadi başlayalım! 🚀
Hadi dürüst olalım: tek bir ajan çalıştırıyorsan her şey yolunda gidiyor gibi duruyor. Ama production'da 5-10 ajan aynı anda koşmaya başladığında fatura gelip ağzınız açık kalıyor 😅
Ben de yaşadım, siz de yaşıyorsunuzdur. Nedenler bunlar:
Senaryo: Bir "research ajan" web arıyor, bulduklarını "summary ajan"a veriyor, o da "report ajan"a besliyor. Her ajan kendi system prompt'unu, conversation history'sini ve output'u token olarak hesaplıyor.
Research Ajan: ~2.500 token (system + user + tool calls + output)
Summary Ajan: ~1.800 token (context + output)
Report Ajan: ~3.200 token (full context + formatted output)
───────────────────────────────────────────────────────
Toplam: ~7.500 token / tek bir workflow koşumu
Ne oluyor burada? Ajanlar arası context passing her seferinde baştan başlıyormuş gibi token yiyor. Shared memory yoksa her ajan "ben kimim, ne yapıyorum?" diye system prompt'unu yeniden yiyor.
💡 Gerçek hayat: Haftada 500 workflow koşuyorsanız → ~3.75M token/ay. GPT-4o pricing ile bu ~$150-200/ay sadece token maliyeti.
Anektot: Geçen hafta bir müşterimizde "code review ajan"ı "security ajan"ına PR diff'ini veriyordu. Security ajan 8K token'lık diff'i alıp, kendi 128K context window'una sığdırıyormuş gibi davranıyordu. Sonuç? Orta kısım kesilmiş, kritik bir SQL injection kaçırmıştı.
Sorunlar:
Tek ajan varken: print(log) → sorun belli.
Paralel ajan varken:
graph LR
A[Orchestrator] --> B[Research Ajan]
A --> C[Analysis Ajan]
A --> D[Writer Ajan]
B --> E[Tool: Web Search]
C --> F[Tool: Code Exec]
D --> G[Tool: File Write]
Ne oluyor?
🛠 İpucu: LangSmith, Langfuse veya custom OpenTelemetry instrumentation olmadan production'a koymayın. "Benim loglarım yeterli" demezseniz kurtarsınız.
| Bileşen | Tek Ajan | 10 Paralel Ajan |
|---|---|---|
| API Latency | ~2-3s | ~15-30s (fan-out/fan-in) |
| Concurrent Connections | 1-2 | 50-100+ |
| Memory/Process | ~200MB | ~2-4GB (context caching) |
| Rate Limit Risk | Düşük | Yüksek (burst → 429 hataları) |
| Retry/Backoff Logic | Basit | Karmaşık (partial failure handling) |
Gerçek senaryo: Black Friday trafiğinde 100 concurrent workflow → her biri 10 ajan → 1000 eşzamanlı LLM isteği. Provider rate limit'iniz 500 RPM ise → yarısı failover'a düşer, retry storm başlar, maliyet 3x olur.
| Maliyet Kalemi | Görünür mü? | Etki |
|---|---|---|
| Token çarpanlığı (context passing) | ❌ Gizli | Yüksek |
| Context window kırpma / yeniden işleme | ❌ Gizli | Orta-Yüksek |
| Debug/observability saatleri | ✅ Görünür | Çok Yüksek (insan maliyeti) |
| Infra scale-up (burst handling) | ❌ Gizli | Orta |
| Rate limit retry storm | ❌ Gizli | Yüksek |
Hazırsan bir sonraki bölümde bu maliyetleri nasıl ölçüp, optimize edip, kontrol altına alabileceğimizi konuşalım 🎯
Hazırsan bu yolculuğun içinden geçelim 🚀
42 sürüm — evet, 42 — içinde ne olduğunu, nasıl ölçtük ve neler değişti adım adım anlatayım.
Her sürümde şu döngüyü tekrarladık:
Bu akış şöyle bir diyagram gibi düşünülebilir:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
│ Prompt │────▶│ Model │────▶│ Doğrulama │────▶│ Metrik Yaz │
│ Hazırla │ │ Çağır + Log │ │ + Debug Ölç │ │ (JSONL) │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘
▲ │
│ ▼
┌──────────────┐ ┌─────────────┐
│ Context │ │ Hata varsa │
│ Yönetimi │ │ Döngüye │
│ (chunk/sum) │ │ Geri Dön │
└──────────────┘ └─────────────┘
| Sürüm Aralığı | Ortalama Token (in/out) | Context Taşması | Ort. Debug Süresi | Strateji Değişikliği |
|---|---|---|---|---|
| v1–v5 | 2.1k / 1.8k | 4/5 | 12 dk | Temel prompt, chunk yok |
| v6–v15 | 3.4k / 2.1k | 2/10 | 7 dk | Sliding window eklendi |
| v16–v25 | 4.2k / 2.5k | 1/10 | 4 dk | Özetleme (summarizer) devreye girdi |
| v26–v35 | 5.1k / 2.8k | 0/10 | 2 dk | Dinamik context budget |
| v36–v42 | 5.8k / 3.0k | 0/7 | 1.5 dk | Adaptive token allocation ✅ |
Ne oluyor burada?
Şu scripti her sürüm çalıştırmasında kullandım. Basit, etkili, CI/CD'ye de sokulabilir 👇
#!/usr/bin/env bash
# token_logger.sh — her sürüm için token/debug metriklerini toplar
set -euo pipefail
LOG_FILE="metrics.jsonl"
VERSION="${1:-$(date +%s)}" # sürüm etiketi (argüman yoksa timestamp)
echo "🔍 [$VERSION] Metrikler toplanıyor..."
# Simüle edilmiş model çağrısı — gerçekte burada API call'in olur
INPUT_TOKENS=4200
OUTPUT_TOKENS=2100
CONTEXT_OVERFLOW=0
DEBUG_SECONDS=95
# JSON Lines olarak append et
jq -n \
--arg version "$VERSION" \
--argjson in_tok "$INPUT_TOKENS" \
--argjson out_tok "$OUTPUT_TOKENS" \
--argjson overflow "$CONTEXT_OVERFLOW" \
--argjson debug_sec "$DEBUG_SECONDS" \
'{
version: $version,
timestamp: now | todateiso8601,
tokens: { input: $in_tok, output: $out_tok, total: ($in_tok + $out_tok) },
context_overflow: $overflow,
debug_seconds: $debug_sec
}' >> "$LOG_FILE"
echo "✅ [$VERSION] Yazıldı → $LOG_FILE"
Nasıl çalışıyor?
./token_logger.sh v17 şeklinde çağırırdımjq ile tip güvenli JSON üretip metrics.jsonl'ye yazıyorjq -s ile hepsini toplayıp analiz edebiliyordum# Tüm sürümlerin özeti
jq -s '
map(.tokens.total) | add / length as $avg_total |
map(.debug_seconds) | add / length as $avg_debug |
map(select(.context_overflow == 1)) | length as $overflows |
{
toplam_surum: length,
ortalama_total_token: $avg_total,
ortalama_debug_dk: ($avg_debug / 60),
context_tasmasi_sayisi: $overflows
}
' metrics.jsonl
Çıktı örneği:
{
"toplam_surum": 42,
"ortalama_total_token": 7850,
"ortalama_debug_dk": 3.2,
"context_tasmasi_sayisi": 7
}
Bu sayede hiçbir zaman Excel açmadım, pivot table yapmadım — terminalden jq ile anında trend gördüm 📊
max_context - safety_margin formülüyle her çağrıda hesapladıkjq -s ile anında aggregate edilebilsin diyeHadi şimdi sıradaki bölüme geçelim — nasıl otomatikleştirdik? 🤖
Hangi modele ne zaman görev vereceğimi karar verirken şu dört kriteri göz önünde bulunduruyorum 🎯:
Bu kriterleri bir skorlama fonksiyonu ile otomatikleştiriyorum; böylece her yeni görev için “en uygun model” tek satırda bellidir 🛠.
from dataclasses import dataclass
from typing import List
@dataclass
class ModelProfile:
name: str # örn. "gpt-4o", "haiku", "llama-3-8b"
cost_per_1k_tokens: float # $ cinsinden
avg_latency_ms: int # ortalama yanıt süresi
quality_score: float # 0‑100 arası subjektif kalite puanı
local: bool = False # yerel mi?
def score_model(m: ModelProfile,
w_cost: float = 0.4,
w_latency: float = 0.2,
w_quality: float = 0.4) -> float:
"""
Ağırlıklı skor hesaplar (daha yüksek = daha uygun).
Maliyet ve gecikme ters orantılı, kalite doğrudan orantılı.
"""
# normalize et (basit min‑max, gerçekte daha gelişmiş olabilir)
cost_norm = 1 - (m.cost_per_1k_tokens / 0.12) # 0.12$ ≈ GPT‑4o üst sınır
latency_norm = 1 - (m.avg_latency_ms / 500) # 500 ms üst sınır
quality_norm = m.quality_score / 100
return (w_cost * cost_norm +
w_latency * latency_norm +
w_quality * quality_norm)
# Örnek profiller
models: List[ModelProfile] = [
ModelProfile("gpt-4o", 0.12, 350, 95),
ModelProfile("haiku", 0.015, 120, 78),
ModelProfile("llama-3-8b", 0.0, 80, 80, local=True),
]
# En iyi modeli bul
best = max(models, key=score_model)
print(f"🏆 Seçilen model: {best.name} (skor={score_model(best):.3f})")
Ne oluyor burada?
score_model fonksiyonu maliyet, gecikme ve kaliteyi ağırlıklı birleştirir.w_cost, w_latency, w_quality) proje ihtiyacına göre oynatabilirsin.cost_per_1k_tokens = 0 olduğu için maliyet kategorisinde avantajlı çıkar ✅.| Teknik | Before (kullanımda zorluk) | After (optimize edilmiş) | Neden işe yarar? |
|---|---|---|---|
| Few‑shot | Kullanıcı: "Özetle"Model: ... |
System: "Aşağıda 3 örnek özet var. Aynı stilin yap."User: "Metni özetle." |
Modelin kalıp öğrenmesini sağlar, token tasarrufu ~30 % 📉 |
| Sistem Mesajı | User: "JSON ver." |
System: "Sadece geçerli JSON döndür, açıklama yazma."User: "Veriyi JSON olarak ver." |
Çıktı formatı kilitlenir, parsing hatası önlenir 🔒 |
| Çıkış Formatı Kısıtlama | User: "Listele" |
User: "Listele (her satır: - [ ] Görev formatında)." |
Downstream işlemler (checkbox parse) direk çalışır ⚙️ |
# System
You are a concise technical assistant.
Return ONLY valid JSON matching the schema:
{
"summary": "string",
"action_items": ["string"]
}
No extra commentary.
# User
{{INPUT_TEXT}}
{{INPUT_TEXT}} yerine işlenecek metni yapıştır.| Senaryo | Tercih Edilen Model | Prompt Stratejisi |
|---|---|---|
| Müşteri destek botu (düşük maliyet, hızlı) | Haiku / Mistral‑7B | Few‑shot + sistem mesajı (JSON) |
| Kod review / güvenlik analizi | GPT‑4o / Claude‑3‑Opus | Sistem mesajı + çıktı formatı kısıtlama |
| İç veri analizi (gizlilik) | Llama‑3‑8B (yerel) | Few‑shot + yerel prompt şablonu |
| Prototip / deneme | Haiku (ucuz) | Basit sistem mesajı yeterli |
Bu tabloyu yanınıza alıp her yeni görevde bir göz atarsanız, hem bütçeniz korur hem de performans hedeflerinizi tutarsınız 🚀.
Hazırsan, dört ayrı repo’yu tek bir pipeline altında nasıl dans ettirebileceğimize bakalım 🎯.
Ana fikir: matrix strategy ile her repo için aynı job şablonunu çalıştırmak, ortam değişkenlerini ve secret’ları merkezi bir yerden yönetmek, token/süre/hata metriklerini toplayıp Slack’e uyarı atmak.
frontend, backend, ml-model, infraDEPLOY_ENV, VERSION_TAG (her repo aynı tag’i kullanır)DOCKER_HUB_TOKEN, KUBECONFIG, SLACK_WEBHOOK_URL (GitHub Actions Secrets’da tanımlı)repo boyutunda fan‑out, her biri kendi build‑and‑push adımını çalıştırırtokens_used, duration_seconds, error_count (job çıktısından ::set-output ile toplanır)name: Multi‑Repo CI/CD 🚀
on:
push:
branches: [ main ]
workflow_dispatch:
env:
DEPLOY_ENV: production
VERSION_TAG: ${{ github.sha }}
jobs:
build-and-push:
runs-on: ubuntu-latest
strategy:
matrix:
repo: [frontend, backend, ml-model, infra]
fail-fast: false # bir repo hata verse diğerleri devam etsin
env:
REPO_NAME: ${{ matrix.repo }}
steps:
- name: 📥 Checkout ilgili repo
uses: actions/checkout@v4
with:
repository: myorg/${{ matrix.repo }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: 🐳 Docker Build & Push
id: docker
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myorg/${{ matrix.repo }}:${{ env.VERSION_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: 📊 Metrikleri topla
id: metrics
run: |
TOKENS=$(jq -r '.tokens_used // 0' ./metrics.json 2>/dev/null || echo 0)
DURATION=$SECONDS
ERRORS=$(jq -r '.error_count // 0' ./metrics.json 2>/dev/null || echo 0)
echo "tokens_used=$TOKENS" >> $GITHUB_OUTPUT
echo "duration_seconds=$DURATION" >> $GITHUB_OUTPUT
echo "error_count=$ERRORS" >> $GITHUB_OUTPUT
- name: ⛔ Token limiti kontrolü
if: ${{ steps.metrics.outputs.tokens_used > 100000 }}
run: |
echo "⚠️ Token limiti aşıldı: ${{ steps.metrics.outputs.tokens_used }}"
exit 1
- name: 📢 Slack bildirimi (başarı / hata)
if: always()
uses: slackapi/slack-github-action@v1.23.0
with:
payload: |
{
"text": "*${{ job.status == 'success' && '✅' || '❌' }} ${{ matrix.repo }}* pipeline *${{ job.status }}*",
"blocks": [
{"type":"section","text":{"type":"mrkdwn","text":"*Repo:* ${{ matrix.repo }}\n*Durum:* ${{ job.status }}\n*Tokens:* ${{ steps.metrics.outputs.tokens_used }}\n*Süre:* ${{ steps.metrics.outputs.duration_seconds }}s\n*Hatalar:* ${{ steps.metrics.outputs.error_count }}"}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Bu sayede ne oluyor?
matrix.repo sayesinde dört repo paralel çalışır → süre kazancı 🎉metrics.json üretir, steps.metrics.outputs ile merkeze göndeririz.fail‑fast: false sayesinde diğer repo’lar etkilenmez.always() koşuluyla her durumda Slack’e özet mesaj gider → anlık görünürlük 📢| Metrik | Nasıl Toplanır? | Uyarı Eşiği |
|---|---|---|
| tokens_used | metrics.json → jq |
> 100 000 → job fail + Slack |
| duration_seconds | $SECONDS değişkeni |
> 600 sn → Slack “uzun süren build” |
| error_count | metrics.json |
> 0 → Slack “hata var” |
İpucu: Metrikleri merkezi bir GitHub Actions Summary sayfasına da yazdırabilirsiniz (
echo "## Metrikler" >> $GITHUB_STEP_SUMMARY).
.github/workflows/multi-repo-ci.yml olarak kaydet.DOCKER_HUB_TOKEN, KUBECONFIG, SLACK_WEBHOOK_URL ekle.metrics.json üreten bir script (ör. make metrics) bulundur.matrix.repo listesini kendi repo adlarınla güncelle.push ya da Run workflow) → Slack kanalında anlık bildirimleri izle 🎉Artık dört repo tek bir dashboard altında, aynı standartlarda build‑push‑deploy ediliyor ve her an durumdan haberdarsın. Kolay gelsin! 🚀
Hazırsan işin özetine geçelim. Aşağıdaki tablo, denediğimiz 3 ana sürüm için token tüketimi, maliyet, hata sayısı ve toplam süreyi tek bakışta gösteriyor 👇
| Sürüm | Token (K) | Maliyet (USD) | Hata Sayısı | Süre (dk) |
|---|---|---|---|---|
| v1 – Basit Prompt | 12 | $0.18 | 7 | 4 |
| v2 – Few‑Shot + RAG | 28 | $0.42 | 2 | 6 |
| v3 – Fine‑Tuned + Cache | 19 | $0.31 | 0 | 5 |
Ne anlıyoruz?
| # | Kural | Neden Önemli? |
|---|---|---|
| 1️⃣ | Token bütçesi belirle, izle | Aniden maliyet patlamasını önler. |
| 2️⃣ | Cache’i versiyonla, TTL koy | Eski veri riskini minimize eder. |
| 3️⃣ | Hata metriğini (hallucination rate) hedefle | Kalite maliyetten daha pahalıdır. |
| 4️⃣ | A/B test ile iteratif iyileştir | Tek seferde “mükemmel” yoktur, küçük adımlar kazandırır. |
Bu yolculuk bana “veri değil, strateji kazandırır” dersini verdi. Her model değişikliği bir maliyet getiriyor; ama doğru gözlem + ölçüm döngüsüyle o maliyeti yatırıma çevirebiliyorsun. Umarım bu tablo ve kural seti, kendi projenizde daha akıllı, daha ucuz kararlar almanıza yardımcı olur.
Hadi birlikte daha da iyileştirelim! 🚀
timeout ve exponential backoff koyarak cascade failure’ı engelle. ❗️Hadi, kendi ajan orkestrasyonunu kurmaya başla — ben buradayım, soruların olursa yorumlarda buluşuruz!
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved