Application { # Application n1: circle label:"Start" n2: rectangle label:"Request data by key" n3: rectangle label:"Return data to caller" n4: circle label:"End" n1.handle(right) -> n2.handle(left) n2.handle(bottom) -> CacheLayer.n5.handle(top) [label="Lookup"] n3.handle(right) -> n4.handle(left) } CacheLayer { # Cache Layer n5: rectangle label:"Check cache for key" n6: diamond label:"Cache hit?" n7: rectangle label:"Return cached value" n8: rectangle label:"Query database" n9: rectangle label:"Store in cache with TTL" n5.handle(right) -> n6.handle(left) n6.handle(right) -> n7.handle(left) [label="Yes"] n6.handle(bottom) -> n8.handle(top) [label="No"] n7.handle(top) -> Application.n3.handle(bottom) [label="From cache"] n8.handle(bottom) -> Database.n10.handle(top) [label="Fetch"] n9.handle(top) -> Application.n3.handle(bottom) [label="From DB"] } Database { # Database n10: rectangle label:"Execute query" n11: diamond label:"Data found?" n12: rectangle label:"Return result set" n13: rectangle label:"Return empty result" n10.handle(right) -> n11.handle(left) n11.handle(right) -> n12.handle(left) [label="Yes"] n11.handle(bottom) -> n13.handle(top) [label="No"] n12.handle(top) -> CacheLayer.n9.handle(bottom) [label="Populate cache"] n13.handle(top) -> Application.n3.handle(bottom) [label="Not found"] } WriteOperation { # Write Operation n14: rectangle label:"Update database" n15: rectangle label:"Invalidate cache key" n16: diamond label:"Write-through?" n17: rectangle label:"Update cache directly" n18: rectangle label:"Let cache expire" n14.handle(right) -> n15.handle(left) n15.handle(right) -> n16.handle(left) n16.handle(right) -> n17.handle(left) [label="Yes"] n16.handle(bottom) -> n18.handle(top) [label="No"] n17.handle(top) -> Application.n3.handle(bottom) [label="Updated"] n18.handle(top) -> Application.n3.handle(bottom) [label="Invalidated"] }