IGFlow'u Nasıl Geliştirdim: Instagram Otomasyon Platformunun Mimarisi
Instagram hesaplarını, DM'leri ve otomasyon akışlarını tek panelden yöneten IGFlow'u sıfırdan geliştirirken verdiğim mimari kararlar: hesap başına kuyruklar, Kafka ile ayrışan servisler, limitleri kısıtlama olarak tasarlamak, WireGuard arkasındaki veri katmanı ve yapay zekâ çağrılarını izole etmek.
Instagram hesabı yöneten ajanslar ve işletmeler her gün aynı işleri elle yapıyor: gelen DM'lere cevap vermek, hedef kitleyi takip etmek, gönderi planlamak. IGFlow bu işleri tek panelde toplayan bir Instagram otomasyon platformu. Bu yazıda
platformu sıfırdan geliştirirken verdiğim mimari kararları ve yolda öğrendiklerimi anlatıyorum.
IGFlow ne yapıyor?
- Görevler: takip, takipten çıkma, beğeni, yorum, hikâye izleme ve veri toplama
- Görsel akış editörü: "biri DM'de fiyat yazarsa şu yanıtı gönder" gibi senaryoları sürükle-bırak ile kurmak
- Gerçek zamanlı gelen kutusu: DM'leri panelden okuyup yanıtlamak
- Yapay zekâ yanıtları: kullanıcının kendi AI bağlantısı ve araçlarıyla çalışan ajanlar
- Zamanlanmış paylaşım: fotoğraf, carousel, Reels ve hikâye
Teknik olarak ilginç olan kısım, bunların hepsinin tek bir hesabı yormadan, güvenli ve tutarlı biçimde çalışması.
Servislere ayırmak: neden tek bir uygulama değil?
İlk sürüm tek bir backend'di. Ama işlerin doğası çok farklıydı: panel isteği milisaniyeler içinde dönmeli, bir takip görevi ise saatlerce sürebiliyor. Instagram'a sürekli açık bir bağlantı tutmak ise bambaşka bir iş. Sonunda sistem şu parçalara ayrıldı:
| Servis | Görevi | Teknoloji |
|---|---|---|
| Panel | Arayüz ve BFF katmanı | Next.js, React, TypeScript |
| Backend | API, kimlik doğrulama, paketler | Spring Boot, PostgreSQL |
| Worker | Görevleri ve akışları çalıştırmak | Spring Boot, Kafka, MongoDB |
| Realtime gateway | Instagram'a kalıcı bağlantı, DM olayları | Spring Boot, MQTT |
| Egress | Dış yapay zekâ ve MCP çağrıları | Go |
Servisler birbirine Kafka üzerinden iş bırakıyor. Backend bir görevi kuyruğa yazıp hemen dönüyor; worker onu kendi hızında işliyor. Böylece panel, arkada ne kadar iş çalışırsa çalışsın hızlı kalıyor.
Hesap başına sıralı kuyruk
Aynı hesapla aynı anda iki işlem yapmak Instagram'ın gözünde şüpheli bir davranış. Öte yandan farklı hesapların birbirini beklemesi için hiçbir neden yok.
Çözüm, hesap başına sıralı, hesaplar arası paralel kuyruk oldu. Her hesabın işleri MongoDB'de kalıcı bir kuyrukta sırayla bekliyor; Java 21'in sanal thread'leri sayesinde yüzlerce hesap aynı anda kendi sırasını işleyebiliyor. Bir iş yeniden başlatmada yarıda
kalırsa kuyruk onu kaldığı yerden devam ettiriyor.
Limitler kapı değil, fren olmalı
İlk tasarımda limitler bir kapı gibiydi: saatte 30 takip limiti olan bir hesaba 1000 kişilik görev verilirse görev daha oluşturulurken reddediliyordu. Kullanıcı açısından anlamsızdı; kimse 30'arlı görevler açmak istemez.
Limitleri fren olarak yeniden tasarladım. Görev her durumda kabul ediliyor; worker her işlemden hemen önce hesabın kalan hakkını kontrol ediyor. Hak bittiyse görev bekletiliyor ama thread'i tutmuyor: kuyruk serbest kalıyor ve pencere açılınca görev kendiliğinden
devam ediyor. Aynı mantık çalışma saatleri için de geçerli.
Gerçek zamanlı gelen kutusu
DM'leri anında göstermek için realtime gateway her bağlı hesap için Instagram'a kalıcı bir MQTT bağlantısı tutuyor. Gelen mesajlar olay olarak akış motoruna ve panele gidiyor.
Burada küçük ama önemli bir kural koydum: hesap sahibi bir konuşmaya elle yazarsa, o konuşmadaki otomasyonlar bir süre susuyor. İnsan devraldığında botun araya girip saçmalaması, otomasyon ürünlerinin en çok şikâyet alan hatası.
Güvenlik: veri katmanı internete hiç açık değil
Sistem iki sunucuda çalışıyor. Birinde panel, backend ve kasa (HashiCorp Vault), diğerinde worker, gateway ve veri katmanı (MongoDB, Redis, Kafka) var.
- Veri katmanı yalnızca WireGuard özel ağından erişilebilir. Portlar sunucunun genel IP'sinde dinlemiyor; dışarıdan bakıldığında yoklar.
- Sırlar Vault'ta. Uygulama ayarlarında şifre yok; hassas alanlar veritabanında AES-256-GCM ile şifreli duruyor.
- Panel güvenliği: JWT ve HttpOnly oturum çerezleri, TOTP ile iki adımlı doğrulama, denetim kaydı, istek sınırlama ve tekrarlanan istekler için idempotency anahtarları.
Yolda öğrendiğim bir ders: bir uç noktayı "yol şununla başlıyorsa" diye korumak yetmiyor. Güvenlik filtresi ham adresi, framework ise çözülmüş adresi okuyorsa ikisi aynı isteği farklı görebiliyor. Kontrolü framework'ün eşleştirdiği yol üzerinden ve birden fazla
katmanda yapmak gerekiyor.
Yapay zekâ çağrılarını izole etmek
Kullanıcılar akışlarına kendi yapay zekâ bağlantılarını ve MCP araçlarını ekleyebiliyor. Bu, sunucunun kullanıcının verdiği adreslere istek atması demek; yanlış kurgulanırsa iç ağdaki sistemlere ulaşmanın kapısı olur.
Bu yüzden dış çağrıların hepsi Go ile yazılmış küçük bir egress servisinden geçiyor. Servisin iç sistemlere giden bir yolu yok; yalnızca dışarıya HTTPS isteği atabiliyor ve bağlantı anında hedef IP'nin iç ağa ait olmadığını doğruluyor. Kodda bir hata olsa bile ağ
kuralı veritabanına ulaşmayı imkânsız kılıyor.
Deploy: her push test edilip yayına çıkıyor
Gitea Actions ile her push'ta önce testler koşuyor, sonra servisler doğru sırayla güncelleniyor: önce worker, sonra backend. Sıra önemli, çünkü yeni bir mesaj alanını tanımayan eski bir worker o mesajı işleyemez. Sıra kuralını pipeline'ın kendisi garanti ediyor.
Sonuç
IGFlow'u geliştirirken en çok işe yarayan ilke şu oldu: hata yapılması kolay olan yerde hatayı imkânsız kılmak. Limitleri frene çevirmek, veri katmanını özel ağa almak, dış çağrıları izole bir servise vermek; hepsi "dikkat etmeyi unutursak ne olur?" sorusuna
verilmiş yapısal cevaplar.
Platformu incelemek istersen: igflow.app
> IGFlow, Meta'nın resmî API'sini değil oturum tabanlı erişimi kullanır ve Meta ile bağlantılı değildir. Bu risk kullanıcılara açıkça belirtilir; sistem, hesapları limitlerle koruyacak şekilde tasarlanmıştır.