İçeriğe atla
Ayhan Sipahi Ayhan Sipahi

Init Amortismanına Göre Kod Mimarisi: Lambda'da Yalın, Ağırlık Ancak Hak Edilince

Mimari ağırlığını runtime'ın init-amortismanına göre seç: single-purpose Lambda'da yalın handler, Lambdalith'te orta, tam OOP/DI yalnızca uzun ömürlü runtime'da.

Problem

1. Bölüm Lambda sorusunun topoloji yarısını yanıtladı: single responsibility bir kod ilkesidir, kaç fonksiyon deploy edileceği ise ayrı bir topoloji kararıdır. Diğer yarı, belirli bir runtime’ın içine ne kadar kod mimarisi girmesi gerektiğidir: ne kadar OOP, dependency injection ve framework ağırlığı. Yanıt 1. Bölüm’ün “istisnayı hak et” biçimini yansıtır: varsayılan olarak yalın fonksiyonel handler kullan, sonra her runtime’ın init-amortismanı izin verdikçe daha ağır yapıyı hak et. Kararı belirleyen değişken “framework’ler yavaştır” değildir; tek bir initialization’ın kaç invocation’a hizmet ettiğidir.

Bu ayrım önemlidir çünkü ekipler mimariyi runtime uyumuna göre değil, alışkanlığa göre seçer. Tam bir NestJS dependency-injection grafiği single-purpose bir fonksiyon olarak deploy edilir; orada neredeyse her cold start’ta decorator taraması yaparak yaklaşık tek bir amaca hizmet eder. Tersi de olur: yalın bir fonksiyonel handler, hiçbir connection pool’u tekrar kullanmayan uzun ömürlü bir Fargate servisine yayılır ve runtime’ın bedava sunduğu amortismanı çöpe atar. Her iki uyumsuzluk da bir paradigmayı, neyin değiştiğini sormadan bir runtime sınırından öbürüne taşımaktan doğar.

Burada TypeScript ve Node ana yoldur; Java ve Spring, kanonik ağır dependency-injection örneği olarak öne çıkar ve o örnek ters köşe bir nüans taşır.

Init-Amortisman Modeli

Tüm kararı tek bir sayı yönetir: initialization başına hizmet edilen invocation sayısı. Mimarinin ağırlığı bu oranı izlemeli, çünkü framework başlangıcının her baytı initialization başına bir kez ödenir ve sonrasında bedava tekrar kullanılır. Tekrar kullanım ne kadar çoksa, ağırlık o kadar ucuzdur.

approx 1 use per cold env

many routes per warm env

whole task lifetime

One init: build deps, DI graph, pools

FaaS single-purpose

Lambdalith

Fargate task

Lean functional handler

Router plus thin service plus light DI

Full OOP, DI, hexagonal

Üç runtime bu oranın üç noktasında durur.

  • FaaS single-purpose: bir cold environment init’i bir kez çalıştırır, sonra atıl kalıp temizlenene kadar yaklaşık tek bir mantıksal amaca hizmet eder. AWS, Lambda’nın her eşzamanlı istek için ayrı bir execution environment ayırdığını ve yeni bir tanesini başlatması gerektiğinde cold start yaşandığını belgeler. Yani init maliyeti, yapılan işe kıyasla orantısız sıklıkta ödenir. Burada init ağırlığı baskın değişkendir.
  • Lambdalith (single-domain): tek bir warm environment init’i bir kez çalıştırır, sonra bounded context’teki her route’a hizmet eder. Aynı router yapısı ve dependency-injection grafiği birçok heterojen isteğe amortize edilir. Orta yapı kazanmaya başlar.
  • Fargate: bir task bir kez başlar ve container’ın tüm ömrü boyunca çalışır, böylece init bir kez ödenir ve her isteğe amortize olur; yanı sıra uzun ömürlü bir sürecin tuttuğu kalıcı pool’lar ve cache’ler de. Ağır dependency injection ve hexagonal katmanlama burada neredeyse bedavadır. Bu basamak herhangi bir uzun ömürlü runtime’ı temsil eder; oranın uç noktasıdır, kararın odağı değil.

Bu listede aşağı indikçe amortisman oranı yükselir ve göze alınabilir mimari ağırlık da onunla yükselir. Omurga budur. Kararın çoğu bu listenin tepesinde, Lambda tarafında yaşar: single-purpose mı Lambdalith mi, yani ağırlığın gerçekten bir bedeli olduğu yer. Fargate, bedelin olmadığı uç noktadır.

