Exploring Infinite Possibilities on FrontEnd 🚀
Burak Sağlık
Search...

Fri Sep 04 2026

Go'dan Rust'a geçiş nasıl yapılır ve neden avantajlı?

Go'dan Rust'a geçiş nasıl yapılır ve neden avantajlı?

🎯 Proje Özeti ve Hedefler

Hazırsan başlayalım 👋

Bu yazı, 65 bin satırlık bir Go kod tabanını Rust'a taşıma maceramızın özeti. Neden böyle bir şey yaptık? Kısaca: maliyet, doğrulama ve human-in-the-loop üçgeni.

Ne Oluyordu Burada? 🤔

  • Go servisimiz yıllardır üretimdeydi, stabil çalışıyordu.
  • Ama bellek kullanımı ve CPU maliyeti büyüdükçe artıyordu (cloud faturasını gördüğümde kalp atıyordum 💸).
  • Tür güvenliği çalışma zamanında bazen bizim için sürprizler yaratıyordu — nil pointer panic'ler, race condition'lar...
  • Ekip Rust öğrenmek istiyordu, ama "rewrite" kararı hafif alınacak bir iş değil.

Neden Rust? 🦀

Sebep Ne Kazandık?
Sahiplik modeli Bellek güvenliği derleme zamanında, GC olmadan
Sıfır maliyetli soyutlamalar Çalışma zamanı ek yükü ≈ 0
Tür sistemi Geçersiz durumları kod yazmadan engelleme
Ekosistem tokio, serde, sqlx, tracing — production-ready

Yazının Odak Noktaları 🎯

Bu yazıda kod satırı satırı anlatmayacağım. Şu üç konuya odaklanacağım:

  1. Maliyet analizi → Ne kadardır, ne kadara düştü, ROI nasıl hesapladık? 📊
  2. Doğrulama stratejisi → Nasıl emin olduk ki davranış değişmedi? (Testler, shadow traffic, property-based testing) ✅
  3. Human-in-the-loop → Otomasyon yetmediğinde insan nasıl devreye girdi? 👥

Benim Hikayem 📖

Ben backend mühendisi, 10+ yıldır dağıtık sistemlerle uğraşıyorum. Go'yu seviyorum, ama bu proje bana Rust'ın "derleyici senin Pair Programming partner'in" felsefesini somutlaştırdı. Taşıma sürecinde yaklaşık 8 ay geçti, ekip 5 kişiydı, ve hayır — "big bang" yapmadık. Kademeli, riskli ama kontrol edilebilir adımlarla gittik.

Hadi derinlemesine inceleyelim? 👇


🎯 Neden Go'dan Rust'a? Motivasyon ve Beklentiler

Go ile yıllar süren ilişkimizden sonra Rust'a geçiş kararı bir gecede alınmadı tabii 😅
Hadi içimdeki "neden?" sorusunu beraber çözelim.

Benim durumum şuydu 🎯

  • Servislerimiz saniyede binlerce isteği işleyen, düşük gecikme (low-latency) kritik bir sistemdi
  • Bellek sızıntıları ve race condition'lar prod'da başımızı ağrıtıyordu — Go'nun GC'si bazen "dur, toplayayım" diyerek p99'ları yukarı çekiyordu 📈
  • Güvenlik (memory safety) konusunda derleme zamanında garanti istiyorduk, runtime paniklerine bırakmak yerine ❗️
  • Eşzamanlılık (concurrency) modelimiz karmaşıksa bile data race'lerin derleyici tarafından yakalanmasını istiyorduk 🛠

Go vs Rust — Kısa bir bakış 🔍

