2025-09-04
Multi-Account AWS Mimarisi: Ölçeklenebilir Event-Driven Sistemler
Dayanıklı event-driven sistemler için multi-account AWS mimari pattern'lerini öğrenin. Hesap yapısı, EventBridge routing, servisler arası iletişim ve dağıtık sistemlerde operasyonel zorlukları keşfedin.
Single-Account Mimarisinin Sınırları
Multi-account AWS mimarisi, organizasyonlar belirli ölçek ve karmaşıklık eşiklerine ulaştığında gerekli hale gelir. Bu pattern’i ne zaman ve nasıl implement edeceğinizi anlamak, sürdürülebilir büyüme ile operasyonel kaos arasındaki farkı belirleyebilir.
Dokuz geliştirme takımının aynı AWS hesabına deploy ettiği çok servisli bir platform düşünün. Bu yaklaşım küçük organizasyonlar için işe yarayabilen, ölçek arttıkça çeşitli kritik zorluklar yaratır.
Yaygın Single-Account Anti-Pattern’leri
Birden fazla takımın aynı AWS hesabını paylaşması kaynak çakışmalarına, güvenlik sorunlarına ve operasyonel karmaşıklığa yol açar. Örnek bir anti-pattern konfigürasyonu:
# "Her-şey-tek-hesapta" anti-pattern
Resources:
CustomerWebLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: quickgrocer-customer-web-api
# Umarım başka kimsenin bu role ihtiyacı yoktur...
Role: !GetAtt SharedLambdaRole.Arn
DriverAppLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: quickgrocer-driver-app-api
# Aynı rol, çünkü kimin least privilege için zamanı var?
Role: !GetAtt SharedLambdaRole.Arn
OrderProcessingLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: quickgrocer-order-processing
# Tahmin ettiniz...
Role: !GetAtt SharedLambdaRole.Arn
SharedLambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
# Herkes her şeyi alıyor!
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: 'sts:AssumeRole'
ManagedPolicyArns:
# "Sonra düzeltiriz" policy'si
- arn:aws:iam::aws:policy/PowerUserAccess
Bu yaklaşım birkaç sorun yaratır:
- Patlama Yarıçapı: Bir takımın kaynak değişiklikleri diğerlerini etkileyebilir
- İzin Karmaşıklığı: IAM policy’leri denetlenmesi zor hale gelir
- Maliyet Atfı: Takım veya servis başına kaynak kullanımını izlemek zorlaşır
- Deployment Çakışmaları: Paylaşılan CI/CD pipeline’lar darboğaz yaratır
- Güvenlik Sınırları: Tüm takımlar aynı güvenlik çevresinde çalışır
Multi-Account Mimari Paterni
Multi-account mimarisi, merkezi altyapı üzerinden kontrollü iletişim sağlayarak servisler arasında net sınırlar sunar. Etkili bir yapı:
Merkezi Identity Service: Güven Sınırımız
Her multi-account mimarisinin authentication ve authorization için tek doğruluk kaynağına ihtiyacı var. Identity Service’imizi tüm servislerin token’ları ve izinleri doğruladığı tek nokta olarak inşa ettik. Kullandığımız gerçek trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowIdentityServiceToAssumeRole",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::000000000000:role/identity-service-validator"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "${IDENTITY_SERVICE_EXTERNAL_ID}",
"aws:PrincipalOrgID": "o-quickgrocer123"
},
"IpAddress": {
"aws:SourceIp": [
"10.0.0.0/8" // VPC CIDR aralığı
]
}
}
}
]
}
Bu merkezileşme tutarlı kimlik doğrulama sağlarken dağıtık JWT validation karmaşıklığını önler.
EventBridge: Sinir Sistemi
Servislerin birbirini doğrudan çağırması yerine (ve bağımlılık kabusunu yaratması), EventBridge’i iletişim omurgamız olarak kullandık. Her hesap merkezi event bus’a event’ler yayınlıyor, o da ilgilenen subscriber’lara yönlendiriyor.
Order processing akışımızdan gerçek bir EventBridge rule:
// Cross-account event routing için CDK kodu
import { Rule, EventBus } from 'aws-cdk-lib/aws-events';
import { LambdaFunction } from 'aws-cdk-lib/aws-events-targets';
const orderPlacedRule = new Rule(this, 'OrderPlacedRule', {
eventBus: EventBus.fromEventBusArn(
this,
'CentralEventBus',
'arn:aws:events:us-east-1:121212121212:event-bus/central-bus'
),
eventPattern: {
source: ['quickgrocer.customer-web'],
detailType: ['Order Placed'],
detail: {
orderStatus: ['PENDING'],
paymentMethod: ['CREDIT_CARD', 'DEBIT_CARD', 'APPLE_PAY']
}
},
targets: [
new LambdaFunction(orderProcessingLambda, {
retryAttempts: 2,
deadLetterQueue: orderProcessingDLQ,
maxEventAge: Duration.hours(2)
})
]
});
// Cross-account event publishing için izinler
const centralBusArn = 'arn:aws:events:us-east-1:121212121212:event-bus/central-bus';
const publishPolicy = new PolicyStatement({
effect: Effect.ALLOW,
actions: ['events:PutEvents'],
resources: [centralBusArn],
conditions: {
StringEquals: {
'events:detail-type': [
'Order Placed',
'Order Updated',
'Order Cancelled'
]
}
}
});
Event-Driven Veri Akış Desenleri
Event-driven mimari servisler arası veri akışının dikkatli orkestrasyonunu gerektirir. Abonelik yükseltme iş akışı, event’lerin birden fazla hesapta durum değişikliklerini nasıl koordine ettiğini gösterir.
Cross-Service Veri Senkronizasyonu
Abonelik durumu hesap veritabanları arasında doğrudan erişim olmadan birden fazla serviste kullanılabilir olmalı. Event-sourced state replication ve local cache ile çözülür.
// Subscription Service - authoritative event yayınlar
export class SubscriptionService {
async upgradeSubscription(userId: string, planId: string) {
const subscription = await this.subscriptionRepo.create({
userId, planId, status: 'ACTIVE',
startDate: new Date(), features: this.getFeaturesByPlan(planId)
});
await this.eventPublisher.publish({
source: '"quickgrocer".subscription-service',
detailType: 'Subscription Activated',
detail: { userId, subscriptionId: subscription.id, plan: { id: planId, features: ['priority_delivery'] } }
});
return subscription;
}
}
// Order Processor - local subscription cache ile
export class OrderProcessor {
private subscriptionCache = new Map<string, SubscriptionInfo>();
@EventHandler('Subscription Activated')
async onSubscriptionActivated(event: SubscriptionEvent) {
this.subscriptionCache.set(event.detail.userId, { plan: event.detail.plan, features: event.detail.plan.features });
}
async processOrder(order: Order) {
const subscription = this.subscriptionCache.get(order.userId);
if (subscription?.features.includes('priority_delivery')) order.priority = 'HIGH';
}
}
Event Choreography vs Orkestrasyon
Orchestration tek bir servisin tüm akışı kontrol etmesi sıkı coupling ve single point of failure yaratır. Choreography her servisin kendi kısmını bilmesiyle daha gevşek coupling sağlar.
// Choreography - her servis kendi parçasını bilir
export class PaymentEventHandlers {
@EventHandler('Subscription Upgrade Requested')
async handleUpgradeRequest(event: UpgradeEvent) {
const result = await this.processPayment(event.detail);
await this.publishEvent('Payment Processed', { userId: event.detail.userId, amount: result.amount });
}
}
export class SubscriptionEventHandlers {
@EventHandler('Payment Processed')
async activateSubscription(event: PaymentEvent) {
const subscription = await this.create(event.detail.userId);
await this.publishEvent('Subscription Activated', { userId: event.detail.userId, subscriptionId: subscription.id });
}
}
Hesap Yapısı ve İzolasyon
Her takım net sınırlarla kendi kum havuzunu aldı:
# Hesap yapımız
quickgrocer-org/
├── production/
│ ├── customer-facing/
│ │ ├── customer-web-111111111111/
│ │ ├── mobile-apps-222222222222/
│ │ ├── partner-portal-333333333333/
│ │ ├── driver-app-444444444444/
│ │ └── merchant-dashboard-555555555555/
│ ├── core-services/
│ │ ├── inventory-mgmt-666666666666/
│ │ ├── order-processing-777777777777/
│ │ ├── delivery-orchestration-888888888888/
│ │ └── payment-service-999999999999/
│ └── shared-services/
│ ├── identity-service-000000000000/
│ ├── event-bus-121212121212/
│ └── monitoring-131313131313/
├── staging/
│ └── [production yapısını yansıtır]
└── development/
└── [geliştirici takımı başına bir hesap]
Gerçekten İşe Yarayanlar (İyi Kısımlar)
1. Takım Özerkliği
Takımlar sonunda kendi hızlarında ilerleyebildi. Mobile takım Black Friday’de beş güncelleme yayınlarken order processing takımı code freeze’deydi. Slack’te artık “lütfen deploy etmeyin, production’ı debug ediyoruz” mesajları yok.
2. Patlama Yarıçapı Kontrolü
DynamoDB silme olayını hatırlıyor musunuz? Yeni mimaride, delivery orchestration takımı yanlışlıkla 100.000 duplicate event işlediğinde (başka bir günün hikayesi), sadece kendi hesapları Lambda concurrent execution limitini vurdu. Müşteri siparişleri akmaya devam etti.
3. Net Maliyet Atfı
CFO’muz hangi takımın AWS kredilerimizi yaktığını tam olarak görebildiğinde neredeyse sevinç gözyaşları döktü:
// Maliyet tahsis etiketlerimiz
function applyCostTags(resource: any, teamName: string, serviceName: string): Record<string, string> {
return {
'Team': teamName,
'Service': serviceName,
'Environment': process.env.ENVIRONMENT || 'dev',
'CostCenter': TEAM_COST_CENTERS[teamName],
'Owner': TEAM_LEADS[teamName],
'CreatedDate': new Date().toISOString(),
'ManagedBy': 'CDK'
};
}
// Aylık maliyet dağılımı kristal berraklıkta oldu:
// Customer Web: $12,450 (%25)
// Mobile Apps: $8,230 (%17)
// Order Processing: $15,670 (%32)
// Delivery Orchestration: $7,890 (%16)
// Identity Service: $4,760 (%10)
4. Mantıklı Güvenlik Sınırları
Her hesabın kendi güvenlik çevresi vardı. Payment service takımı tüm şirketi compliance tiyatrosuna zorlamadan PCI compliance kontrollerini etkinleştirebildi:
// Payment service hesap güvenlik baseline'ı
const paymentServiceBaseline = new SecurityHub(this, 'PCICompliance', {
standards: [
SecurityHubStandard.PCI_DSS_V321,
SecurityHubStandard.AWS_FOUNDATIONAL_SECURITY
],
enabledRegions: ['us-east-1', 'us-west-2'],
// Sadece payment service hesabı için
accountId: '999999999999'
});
İşe Yaramayanlar (Acı Dersler)
1. Event Schema Evolution Cehennemi
Distributed sistemde event schema’ları değiştirmenin otoyolda giderken arabanın motorunu değiştirmek gibi olduğunu zor yoldan öğrendik. “Order Placed” event’imiz basit başladı:
// Versiyon 1 (Mart 2020)
{
"orderId": "ord-123",
"customerId": "cust-456",
"items": ["item-1", "item-2"],
"total": 45.99
}
Birçok “hızlı düzeltme” sonrası:
// Versiyon 7 (Aralık 2020)
{
"orderId": "ord-123",
"customerId": "cust-456",
"customerIdV2": "usr_cust-456", // Yeni ID formatı
"items": ["item-1", "item-2"], // Deprecated, itemsV2 kullan
"itemsV2": [
{
"id": "item-1",
"quantity": 2,
"price": 12.99,
"modifiers": [] // v4'te eklendi
}
],
"total": 45.99, // v5'te deprecated
"totalAmount": { // v5'te eklendi
"value": 45.99,
"currency": "USD"
},
"metadata": { // v6'da eklendi
"source": "mobile-app",
"version": "2.3.1"
}
}
Versiyonlama kabusu consumer’larımızda bu ucubeye yol açtı:
// "Schema registry kullanmalıydık" handler'ı
export const handleOrderPlaced = async (event: any) => {
// Hangi versiyonla uğraştığımızı kontrol et
const version = event.metadata?.schemaVersion ||
(event.customerIdV2 ? 7 :
event.totalAmount ? 5 :
event.items?.[0]?.modifiers ? 4 : 1);
switch(version) {
case 1:
case 2:
case 3:
return handleLegacyOrder(event);
case 4:
return handleV4Order(migrateV4ToV7(event));
case 5:
case 6:
return handleV5Order(migrateV5ToV7(event));
case 7:
return handleCurrentOrder(event);
default:
// Logla ve dua et
console.error('Bilinmeyen order versiyonu:', event);
throw new Error('Bilinmeyen schema versiyonu');
}
};
2. Cross-Account Debugging Kabusu
Bir isteği birden fazla AWS hesabı boyunca takip etmek zordur. PagerDuty alert’inden Lambda retry döngüsüne, oradan EventBridge rule’daki typo’ya kadar iz sürmek saatler alabilir. Çözüm: OpenTelemetry ile distributed tracing.
// Distributed tracing akıl sağlığımızı kurtardı
import { trace, context, SpanStatusCode } from '@opentelemetry/api';
const tracer = trace.getTracer('quickgrocer-order-service', '1.0.0');
export const processOrder = async (event: any) => {
// EventBridge event'inden trace context'i çıkar
const traceParent = event.detail?.traceContext?.traceparent;
const traceState = event.detail?.traceContext?.tracestate;
// Upstream service'ten trace'i devam ettir
const extractedContext = propagation.extract(context.active(), {
traceparent: traceParent,
tracestate: traceState
});
return context.with(extractedContext, () => {
const span = tracer.startSpan('process-order', {
attributes: {
'order.id': event.detail.orderId,
'order.account': process.env.AWS_ACCOUNT_ID,
'order.region': process.env.AWS_REGION,
'order.service': 'order-processing'
}
});
try {
// Siparişi işle
const result = await actuallyProcessOrder(event);
span.setStatus({ code: SpanStatusCode.OK });
return result;
} catch (error) {
span.recordException(error);
span.setStatus({
code: SpanStatusCode.ERROR,
message: error.message
});
throw error;
} finally {
span.end();
}
});
};
3. Maliyet Patlaması
Multi-account multi-budget anlamına gelmiyor, ama birisi AWS faturamıza söylemeyi unuttu. Cross-account data transfer, EventBridge maliyetleri ve duplicate kaynaklar toplandı:
# "Faturamız neden bu kadar yüksek" dökümü
EventBridge Events: $3,450/ay # 345 milyon event
Cross-AZ Data Transfer: $2,100/ay # Event'leri regional tutmalıydık
NAT Gateway (9 hesap): $3,215/ay # Hesap başına $35
CloudWatch Logs: $4,500/ay # Herkes her şeyi logluyordu
Secrets Manager: $1,800/ay # Secret'lar her yerde kopyalandı
Parameter Store API calls: $890/ay # Cache yok = API limit hit'leri
Toplam beklenmeyen maliyetler: $13,955/ay
Maliyet optimizasyon sprint’imiz:
// Önce: Her servis her istekte secret'ları çekiyor
const getSecret = async (secretName: string) => {
const client = new SecretsManagerClient({});
const response = await client.send(
new GetSecretValueCommand({ SecretId: secretName })
);
return response.SecretString;
};
// Sonra: TTL ile caching
class SecretCache {
private cache = new Map<string, {value: string, expiry: number}>();
private ttl = 3600000; // 1 saat
async getSecret(secretName: string): Promise<string> {
const cached = this.cache.get(secretName);
if (cached && cached.expiry > Date.now()) {
return cached.value;
}
const client = new SecretsManagerClient({});
const response = await client.send(
new GetSecretValueCommand({ SecretId: secretName })
);
this.cache.set(secretName, {
value: response.SecretString!,
expiry: Date.now() + this.ttl
});
return response.SecretString!;
}
}
// Secrets Manager maliyetlerini %94 azalttı
Kritik Olay: Event Bus Sessizliği
Yoğun bir dönemde merkezi EventBridge bus aniden event teslim etmeyi bıraktı. Bus sağlıklı görünüyordu ama sıfır event yönlendiriliyordu. Birden fazla hesapta saatler süren debugging sonucu kök neden bulundu:
// $2.3 milyon kayıp siparişe mal olan typo
{
"eventBusName": "central-bus",
"rules": [{
"name": "route-all-events",
"state": "DISABLED", // <-- Birisi "hızlı düzeltme" sırasında yanlış tuşa bastı
"eventPattern": {
"source": [{ "prefix": "quickgrocer." }]
}
}]
}
Birisi alakasız bir sorunu debug ederken ana routing rule’u devre dışı bırakmış ve yeniden etkinleştirmeyi unutmuştu. Bir checkbox. Dokuz hesap etkilendi. Yoğun sezonda 90 dakika kesinti.
Bu “Bir Daha Asla” protokollerimize yol açtı:
// Event bus sağlığı için otomatik monitoring
const eventBusMonitor = new Lambda(this, 'EventBusMonitor', {
runtime: Runtime.NODEJS_18_X,
handler: 'monitor.handler',
environment: {
EXPECTED_EVENTS_PER_MINUTE: '1000',
ALERT_THRESHOLD: '100',
SLACK_WEBHOOK: process.env.SLACK_WEBHOOK
}
});
// Her dakika çalıştır
new Rule(this, 'MonitorSchedule', {
schedule: Schedule.rate(Duration.minutes(1)),
targets: [new LambdaFunction(eventBusMonitor)]
});
// Gerçek monitoring mantığı
export const handler = async () => {
const cloudWatch = new CloudWatchClient({});
// Son dakikada yayınlanan event'leri kontrol et
const metrics = await cloudWatch.send(new GetMetricStatisticsCommand({
Namespace: 'AWS/Events',
MetricName: 'SuccessfulRuleMatches',
StartTime: new Date(Date.now() - 120000), // 2 dakika önce
EndTime: new Date(),
Period: 60,
Statistics: ['Sum']
}));
const eventCount = metrics.Datapoints?.[0]?.Sum || 0;
if (eventCount < parseInt(process.env.ALERT_THRESHOLD!)) {
// YÜKSEK SESLE BAĞIR
await sendSlackAlert({
text: `[ALERT] EVENT BUS KRİTİK: Son dakikada sadece ${eventCount} event!`,
color: 'danger'
});
// Otomatik iyileşme denemesi
await enableAllRules();
}
};
Farklı Yapacaklarımız (Geçmişe Bakış 20/20)
Bu mimariyi üç yıl çalıştırdıktan sonra geriye bakınca, geçmişteki kendime şunları söylerdim:
1. İlk Günden Schema Registry ile Başla
Sonunda AWS EventBridge Schema Registry’yi implement ettik, ama migration acı vericiydi:
// Baştan yapmalıydık
import { SchemaRegistry } from '@aws-sdk/client-schemas';
const registry = new SchemaRegistry({});
// Schema'yı versiyonlama ile tanımla
const orderSchema = {
openapi: '3.0.0',
info: {
version: '1.0.0',
title: 'OrderPlaced'
},
paths: {},
components: {
schemas: {
OrderPlaced: {
type: 'object',
required: ['orderId', 'customerId', 'items', 'totalAmount'],
properties: {
orderId: { type: 'string', pattern: '^ord-[0-9a-f]{8} },
customerId: { type: 'string', pattern: '^cust-[0-9a-f]{8} },
items: {
type: 'array',
items: {
$ref: '#/components/schemas/OrderItem'
}
},
totalAmount: {
$ref: '#/components/schemas/Money'
}
}
}
}
}
};
// Yayınlamadan önce doğrula
const validateAndPublish = async (event: any) => {
const validation = await registry.validateSchema(event, 'OrderPlaced', '1.0.0');
if (!validation.valid) {
throw new Error(`Schema doğrulama başarısız: ${validation.errors}`);
}
return await eventBridge.putEvents({ Entries: [event] });
};
2. Önce Observability’ye Yatırım Yap, Son Değil
Monitoring’i sonradan düşündük. Şöyle olmalıydı:
// Observability-first yaklaşım
class InstrumentedEventPublisher {
private metrics: MetricsClient;
private tracer: Tracer;
async publish(event: Event): Promise<void> {
const span = this.tracer.startSpan('event.publish');
const timer = this.metrics.startTimer('event.publish.duration');
try {
// Event'e trace context ekle
event.traceContext = {
traceparent: span.spanContext().traceId,
tracestate: span.spanContext().traceState
};
await this.eventBridge.putEvents({
Entries: [{
...event,
Detail: JSON.stringify({
...JSON.parse(event.Detail),
_metadata: {
timestamp: Date.now(),
account: process.env.AWS_ACCOUNT_ID,
service: process.env.SERVICE_NAME,
version: process.env.SERVICE_VERSION,
traceId: span.spanContext().traceId
}
})
}]
});
this.metrics.increment('event.published', {
type: event.DetailType,
source: event.Source
});
} catch (error) {
this.metrics.increment('event.publish.error', {
type: event.DetailType,
error: error.name
});
span.recordException(error);
throw error;
} finally {
timer.end();
span.end();
}
}
}
3. Baştan Account Vending Machine
İlk başta hesapları manuel oluşturduk. Büyük hata:
// Hemen inşa etmeliydik
import { Organizations } from '@aws-sdk/client-organizations';
import { ControlTower } from '@aws-sdk/client-controltower';
class AccountVendingMachine {
async createTeamAccount(team: TeamConfig): Promise<AWSAccount> {
// 1. Control Tower üzerinden hesap oluştur
const account = await this.controlTower.createAccount({
accountName: `quickgrocer-${team.name}-${team.environment}`,
accountEmail: `aws+${team.name}+${team.environment}@quickgrocer.com`,
organizationalUnit: this.getOUForTeam(team),
// Baseline konfigürasyon
baselineConfig: {
enableCloudTrail: true,
enableConfig: true,
enableSecurityHub: true,
enableGuardDuty: true,
budgetLimit: team.monthlyBudget
}
});
// 2. Takıma özel SCP'leri uygula
await this.applyServiceControlPolicies(account.id, team.permissions);
// 3. Cross-account rolleri kur
await this.setupCrossAccountRoles(account.id, {
identityServiceRole: 'arn:aws:iam::000000000000:role/identity-validator',
eventBusRole: 'arn:aws:iam::121212121212:role/event-publisher'
});
// 4. Baseline altyapıyı deploy et
await this.deployBaseline(account.id, {
vpcCidr: this.allocateVpcCidr(team),
eventBusArn: 'arn:aws:events:us-east-1:121212121212:event-bus/central-bus',
logGroupRetention: 30
});
return account;
}
}
4. Regional Strateji Global Olmalıydı
“Basit tutmak” için her şeyi us-east-1’de tuttuk. Sonra EU compliance’a ihtiyacımız oldu:
// İlk günden multi-region ayları kurtarırdı
const multiRegionStack = new Stack(app, 'MultiRegionInfra', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION
}
});
// Birden fazla bölgeye deploy et
['us-east-1', 'eu-west-1', 'ap-southeast-1'].forEach(region => {
new RegionalStack(app, `Regional-${region}`, {
env: { region },
eventBusArn: `arn:aws:events:${region}:121212121212:event-bus/central-bus`,
// Regional event routing
eventRouting: {
primary: region,
failover: getFailoverRegion(region)
}
});
});
Özet
Multi-account mimari üç yıl çalıştırıldığında tipik metrikler:
Örnek sayılar:
- Günlük event: 450 milyon
- Cross-account API çağrıları: 12 milyon/gün
- Ortalama gecikme: 47ms (340ms’den düştü)
- Deployment sıklığı: 340 deployment/hafta (12’den yükseldi)
- Production olayları: 2/ay (31’den düştü)
- AWS faturası: $127,000/ay (ama her doların nereye gittiğini biliyoruz)
Takımlar kendi hızlarında ilerleyebiliyor, hatalar izole kalıyor.
Ana Çıkarımlar
Organizasyonunuz için multi-account mimari düşünüyorsanız, üç yıl siperlerde geçirdikten sonra öğrendiklerim:
- İhtiyacınız Olmadan Başlayın: Krizi beklemeyin. Baskı altında migration 10 kat daha zor
- Event-Driven Opsiyonel Değil: Multi-account’ta doğrudan service-to-service çağrılar sizi rahatsız edecek
- İlk Günden Schema Registry: Versiyonlama olmadan event schema evrimi organizasyonel borç
- Observability Bir Özellik Değil: Temel. Önce inşa edin, sonra kendinize teşekkür edin
- Account Vending Kritik: Manuel hesap oluşturma 3-4 hesaptan fazlasında ölçeklenmiyor
- Maliyet Sizi Şaşırtacak: Multi-account overhead için %30 fazla bütçe ayırın, sonra optimize edin
- Takım Eğitimi Önemli: Herkes distributed sistemleri nasıl idare edeceğini bilmiyor. Eğitime yatırım yapın
Multi-account yolculuğu sadece teknoloji değil - takımlara organizasyonel tutarlılığı korurken yenilik yapma özerkliği vermek. Karmaşık, pahalı ve kompleks, ama bir sonraki 10x büyüme dalgası vurduğunda hazır olacaksınız.
Unutmayın: distributed sistemler zor, multi-account AWS daha zor, ama hızlı büyüme sırasında monolithic karmaşa hepsinden zor.
İlgili yazılar
Çok takımlı AWS organizasyonları için platform mühendisliği varsayılanı: tek event, birçok consumer, her biri kendi hesabında kendi SQS ve DLQ'suyla; fan-out event bus katmanında yaşar.
Transactional Outbox Pattern'in dağıtık sistemlerdeki dual-write problemini nasıl çözdüğünü, PostgreSQL, DynamoDB ve CDC araçlarıyla pratik implementasyonlarını öğren.
Yönetilen bir event bus'tan Kafka'ya geçişi hak eden sinyaller ve rip-and-replace yapmadan taşımak için outbox tabanlı dört aşamalı geçiş planı.
AWS Verified Permissions, SpiceDB, OpenFGA, Cerbos ve OPA dahil harici yetkilendirme platformlarının tarafsız değerlendirmesi. Mimari desenler, maliyet analizi ve mühendislik ekipleri için karar çerçevesi.
OU yapısı, SCP, RCP, Account Factory for Terraform, IAM Identity Center ve merkezi güvenlik mimarisi konularını kapsayan AWS Control Tower çoklu hesap stratejisi tasarımı ve uygulaması için pratik bir rehber.