Üç Yaşam Döngüsü, Tek Kısıt

Oran, her runtime’ın nasıl doğup öldüğünden gelir; bu yüzden yaşam döngülerini bir kez söylemeye değer.

FaaS önce INIT fazını çalıştırır (indirme, ortam kurulumu, modül init), sonra environment’ı dondurur, sonra sonraki invocation’lar için belki warm olarak tekrar kullanır, sonra eninde sonunda temizler. Ölçekleme granülaritesi istek başınadır. Tekrar kullanım garantili değil fırsatçı olduğundan, bir connection pool’unun veya bellek içi cache’in invocation’lar arasında ayakta kaldığını varsayamazsınız. Hem cold hem warm yola göre tasarlamak ve bağlantı yönetimini RDS Proxy gibi bir proxy’ye taşımak, bunun ardından gelen disiplindir.

Lambdalith aynı Lambda yaşam döngüsünü kullanır, ama handler bir router’dır. Tek bir init router’ı ve paylaşılan servisleri kurar ve bir warm environment o tek yapıdan N route handler’a hizmet eder. Amortisman gerçektir, ama o tek fonksiyonun kendi trafiğiyle ne sıklıkta warm kaldığıyla sınırlıdır.

Fargate uzun ömürlü bir süreçten isteklere hizmet eder. İstek başına değil, task ekleyerek ölçeklersiniz ve istek başına cold start yoktur. Init boot’ta bir kez ödenir ve task’in tüm ömrü boyunca tekrar kullanılır; bu da bir task içindeki uzun ömürlü stateful bir nesneyi bir kez kurup tutmayı güvenli kılar. Buradaki tek önemli mimari sonuç, herhangi bir uzun ömürlü runtime için de geçerlidir: pahalı şeyleri boot’ta kur, asla istek başına değil.

Kısıt üçünde de aynıdır: pahalı şeyleri runtime izin verdiği kadar seyrek kur ve elverdiği kadar çok tekrar kullan. Runtime’lar yalnızca ne kadar tekrar kullanıma izin verdiklerinde ayrışır.

Geniş Compute Merdiveni

Bu üç nokta daha uzun bir merdivenin üstünde durur ve merdivenin tamamını görmek iki hatayı önler: Fargate’i Lambda’dan sonraki ilk durak sanmak ve single-purpose ile Lambdalith’i bir ölçekleme tercihi sanmak. Bu bir ölçekleme tercihi değildir. Single-purpose ve Lambdalith aynı compute tier’dır (Lambda), istek başına ve sıfıra ölçeklenir. Aralarındaki fark kod topolojisidir.

Container’a atlamadan önce Lambda’nın çoğu ekibin yeterince kullanmadığı bir başlığı vardır. Tek bir fonksiyon 15 dakikaya kadar çalışabilir, 10.240 MB’a kadar memory ve 10.240 MB’a kadar ephemeral storage kullanabilir ve container image olarak paketlenebilir. Bir fonksiyon büyük hissettirir hissettirmez container’a uzanmak yaygın bir uyumsuzluktur. Daha şişman bir Lambda ya da bir Lambdalith çoğu zaman hâlâ yeter ve scale-to-zero’yu korur. (AWS App Runner eskiden buradaki yönetilen-container boşluğunu doldururdu, ama yeni müşterilere kapalıdır, dolayısıyla yeni projeler için bir yol değildir.)

Lambdalith’ten Fargate’e geçiş bir uçurum değil bir yokuştur, çünkü iki kaldıraç bir Lambda’yı Lambda’dan çıkmadan Fargate’in şekline taşır. Birincisi paketleme. AWS Lambda Web Adapter ile standart bir Express, Fastify ya da Spring web sunucusunu, Fargate’e deploy edeceğiniz aynı container image olarak, Lambda üzerinde çalıştırırsınız. Artifact yakınsar, çalışma modeli ise istek başına kalır ve sıfıra iner. İkincisi warmth. Provisioned concurrency başlatılmış environment’ları hazır tutar ve her iki paketlemeyle de, birinci kaldıraçtaki container image dahil, çalışır. Boştayken bile o warm tabanı faturalandırır, tıpkı Fargate’in bir task tutarak yaptığı takas gibi. SnapStart aynısını Java, Python ve .NET’te yapar, ama yalnızca managed runtime’larda zip paketleri için, container image’ları için değil; yani container-image yolu yerine Web Adapter layer’ı ile eşleşir. Paketleme ve warmth ikisi de halledildiğinde, Fargate’e olan açık faturalama granülaritesine, arka plan işine ve Lambda’nın 15 dakikalık tavanına iner. Bunlara gerçekten ihtiyaç duyduğunuzda Fargate’e geçersiniz.