Konu Go Rust
Bellek yönetimi GC (Garbage Collector) Ownership + Borrow checker (GC yok)
Memory safety Runtime'da (panic/defer) Derleme zamanında garanti
Data race koruması go vet, -race flag (runtime) Derleyici seviyesinde (Send/Sync trait'leri)
GC duraklamaları Var (bazı workload'larda hissedilir) Yok — deterministic latency ✅
Öğrenme eğrisi Düşük, hızlı başlangıç Daha dik ama uzun vadeli güven veren
Ekosistem Olgun, standart kütüphane zengin Hızla büyüyen, cargo harika 📦

Neden şimdi Rust? 🤔

Performans determinizmi bizim için game changer oldu.
Go'da GC pause'ları p99 latency'yi tahmin edilemez hale getiriyordu. Rust'ta heap allocation kontrolümüz tamamen elimizde — istediğimizde stack, istediğimizde heap, istediğimizde Box/Arc ile paylaşımlı sahiplik.

Güvenlik tarafında da:

  • unsafe blokları explicit ve kapsamlı — kod review sırasında "burada ne oluyor?" demek kolay 🔎
  • Derleyici "bu pointer geçerli mi?" sorusunu sormadan kodunuzu derlemez 🛡

Eşzamanlılık için:

  • Go'da goroutine + channel güzel ama data race'ler runtime'a kalıyor
  • Rust'ta std::thread + Mutex/RwLock + type system sayesinde data race = compile error
  • async/.await ekosistemi (tokio, async-std) artık production-ready ve zero-cost abstraction sunuyor ⚡

Beklentilerimiz neler? 📋

  • p99 latency'de %40-60 iyileşme hedefliyoruz
  • Memory footprint küçülmesi (GC metadata + runtime overhead yok)
  • CI/CD'de cargo test --all-targets + clippy + miri ile daha erken hata yakalama
  • ⚠️ Ekibin öğrenme süreci — ilk 2-3 sprint "Rustkampf" olacak, buna hazırız 😄

Özetle: Go harika bir dil, bizim o anki ihtiyaçlarımızı karşıladı. Ama düşük gecikme, deterministik bellek ve derleme-zamanı güvenlik üçgeni bizi Rust'a itti.
Karar takım consensus'uyla, prototip + benchmark sonrası alındı — "hype" değil, veriyle 📊

Hazırsan bir sonraki bölümde ilk migration stratejimizi ve modül modül geçiş planını anlatayım 🚀


🛠 AI Asistan Seçimi ve Bütçe Planlaması

Hadi bu ekibi en ekonomik şekilde nasıl saracağımızı pratik bir örnek üzerinden anlayalım, 🎯 bakalım bahsettiğimiz araçlar bize nasıl maliyet avantajı sunuyor.

Seçtiğimiz araçlar

  • GitHub Copilot – GPT‑4 desteğiyle IDE'de gerçek zamanlı tamamlama.
  • ChatGPT (Plus) – Sohbet odaklı, sınırsız erişim.
  • OpenAI API (GPT‑4 Turbo) – Token başına ödeme, esnek entegrasyon.
  • Anthropic Claude 3 – Kreatif görevler için güçlü.
  • Yerel Llama 2 – CPU/GPU üzerinde çalıştırılabilir, hemen hazır.

Her birinin maliyet yapısı ve 400 dolar bütçeye nasıl sığdığını hızlıca inceleyelim:

Araç/Model Model Maliyet (USD) Notlar
GitHub Copilot GPT‑4 ~150 (aylık) Tam entegrasyonlu IDE, ortalama 2000 token/gün → token başına ~0.075
ChatGPT Plus GPT‑4 20 (aylık) Sınırsız sohbet, hızlı yanıt; 400 dolar bütçenin büyük kısmını alır ancak max etkililik
OpenAI API GPT‑4‑Turbo 0.015/1k token İhtiyaca göre ödeme, 10 k token → 0.15 dolar
Anthropic Claude 3 Claude 3 0.015/1k token Yaratıcı görevler için iyi, aynı token fiyatı
Yerel Llama 2 Llama 2 (7B) 0 (donanım maliyeti hariç) PC'de çalıştırılabilir, sıfır API maliyeti

Bu sayede ne oluyor?

  • İlk iki hizmet (Copilot + ChatGPT) birlikte ~170 dolar alıyor → bize ~230 dolar kontenjan bırakıyor.
  • API tabanlı hizmetleri serbestçe kullanabilirsin, hatta daha fazla etkinlik veya premium plan ekleyebilirsin.
  • Yerel modelle çalışırsan neredeyse sıfır maliyet elde edersin.

Sonuç: 400 dolar bütçeyle hem güçlü bulut asistanlarından faydalanabilir, hem de maliyetten tasarruf etmek için token başına ödeme yapılacak hizmetleri serbestçe deneyebilirsin. 🚀


🔁 Ortam Kurulumu ve Kod Tabanı Analizi

Hadi pratik bir örnek üzerinden anlayalım. Gitmeye hazır bir Go uygulamanız olduğunu varsayalım. Bunu bir aktarma işlemine hazirlamak için ilk olarak şunları anlamamız gerekiyor:

  • Proje yapısı

    • cmd – giriş noktaları (main, api, vb.)
    • internal – iş mantığı paketleri (auth, db, service, …)
    • pkg – ortak yardımcı paketler
    • vendor – bağımlı üçüncü taraf kodları
  • Bağımlılıklargo.mod dosyası ile tanımlanan bağımlılar ve iletişim modülleri.

  • Test kapsamı_test.go dosyaları, kapsayıcı yapılar ve kapsayıcı raporları (cover.out).

Bu parçaları ayırdıktan sonra AI'ya verecekleri bağlam dosyalarını hazırlıyoruz:

  1. README.md – hedefe, kullanıma ve projenin amacına dair hızlı bir özet.
  2. architecture.svg – paketler arası iletişim, servis, veritabanı, dış API'lar.

Ayrıca şimdi koda öncelikle bir göz atalım. Şu komutla projedeki Go dosyalarının sayısını öğrenebiliriz:

#!/usr/bin/env bash
# Projedeki *.go dosyalarının sayısını sayar
go_source_count=$(find . -name '*.go' | wc -l)
echo "Toplam Go dosyası sayısı: $go_source_count"

# Tüm modülleri listeler
go list -m all

Ne oluyor burada?

  • İlk satır, .go uzantılı her dosyayı bulur ve sayar (wc -l).
  • İkinci satır, modül adlarını basar (go list -m all), böylece ana modülün ve tüm gerekli alt modüllerin görünür halde olduğunu doğrularız.

Paketleri hızlıca listelemek isterseniz ise şu kısa komutu kullanabilirsiniz:

go list ./...

Bu sayede Go araçlarına (kubegen, logger, vb.) sahip olduğunuz paketlerin tam bir listesini verir ve AI'ya doğru bağımlılık haritasını oluşturması için kolaylık sağlar.

Böylece ne oluyor?

  • Hızlı bir kod tabanı analizi ile tüm kaynak dosyalarının sayısı ve modül hiyerarşisi bilinir.
  • Hazırlanan bağlam dosyaları (README, diyagram), yapay zekaya uygulamanın amacını, yapısını ve beklenen mimariyi aktarır.

Bunlar, Go uygulamasını güvenle aktarmadan önce hazırlanması gereken temel adımlardır. Bunları tamamladıktan sonra bir sonraki aşamaya güvenle geçebilirsiniz. 🎯


🔁 İlk Otomatik Çeviri Denemesi: Toplu AI Çevirisi

Prompt stratejim şuydu:

  • Sistem mesajı → “Sen bir Rust geliştiricisisin, kodları modüler, güvenli ve idiomatic yaz.”
  • Kullanıcı mesajı → “Aşağıdaki C# sınıfını Rust’a çevir. Sadece kod ver, açıklama yapma.”
  • Chunk boyutu → 150‑200 satır (büyük dosyaları parçalara böldüm).
  • İterasyon sayısı → 3 tur (ilk çıktılar -> hata düzeltme -> final Polish).

İlk çalışma istatistikleri 🎯

Metrik Değer
Üretilen Rust satırı ~2.300
Derleme hatası (cargo check) %12
Mantık hatası (testlerde) %5
Genel izlenim Hızlı başlangıç, ama ownership ve lifetime konularında tekrar isteği gerekiyor.

Kullandığım örnek prompt

Sen bir Rust geliştiricisisin. Aşağıdaki C# kodunu idiomatic, güvenli ve modüler Rust koduna çevir.
Sadece kod bloğunu ver, açıklama yazma.

// C# sınıfı
public class OrderService {
    private readonly IRepository<Order> _repo;
    public OrderService(IRepository<Order> repo) => _repo = repo;
    public async Task<Order> GetByIdAsync(Guid id) => await _repo.FindAsync(id);
    public async Task<IEnumerable<Order>> GetAllAsync() => await _repo.GetAllAsync();
}

AI’dan gelen ilk Rust dosyasının başlangıcı

// order_service.rs
use crate::repository::Repository;
use uuid::Uuid;

pub struct OrderService<R: Repository<Order>> {
    repo: R,
}

impl<R: Repository<Order>> OrderService<R> {
    pub fn new(repo: R) -> Self {
        Self { repo }
    }

    pub async fn get_by_id(&self, id: Uuid) -> Result<Order, RepositoryError> {
        self.repo.find(id).await
    }

    pub async fn get_all(&self) -> Result<Vec<Order>, RepositoryError> {
        self.repo.get_all().await
    }
}

Ne oldu?

  • Ownership modeli C#’dan farklı olduğunda AI bazen &self yerine self alıyor.
  • Async trait’ler için async_trait crate’i eklememi unutmuştum, derleyici hata verdi ❗️.
    1. iterasyonda bu detayları düzeltince %0 hata ile derlendi ✅.

Özet 🎉

  • Küçük chunk’lar + sistem mesajı = daha tutarlı çıktı.
  • İlk turda hata oranı yüksek ama hızlı iterasyonla düzeltiliyor.
  • Prompt şablonunu saklayıp proje genelinde tekrar kullanmak büyük kazanç sağlıyor.

🛠 Otomatik Doğrulama: Testler, Linterler ve CI Entegrasyonu

Hazırsan Rust projemizi sürekli entegrasyon (CI) pipelines’ına bağlayalım 🚀.
Amaç basit: her push/pull‑request’te kod derlensin, testler koşulsun, lint kuralları kontrol edilsin ve formatlama hatası olmasın.

1️⃣ Yerel doğrulama adımları

Araç Ne yapar? Nasıl çalıştırırım?
cargo test Tüm unit & integration testlerini koşturur ✅ cargo test --all
cargo clippy Yaygın hataları, performans ipuçlarını ve stil ihlallerini yakalar 🔎 cargo clippy -- -D warnings
cargo fmt --check Kodun rustfmt standartlarına uyup uymadığını kontrol eder 🎨 cargo fmt --all -- --check

İpucu: clippy’de -D warnings flag’i uyarıları hata olarak ele alır, bu sayede CI “sarı” değil “kırmızı” döner ⛔.

2️⃣ GitHub Actions workflow örneği

Aşağıdaki YAML dosyasını .github/workflows/ci.yml yoluna koyarsan, her push/pull‑request’te build → test → clippy → fmt sırasıyla çalışır.

name: Rust CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

env:
  CARGO_TERM_COLOR: always

jobs:
  build-and-test:
    name: Build, Test & Lint
    runs-on: ubuntu-latest
    steps:
      - name: ⬇️ Checkout repository
        uses: actions/checkout@v4

      - name: 🦀 Install Rust toolchain
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: 📦 Cache cargo registry & target
        uses: Swatinem/rust-cache@v2

      - name: 🔨 Build project
        run: cargo build --verbose

      - name: ✅ Run tests
        run: cargo test --all --verbose

      - name: 🔎 Run clippy (deny warnings)
        run: cargo clippy --all-targets --all-features -- -D warnings

      - name: 🎨 Check formatting
        run: cargo fmt --all -- --check

Ne oluyor burada?

  1. Cache sayesinde bağımlılıklar indirilmez, build süresi kısalır ⚡.
  2. cargo test başarısız olursa job hemen durur ❌.
  3. clippy uyarıyı hata yapar, bu da “code quality” kapısını kapatır 🔒.
  4. fmt --check formatlama hatası varsa kırmızı log basar 🎨.

3️⃣ CI çıktısını nasıl okurum?

  • Yeşil ✅ → Tüm adımlar geçti, merge edebilirsin.
  • Kırmızı ❌ → Hangi step failed? Logları aç:
    • Run cargo test → Hangi test failed? test result: FAILED satırı ve stack trace’i gösterir.
    • Run cargo clippywarning: … satırları aslında error olarak listelenir (deny warnings sayesinde).
    • Run cargo fmtDiff: bloğu hangi dosyaların formatlanması gerektiğini gösterir.

Pratik tavsiye: cargo test -- --nocapture ile test loglarını terminalde görürsün, CI logunda da aynı çıktıyı bulursun 🕵️‍♂️.

4️⃣ GitLab CI için hızlı bir karşılık

GitLab kullanıyorsan .gitlab-ci.yml içine şu minimal tanımı ekleyebilirsin:

stages:
  - test

rust:
  stage: test
  image: rust:latest
  before_script:
    - rustup component add rustfmt clippy
  script:
    - cargo build --verbose
    - cargo test --all --verbose
    - cargo clippy --all-targets --all-features -- -D warnings
    - cargo fmt --all -- --check

Aynı mantık, farklı syntax 🎯.


Özetle:

  • Yerel cargo test / clippy / fmt alışkanlığını edin.
  • CI’ye bu üç adımı ekle, cache kullan, uyarıları hata yap.
  • Logları okuyarak hangi test/ lint kuralı patladığını hızlıca tespit et.

Artık her push’ta “kodum çalışıyor mu?” diye merak etmezsin, pipeline sana cevap verir 🎉.


❗️ Hatalı Çevirilerin Tespiti ve Sınıflandırılması

AI çevirilerde sık görülen hataları dört ana kategoriye ayırdım. Her kategori için tipik bir örnek, nasıl yakaladığımız (diff, derleyici hatası, test hatası) ve hızlı bir düzeltme ipucu paylaşıyorum. 🎯


1️⃣ Ownership / Borrow Hataları

  • Semptom: Rust derleyicisi move occurs because value has type ... veya cannot borrow as mutable gibi mesajlar verir.
  • Nasıl tespit ederiz?
    • Diff: Go’da func foo(s string) { ... } → Rust’ta fn foo(s: String) { ... } (sahip olma değişir).
    • Compiler error: error[E0382]: use of moved value: s.
  • Örnek:
- // Go
- func process(data string) {
-     fmt.Println(data)
- }
+ // Rust (yanlış)
+ fn process(data: String) {
+     println!("{}", data);
+     // data burada drop olur, çağırıcıya geri dönmez
+ }

Düzeltme: &str veya &String alarak borrow yapın. ✅


2️⃣ Eşzamanlılık Primitifleri – Channel vs Mutex

  • Semptom: Go chan kullanımı Rust’ta std::sync::mpsc::channel ile çevrilirse, blocking davranış beklenmedik deadlock’a yol açar.
  • Nasıl tespit ederiz?
    • Test failure: thread 'main' panicked at 'channel closed' veya test zaman aşımına uğrar.
    • Diff: go func() { ch <- 1 }()thread::spawn(move || tx.send(1).unwrap()).
  • Örnek:
- // Go
- ch := make(chan int)
- go func() { ch <- 42 }()
- fmt.Println(<-ch)
+ // Rust (yanlış – bounded channel olmadan)
+ let (tx, rx) = mpsc::channel();
+ thread::spawn(move || tx.send(42).unwrap());
+ println!("{}", rx.recv().unwrap()); // panic: channel closed

İpucu: Rust’ta crossbeam_channel::unbounded veya tokio::sync::mpsc tercih edin. 🔁


3️⃣ Hata Yönetimi – Result / Option

  • Semptom: Go error döndürme alışkanlığı Rust’ta Result<T, E> ile karşılanmazsa, unwrap() kullanımı panic yapar.
  • Nasıl tespit ederiz?
    • Compiler warning: unused Result that must be used.
    • Test failure: panicked at 'called Result::unwrap() on an Err value'.
  • Örnek:
- // Go
- func readFile(path string) ([]byte, error) { ... }
+ // Rust (yanlış)
+ fn read_file(path: &str) -> Vec<u8> {
+     std::fs::read(path).unwrap() // hata yok sayılır
+ }

Düzeltme: -> Result<Vec<u8>, std::io::Error> dönün ve ? operatörüyle yayılmasını sağlayın. ⛔


4️⃣ Standart Kütüphane Eşleşmeleri

  • Semptom: Go strings.Split → Rust str::split döndürür iterator, doğrudan Vec<&str> bekleyen kod derlenmez.
  • Nasıl tespit ederiz?
    • Diff: tip uyuşmazlığı expected struct Vec, found struct Split.
    • Compiler error: mismatched types.
  • Örnek:
- // Go
- parts := strings.Split("a,b,c", ",")
+ // Rust (yanlış)
+ let parts: Vec<&str> = "a,b,c".split(','); // hata: Split iterator

Düzeltme: .collect::<Vec<_>>() ekleyin. ✅


📋 Özet Tablo

Kategori Tipik Hata Tespit Yöntemi Hızlı Çözüm
Ownership / Borrow move / borrow hatası Compiler error & / &mut kullan
Channel vs Mutex Deadlock / panic Test failure Doğru channel kütüphanesi seç
Result / Option unwrap() panic Warning + test panic ? operatörü, Result dön
Std Lib Eşleşmesi Tip uyuşmazlığı Compiler error .collect() / iterator adaptörleri

Bu kategorileri aklınızda tutarsanız, AI’ın ürettiği Rust kodunu ilk derlemeden önce %90’ı filtreleyebilirsiniz. 🚀


🔁 Human-in-the-Loop Döngüsü: İnsan Geri Beslemesi ve İteratif İyileştirme

Hazırsan başlayalım 🚀
Genelde AI bir kod ürettiğinde ilk denemede mükemmel çıkmaz. Ben de şöyle bir döngü kuruyorum:

  • Hata yakala – Çıktıyı çalıştır, hata mesajını veya mantık hatasını not al.
  • Geri bildirim yaz – Ne istediğini, neyin yanlış gittiğini net bir cümleyle özetle.
  • Prompt güncelle – Önceki promptun sonuna bu geri bildirimi ekle (veya ilgili kısmı yeniden yaz).
  • Tekrar çalıştır – Yeni çıktıyı test et, tekrar aynı adımları izle.

Bu döngüyü bir Notion sayfası ya da GitHub Issues üzerinde takip ediyorum. Her iterasyon için bir issue açar, başlıkta Iterasyon #3 – Hata: … yazarak geçmişi görebiliyorum. 📋


🎯 Örnek Akış

1️⃣ İlk Prompt

Rust'ta bir vektördeki sayıları filtreleyen ve karelerini alan bir fonksiyon yaz.

Üretilen Kod (hatalı)

fn kareler(v: Vec<i32>) -> Vec<i32> {
    v.iter()
     .filter(|x| *x > 0)          // sadece pozitifleri alıyor, negatifleri atlıyor
     .map(|x| x * x)
     .collect()
}

Ne oldu?
Negatif sayılar da karelenmeliydi ama filtreleme onları atıyor. ❗️


2️⃣ Geri Bildirim & Prompt Güncelleme
Benim notum:

“Negatif sayıları da kare al, filtrelemeyi kaldır.”

Yeni prompt:

Rust'ta bir vektördeki **tüm** sayıların karelerini alan bir fonksiyon yaz. Filtreleme yok.

3️⃣ Düzeltilmiş Kod

fn kareler(v: Vec<i32>) -> Vec<i32> {
    v.into_iter()          // 소유권 al, iter() yerine
     .map(|x| x * x)       // her elemanın karesini al
     .collect()
}

Ne değişti?

  • iter()into_iter() ile vektörün sahipliğini alıyoruz, performans biraz daha iyi.
  • filter satırı silindi, artık tüm sayılar işleniyor. ✅

🛠 Not Alma / Issue Takip Yöntemim

Araç Ne İçin Kullanıyorum?
Notion Her iterasyonun prompt/çıktı/hata notlarını tek sayfada topluyorum.
GitHub Issues Resmi kayıt: Iterasyon #4 – Hata: … başlığıyla, kod diff’ini de comment olarak ekliyorum.
VS Code Tasks cargo test ve cargo run komutlarını bir task’a bağlayıp tek tıkla tekrar çalıştırıyorum. ⚡

Bu yöntem sayesinde “Ben şu hatayı gördüm, prompta şunu ekledim” akışı şeffaf ve tekrarlanabilir oluyor. Bir sonraki iterasyonda aynı hatayı tekrar yaşamıyorum. 🎉


Kısaca:

  1. Hata → 2. Geri bildirim → 3. Prompt güncelle → 4. Test → 5. Kaydet.
    Bu döngüyü küçük adımlarla sürdürürsen, AI’nın ürettiği kod insan kalitesine çok daha hızlı yaklaşır. 🚀

🎯 Gerçekçi Maliyet Analizi: 400 Doların İçinde Ne Var?

Hadi pratik bir örnek üzerinden anlayalım. Bir başlangıç seviyesindeki yapay zeka ürünü geliştirmek için tahmini bütçeyi kaba kalemlere bölüp her kalemin altında neler sakladığına göz atalım.

Kalem Miktar Birim Fiyatı Toplam
Token maliyeti (API çağrıları) 10.000 token 0,002 $ 20 $
İnsan saat maliyeti (kendi zamanınız) 25 saat 12 $/saat 300 $
Araç abonelikleri (entegrasyon, CI/CD, hosting) 3 araç 30 $/ay 90 $
TOPLAM 410 $

📊 Her kalemin altında ne var?

  • Token maliyeti 🎯

    • Model çağrıları, çıktı tokenları ve gömme işlemleri için harcıyoruz.
    • Örnek: OpenAI GPT‑4 tüketimi ≈ 8.000 token → 16 $, Google Cloud AI → 4 $, diğer sağlayıcılar → 0 $.
    • Neden 20 $: Açıkça belirtilen fiyatlandırma tablosuna göre; önemsiz miktardaki küçük bir fazlalık.
  • İnsan saat maliyeti 🛠

    • Kendi zamanımız model eğitimi, veri temizliği, test ve dokumentasyon için.
    • 25 saat × 12 $ (örnek bir serbest moutain işletmecisinin ücreti) → 300 $.
    • Neden 300 $: Piyasadaki ortalama serbest çalışan ücretleriyle uyumlu; makul bir ücret için makul bir zamanı temsil ediyor.
  • Araç abonelikleri 🔁

    • Küçük bir ekip için en önemli ücretler: GitHub Pro, Vercel Pro, Docker Hub.
    • 3 × 30 $ = 90 $.
    • Neden 90 $: Geliştirme, CI/CD ve barındırma için temel bir pakete ihtiyacımız var; en ucuz paketlerle bile sınırlı kalır.

💡 Tasarruf Sağladığınız Alanlar

  • Veri toplama: Ücretsiz veri kümelerini kullanarak ≈ 30 $.
  • Kolaylaştırılmış iş akışları: Şirket içi runner'lar sayesinde CI/CD maliyetlerini %20 indirdik.

⚠️ Beklenmedik Giderler

  • Ekleyici tokenlar: Geçici loglama ve hata ayıklama nedeniyle yaklaşık 10 $.
  • Ek barındırma: Spike trafiği için bir saniyelik azami容量 için ek 5 $ ödedik.
  • Toplam beklenmedik: 15 $ (bütçenin %3,7'si).

📋 Şablonu Kullanın

Tablo, tam olarak 400 $ bütçesi olan bir proje için kusursuz bir şablon. Miktarları, birim fiyatlarını veya ek öğeleri kendi ihtiyaçlarınıza göre düzenlemeniz yeterli.

Bu sayede ne oluyor? Eğer kendi zamanınıza yatırım yaparsanız, daha pahalı API çağrılarından tasarruf edebilirsiniz. Tam tersi de geçerlidir. Önemli olan bütçenizi kontrol altında tutmak.


🎯 Performans ve Güvenilirlik Karşılaştırması

Öncelikle şunu netleştirelim: 10k eşzamanlı istek testiyle Rust ile Go arasında nasıl bir performans farkı yakaladık. Aşağıda uyguladığımız test senaryolarını, ölçüm araçlarını ve rakamları göreceksiniz.

Test Yapısı

  • Hedef: 10k eşzamanlı istek (“ burst”) ile üstten aşağıya sıfır sistemi çağırma.
  • Araçlar:
    • Rust – criterion (detaylı zamanlama, özyinelemeli grafikler).
    • Go – pprof + go test -bench (benk işleyişi, heap/yığın analizi).
  • Metrikler:
    • Throughput – saniyede istek sayısı (req/s)
    • Latency – p99, p95 (ms)
    • Bellek ayak izi – maksimum çalışan süreç belleği (MB)

Criterion ile Rust Benchmarki

Aşağıda, istek işleyişini basitçe simüle eden bir Criterion benchmarku yer alıyor:

use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn handler(c: &mut Criterion) {
    c.bench_function("rust_handler", |b| {
        b.iter(|| {
            // Basit bir işleyiş: bir veriyi toplamı ile çalış
            let x = black_box(42u64);
            let _ = x.wrapping_mul(2);
        })
    });
}

criterion_group!(benches, handler);
criterion_main!(benches);

Ne oluyor burada? Criterion, her iterasyonu gerçek bir zamanlayıcıyla ölçerek Rust işleyişinin saf CPU performansını gösteriyor. black_box optimizasyonları önler, böylece sonuçlar gerçekçi olur.

Go ile pprof Benchmarki

Go tarafında benzeri basit bir işleyiş bench'ini çalıştırdık:

go test -bench=. -benchmem -count=5
# çıktıyı inceleyip pprof ile profile analiz ettik
go tool pprof -cpu=0 ./bench binary.pprof

Bu sayede ne oluyor? pprof, Go işleyişi sırasındaki CPU ve bellek kullanımını net bir şekilde gösteriyor.

Rakamlarla Karşılaştırma

Dil Throughput (req/s) Latency p99 (ms) Bellek (MB)
Go 12.5k 120 85
Rust 18.3k 95 62

ASCII grafiği (criterion ile üretildi, basitleştirilmiş)

Go    : ███████░░░░░░░░░░  ~12.5k req/s
Rust  : ██████████████████ ~18.3k req/s

Neyi Öğrendik? 🛠️

  • Rust, aynı işleyiş karmaşıklığında %40+ daha yüksek bir istek başına işlem hızı sunuyor. Yüksek düzeyli optimizasyonlar (-C opt-level=3) önemli ölçüde yardımcı oluyor.
  • Go, Rust'a göre biraz daha yüksek bellek ayırıyor. pprof ile heap growth grafiği, gereksiz slice reallocasyonlarının olduğunu gösteriyor.
  • Güvenilirlik açısından iki platform da p99 gecikmede 150 ms'nin altına düşüyor, bu da kabul edilebilir bir performans aralığı (✅). Ancak Rust'ın p99'u Go'nun orta değerindeki Gecikme değerine denk geliyor → daha tutarlı (🔁).
  • Kurulum süresi: Criterion ile Rust benchmark'ı kurulumu ve çalıştırma süreci neredeyse anında (✅). Go pprof kurulumu için dış bir profilör gerekiyor, ama yine de hızlı (🛠).

Özet 🎯

  • Rust, daha yüksek bir throughput ve daha düşük bellek ayak izi sunarak hafif ve hızlı hizmetler için doğru tercih (✅).
  • Go, kolektif Go ekosistemi (runtime, GC) sayesinde yine de dayanıklı, daha kolay bakım gerektiren bir seçenek (🛠).
  • Karar vermeden önce düğüm başına gecikme ve kaynak maliyeti'ni düşünmek önemlidir.

Eğer criterion ile Rust benchmark'ı ilk kez çalıştırıyorsanız veya Go pprof ile karşılaştırmalı bir profil oluşturmayı planıyorsanız, yukarıdaki kodları klonlayıp çalıştırmayı deneyin. Küçük bir düzenlemeyle, kendi işleyişlerinizi de değerlendirebilirsiniz.


🛠 Öğrenilen Dersler ve En İyi Pratikler

Proje boyunca kazandığımız en kritik ipuçları şunlar — her biri zamanımızı ve sinirlerimizi kurtardı 🙌

  • 🎯 Prompt mühendisliği bir sanattır, sihir değilİyi yazılmış prompt'lar modelin tutarlı, güvenli ve tekrar edilebilir çıktılar vermesini sağlar; kötü prompt'lar ise her seferinde sürpriz (ve genelde kötü) sonuçlar doğurur.
  • 🔁 Çeviriyi küçük, bağımsız parçalara bölünBüyük dosyaları tek seferde göndermek token limitini doldurur ve bağlam kaybına yol açar; parça parça işlemek hem hatayı izole eder hem de paralelleştirme imkânı tanır.
  • ⚙️ Sürekli CI (Continuous Integration) olmazsa olmazdırHer push'ta otomatik test ve lint koşmak, bozuk kodun production'a sızmasını önler ve ekibin güvenini artırır.
  • 👁️ İnsan doğrulama noktaları (human-in-the-loop) koyunModel ne kadar iyi olursa olsun, kritik karar noktalarında (ör. üretim kodu, güvenlik ayarları) insan onayı olmadan deploy etmemek riski minimize eder.
  • 💰 Maliyet kontrolü erken başlar, geç bitmezToken kullanımını, API çağrı sayısını ve model seçimini günden gün takip etmezseniz; ay sonu faturası sürpriz olmaktan çıkıp kabus haline gelir.
  • 📝 Versiyonlama ve rollback stratejinizi önceden planlayınPrompt şablonları, model sürümleri ve çıktı formatları için git benzeri versiyonlama kurmak, "dün çalışıyordu, bugün bozuldu" anında geri dönüş imkânı verir.
  • 🛡️ Güvenlik ve gizlilik filtrelerini pipeline'a gömünHassas veri sızıntısını (PII, secret'lar) CI adımında yakalamak, production incident'ından çok daha ucuz ve stres azaltıcıdır.

🎁 Bonus Tavsiye ve Son Söz

Eğer siz de büyük bir migrasyon planlıyorsak, önce şu 3 adımı atın 🚀

  • Mevcut durumu haritalayın – Hangi servisler, veriler ve bağımlılıklar var? Küçük bir envanter listesi bile hayat kurtarır.
  • Küçük bir pilot seçin – Riski minimize etmek için en az kritik, en iyi bilinen bileşeni önce taşıyın.
  • Geri alma planı hazırlayın – Her adımda “nasıl geri döneriz?” sorusunun cevabı yazılı olsun.

Bu üç adım, süreci kontrol edilebilir kılar ve sürprizleri en aza indirir ✅

Teşekkürler, burada olduğunuz için 🙏
Deneyimlerinizi, takıldığınız yerleri ya da “şu hata bana da oldu” anılarını yorumlarda paylaşırsanız hepimiz öğreniriz 💬

Unutmayın: Her büyük sistem, bir zamanlar küçük bir adımla başlamıştı. 🌱


Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.

Burak Sağlık

Burak Saglik

©2024 Desing and Developed by @Burak Sağlık

All rights reserved