Fargate’in altı, çoğu Lambda-tarafı ekibin hiç ihtiyaç duymadığı bölgedir: GPU, bin-packing ya da daemon iş yükleri için kapasiteyi yönetmeniz gerektiğinde ECS ya da EKS on EC2, sonra ham EC2 ve bare metal. Her adım scale-to-zero’yu kontrolle takas eder, ama hiçbiri mimari soruyu değiştirmez, yalnızca etrafındaki operasyonu.

Lambda single-purpose

per request, scales to zero

Lambda Lambdalith

in-process router, scales to zero

Lambda + Web Adapter

same container as Fargate, scales to zero

Lambda + provisioned concurrency

always warm, still per request

Fargate task

per task, at least one

ECS or EKS on EC2

you manage the nodes

EC2 or Auto Scaling group

per instance

Bare metal or dedicated host

fixed capacity

Mimari kararı içinse merdiven üç banda iner. Ephemeral-per-request iş (single-purpose Lambda) yalın ister. Router-amortized iş (Lambdalith) orta ister. Bir kez kurulup ömrü boyunca yeniden kullanılan her uzun ömürlü süreç (Fargate, ECS ya da EKS on EC2 ya da düz bir EC2 servisi) tam ağırlığın karşılanabildiği aynı banda girer, çünkü hepsi init’i süreç ömrüne amortize eder. Provisioned concurrency ya da SnapStart’lı bir Lambda da aynı banda girer, çünkü init’i amortize eden şey, runtime ne olursa olsun, warmth’tir. O alt basamaklar operasyon, maliyet ve ölçekleme granülaritesinde farklılaşır; ne kadar dependency injection ya da hexagonal katman taşıyabildiklerinde değil. Basamak eklemek mimari değil operasyonel karar ekler; bu yüzden yazının geri kalanı mimarinin gerçekten değiştiği üç noktada kalır.

Runtime Başına Paradigma: Varsayılan Yalın

Paradigma ekseni (fonksiyonel ile OOP, framework’süz ile ağır framework) doğrudan oranla eşleşir. Her yerde varsayılan yalındır; ağırlığı yalnızca amortismanın haklı çıkardığı yere eklersiniz.

FaaS single-purpose: yalın fonksiyonel handler

Single-purpose bir fonksiyon cold environment başına yaklaşık tek bir amaca hizmet eder, bu yüzden en aza indirilecek şey init ağırlığıdır. Fonksiyonel bir çekirdek (saf fonksiyonlar artı ince bir imperatif kabuk) tek bir handler’a doğal olarak oturur. Küçük ölçekte OOP sorun değil: bir value object, küçük bir sınıf, odaklı bir servis. Anti-pattern, tam bir dependency-injection container’ını ve decorator tarayan bir framework’ü, tek bir iş yapmak için var olan bir fonksiyonun içine sürüklemektir.

// src/orders/create.ts - lean functional handler, minimal deps, lazy init
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";

// Built once at module load, reused across warm invocations.
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
const TABLE = process.env.ORDERS_TABLE!;

// Pure core: no AWS, no I/O, trivially testable.
function toOrder(input: { sku: string; qty: number }) {
  return { id: crypto.randomUUID(), ...input, createdAt: Date.now() };
}

export const handler: APIGatewayProxyHandlerV2 = async (event) => {
  const input = JSON.parse(event.body ?? "{}");
  const order = toOrder(input);
  await ddb.send(new PutCommand({ TableName: TABLE, Item: order }));
  return { statusCode: 201, body: JSON.stringify(order) };
};

Saf fonksiyon domain kuralını tutar; handler ince imperatif kabuktur. Cold yolda hiçbir container grafik kurmaz ve modül yüklenirken kurulan tek şey, warm invocation’ların tekrar kullandığı bir client’tır.

Lambdalith: orta yapı

Bir Lambdalith router’ını ve servislerini bir kez kurar ve her route’a amortize eder, bu yüzden bir servis katmanını ve hafif dependency injection’ı göze alabilir. Tatlı nokta bir karışımdır: küçük bir OOP servis katmanının önünde fonksiyonel route handler’lar, cold start’ta çalışan ve tüm route’larca paylaşılan tek bir composition root ile bağlanır.

// src/composition.ts - one composition root, built once, shared by every route
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

export class OrderService {
  constructor(private readonly ddb: DynamoDBDocumentClient, private readonly table: string) {}
  // ... domain methods reused across routes
}

// Light, hand-wired DI: no decorator scanning, built at module load.
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const orders = new OrderService(ddb, process.env.ORDERS_TABLE!);
// src/handler.ts - router amortizes one init across many routes
import { Hono } from "hono";
import { handle } from "hono/aws-lambda";
import { orders } from "./composition";

const app = new Hono();
app.get("/orders/:id", (c) => c.json(/* orders.get(...) */ { id: c.req.param("id") }));
app.post("/orders", async (c) => c.json(/* orders.create(...) */ await c.req.json(), 201));

export const handler = handle(app); // one Lambda, every route reuses `orders`

Hono buradaki düşük-init router’dır, ama aynı biçim 1. Bölüm’ün ele aldığı AWS Lambda Web Adapter üzerinden Fastify veya Express için de geçerlidir. NestJS bir Lambdalith üzerinde aynı amortisman nedeniyle uygulanabilirdir: dependency-injection container’ı cold start’ta bir kez kurulur ve warm environment’ta her route’a tekrar kullanılır. Maliyet cold yola düşer, bu yüzden grafik ne kadar ağırsa, aşağıdaki cold-start kaldıracı o kadar önemlidir.

Fargate: tam OOP, DI, hexagonal

Bir Fargate task’i her şeyi bir kez kurar ve task’in ömrü boyunca tekrar kullanır, böylece zengin domain modelleri, eager singleton’lar ve kalıcı pool’lar hakkını verir. İstek başına cold start olmadığından ağırlık amortize edilmiş anlamda neredeyse bedavadır; bu da tam bir Spring ya da NestJS grafiği için doğal ev yapar. Tek hata modu, uzun ömürlü bir task içinde istek başına yeniden başlatmaktır ki bu da runtime’ın sana verdiği avantajı çöpe atar.

Bu runtime’lardan herhangi birinde fonksiyonel TypeScript desenleri için Effect benimseme rehberine bakın; özellikle Fargate üretim operasyonları için Fargate üretim dersleri yazısına bakın. O konular onlara sahip olan kardeş yazılara aittir; buradaki odak kod mimarisinde kalır.

Tek Çekirdek, Ayarlanan Kenarlar

Runtime başına ayarlamayı pahalı yerine ucuz kılan yeniden çerçeveleme şudur: clean architecture çekirdeği taşınır, yalnızca kenarlar değişir. Bir ports-and-adapters veya clean-architecture domain çekirdeği tanım gereği delivery mekanizmasından bağımsızdır, bu yüzden aynı domain kodu FaaS’tan Lambdalith’e ve Fargate’e değişmeden taşınır. Runtime başına ayarladığınız şey composition root ve adapter kenarıdır: çekirdeğin etrafına ne kadar framework ve dependency injection sardığınız ve bunu ne kadar eager yaptığınız. Çekirdek hangi runtime’da çalıştığını bilmez, bilmemeli de.

Domain core: entities, use cases, ports (unchanged)

FaaS edge: tiny composition root, lazy adapters

Lambdalith edge: one root at cold start, shared adapters

Fargate edge: full DI container, eager singletons, persistent adapters

Pratikte kenarlar tam olarak tek bir şeyde, composition root’ta ayrışır:

  • FaaS: küçük bir composition root, elle ya da minimal bağlanmış, cold yolun ucuz kalması için adapter’lar lazy oluşturulmuş.
  • Lambdalith: cold start’ta kurulan ve warm environment’taki her route’ta paylaşılan tek bir composition root.
  • Fargate: eager singleton’lar ve boot’ta kurulan kalıcı adapter’larla tam bir dependency-injection container’ı.

İşte bu yüzden “runtime değiştirirken domain mantığımı yeniden mi yazmalıyım?” sorusunun net bir yanıtı var: hayır. Domain çekirdeği handler’a ya da framework’e bağlıysa, bir runtime değişimi yeniden yazmaya zorlar ve o bağımlılık asıl tuzaktır. Çekirdeği bağımsız tutun ve runtime değişiminin dokunduğu tek şey composition root olsun. Karar “hangi mimari” olmaktan çıkar ve “çekirdeği koru, kenarları ayarla” olur.

Ne Zaman Aşılır: SnapStart ve Provisioned Concurrency

Varsayılan yalındır ve aşma durumu “FaaS’ta ağır bir kenarı korumak zorundayım”dır. Bu olur ve AWS bunun için iki kaldıraç sunar. Bunlar omurga değil, aşma durumlarıdır ve hangisini kullanabileceğiniz, çoğu ekibi şaşırtan bir biçimde runtime dilinize bağlıdır.

Provisioned concurrency execution environment’ları önceden başlatır, böylece init, dependency-injection grafiği kurulumu dahil, trafik gelmeden ödenir. AWS, provisioned-concurrency environment’larını çift haneli milisaniyede yanıt vermeye hazır olarak tanımlar. Her zaman açık bir ücret taşır, çünkü bir instance hiçbir isteğe hizmet etmese bile Lambda o initialization’ı faturalandırır. Node ve TypeScript ana yolu için, mevcut tek cold-start kaldıracı budur.

SnapStart bir versiyon yayınladığınızda başlatılmış execution environment’ın bir Firecracker microVM snapshot’ını alır, sonra environment’ları sıfırdan başlatmak yerine o önbelleğe alınmış snapshot’tan geri yükler. AWS bunu tam olarak bu probleme yanıt olarak çerçeveler: “modül dependency’leri veya framework’leri yükleme gibi” tek seferlik initialization kodundan gelen gecikme değişkenliği ki bunun “bazen birkaç saniye sürebileceğini” belirtir. Bu, AWS tarafından adı konmuş ağır dependency-injection cold start’ıdır. Üç kısıt onu sihirli bir anahtar yerine hassas bir araç yapar:

  • Runtime desteği dardır. SnapStart yalnızca Java 11+, Python 3.12+ ve .NET 8+ destekler. Node.js (nodejs24.x) ve Ruby desteklenmez; OS-only runtime’lar ya da container image’ları da desteklenmez. Yani TypeScript kitlesi SnapStart’ı hiç kullanamaz; provisioned concurrency Node kaldıracıdır.
  • Aynı fonksiyon versiyonunda provisioned concurrency ile karşılıklı dışlayıcıdır. Birini seçersiniz.
  • Fiyatlandırma runtime’a göre değişir. SnapStart, Java managed runtime’larında ek ücret taşımaz. Python ve .NET’te, yayınlanan versiyon başına bir önbellekleme ücreti artı bir environment her geri yüklendiğinde bir geri yükleme ücreti ödersiniz. Eski blanket “SnapStart bedava” iddiası yalnızca Java’ya özgüdür; onu diğer runtime’lara taşımayın.

Bir de doğruluk kısıtı var. Tek bir snapshot birçok environment’a tekrar kullanıldığından, environment başına benzersiz olması gereken her şey (tohumlanmış rastgelelik, önceden açılmış bağlantılar) bir runtime hook’u gerektirir; AWS açıktır: “uygulamalarınız durum benzersizliğine bağlıysa, fonksiyon kodunuzu değerlendirmelisiniz.” Ve SnapStart en az tam olarak amortisman omurgasının öngördüğü yerde yardımcı olur: AWS, seyrek çağrılan fonksiyonların aynı iyileşmeyi görmeyebileceğini belirtir ki bu da doğrudan orana geri döner.

Şimdi ters köşe. En sık “Lambda için fazla ağır” diye dışlanan framework, JVM üzerindeki Spring, SnapStart’ta bedava bir init kaldıracına sahip. Serverless dostu denen daha hafif Node yolunda yalnızca ücretli kaldıraç, provisioned concurrency var. Yani “JVM serverless için fazla ağır” kısmen geçersiz ve “Node her zaman serverless dostu seçimdir” cold-start’a duyarlı, ağır-init yollar için kısmen yanlış. Asimetri ters köşedir ve doğrudan AWS dokümanlarından gelir. Tam cold-start araç setine (paket init, snapshot ayarı, bu kaldıraçların ardındaki yaşam döngüsü mekaniği) için AWS Lambda cold start optimizasyonu yazısına bakın; bu bölüm kaldıraçları yeniden öğretmek yerine aşma durumları olarak adlandırır.

Adı konmaya değer bir tuzak daha, çünkü en yaygın yanlış çerçeveleme bu: “framework’ler Lambda’da yavaştır”ı hikayenin tamamı sanmak. Bu bir init-amortisman problemidir, steady-state değil. Bir dependency-injection grafiği bir kez kurulup warm olduğunda, p50 ya da p99 istek gecikmesini vergilendirmez; ağırlık neredeyse tamamen init’te yaşar. Çözüm, framework’ü hareket ettirmediği steady-state sayıları için suçlamak yerine, init süresini (Lambda’nın CloudWatch ve X-Ray’de görünen Init Duration’ı) ve tekrar kullanım oranını, invoke gecikmesinden ayrı ölçmektir.

Sonuç

Mimari ağırlığı init-amortismanı seçsin. Her runtime’ı oranının haklı çıkardığı en hafif mimariye varsayılan yap: single-purpose FaaS’ta yalın fonksiyonel handler, Lambdalith’te router artı ince servis artı hafif dependency injection, ve Fargate gibi uzun ömürlü bir runtime’da tam OOP, dependency injection ve hexagonal katmanlama. Üçünde de tek bir delivery’den bağımsız domain çekirdeği tut ve kenarda yalnızca composition root değişsin. Sınır net: tam framework ve dependency-injection ağırlığı, amortisman onu ödediğinde doğrudur; bu da varsayılan olarak uzun ömürlü bir servis (Fargate ya da ECS/EKS on EC2), ya da SnapStart (Java, Python ya da .NET) veya provisioned concurrency (Node kaldıracı) arkasına koyduğunuz bir Lambda demektir. Tek bir sonraki adım, bugün çalıştırdığınız bir fonksiyona bakıp init’inin gerçekte kaç invocation’a hizmet ettiğini sormaktır; bildiğiniz framework değil, o sayı, fonksiyonun ne kadar ağırlık taşıyabileceğini söyler.

Kaynaklar

  • Understanding the Lambda execution environment lifecycle - INIT/freeze/restore fazları, cold ve warm karşılaştırması ve istek başına environment ayırma üzerine AWS dokümantasyonu: amortisman modelinin üzerine kurulduğu yaşam döngüsü.
  • Improving startup performance with Lambda SnapStart - Firecracker microVM snapshot mekanizması, desteklenen runtime’lar (Java 11+, Python 3.12+, .NET 8+; Node ve Ruby değil), framework yükleme amaç ifadesi, provisioned concurrency ile karşılıklı dışlama, fiyatlandırma ve durum-benzersizliği uyarısı üzerine AWS dokümantasyonu.
  • AWS Fargate on Amazon ECS (“Architect for AWS Fargate”) - Uzun ömürlü task modeli, task başına izolasyon, task düzeyinde ölçekleme ve istek başına cold start’ın yokluğu üzerine AWS dokümantasyonu.
  • Lambda quotas - Lambda’nın katı limitleri üzerine AWS dokümantasyonu: invocation başına 15 dakikaya kadar, 10.240 MB’a kadar memory ve 512 ile 10.240 MB arası ephemeral storage; container’a uzanmadan önce tüketilecek başlık.
  • AWS App Runner availability change - App Runner’ın yeni müşterilere kapalı olduğuna dair AWS duyurusu; Lambda ile Fargate arasındaki yönetilen-container basamağının yeni projeler için neden bir yol olmadığı.
  • Configuring provisioned concurrency - Önceden başlatılmış environment’lar, çift haneli milisaniye hazırlığı ve bir instance hiçbir isteğe hizmet etmese bile initialization’ın faturalandırılması üzerine AWS dokümantasyonu: Node yolunun cold-start kaldıracı.
  • Well-Architected Serverless Applications Lens: design principles - Yalın FaaS handler’larının ardındaki ilke olan “Functions are concise, short, single-purpose” için AWS kaynağı.
  • NestJS documentation: Custom providers - Kanonik ağır-DI Node framework’ünün dependency-injection container’ı, provider’ları ve module grafiği; Lambdalith’te uygulanabilir, Fargate’te doğal.
  • Spring Boot reference documentation - Classpath taraması, IoC container’ı ve auto-configuration: kanonik ağır-DI JVM örneği ve SnapStart’ın bedava olduğu runtime.
  • Hono documentation - Ultra-hafif bir router; bir Lambdalith ya da edge runtime için düşük-init seçeneği.
  • The Clean Architecture (Robert C. Martin) - Delivery mekanizmasından bağımsız çekirdek; “çekirdek taşınır, kenarları ayarla”nın temeli.
  • Hexagonal Architecture (Ports and Adapters, Alistair Cockburn) - Değişmeyen bir çekirdeğin etrafında runtime başına ayarladığınız kenar olarak ports ve adapters.
  • AWS Lambda Web Adapter - Bir Express, Fastify ya da benzeri HTTP sunucusunu bir Lambdalith içinde değiştirmeden çalıştıran AWS bakımlı eklenti.

İlgili yazılar