0%

A professional's guide to solving complex problems while designing modern software

Key Features

  • Learn best practices for designing enterprise-grade software systems
  • Understand the importance of building reliable, maintainable, and scalable systems
  • Become a professional software architect by learning the most effective software design patterns and architectural concepts

Book Description

As businesses are undergoing a digital transformation to keep up with competition, it is now more important than ever for IT professionals to design systems to keep up with the rate of change while maintaining stability.

This book takes you through the architectural patterns that power enterprise-grade software systems and the key architectural elements that enable change such as events, autonomous services, and micro frontends, along with demonstrating how to implement and operate anti-fragile systems. You'll divide up a system and define boundaries so that teams can work autonomously and accelerate the pace of innovation. The book also covers low-level event and data patterns that support the entire architecture, while getting you up and running with the different autonomous service design patterns. As you progress, you'll focus on best practices for security, reliability, testability, observability, and performance. Finally, the book combines all that you've learned, explaining the methodologies of continuous experimentation, deployment, and delivery before providing you with some final thoughts on how to start making progress.

By the end of this book, you'll be able to architect your own event-driven, serverless systems that are ready to adapt and change so that you can deliver value at the pace needed by your business.

What you will learn

  • Explore architectural patterns to create anti-fragile systems that thrive with change
  • Focus on DevOps practices that empower self-sufficient, full-stack teams
  • Build enterprise-scale serverless systems
  • Apply microservices principles to the frontend
  • Discover how SOLID principles apply to software and database architecture
  • Create event stream processors that power the event sourcing and CQRS pattern
  • Deploy a multi-regional system, including regional health checks, latency-based routing, and replication
  • Explore the Strangler pattern for migrating legacy systems

Who this book is for

This book is for software architects and aspiring software architects who want to learn about different patterns and best practices to design better software. Intermediate-level experience in software development and design is required. Beginner-level knowledge of the cloud will also help you get the most out of this software design book.

Table of Contents

  1. Software Architecture Patterns for Serverless Systems
  2. Contributors
  3. About the author
  4. About the reviewers
  5. Preface
    1. Who this book is for
    2. What this book covers
    3. To get the most out of this book
    4. Download the color images
    5. Conventions used
    6. Get in touch
    7. Share Your Thoughts
  6. Section 1: Establishing an Architectural Vision
  7. Chapter 1: Architecting for Innovation
    1. Continuously delivering business value
    2. By the skin of our teeth
    3. Through high-velocity teamwork
    4. Taking control of lead time
    5. Risk mitigation
    6. Decision making
    7. Software Development Life Cycle methodology
    8. Hardware provisioning
    9. Software deployment
    10. Software structure
    11. Testing and confidence
    12. Dependencies and inter-team communication
    13. Dissecting integration styles
    14. Batch integration
    15. Spaghetti integration
    16. Real-time integration
    17. Enterprise application integration
    18. Shared database
    19. Service-oriented architecture
    20. Microservices
    21. Enabling autonomous teams with autonomous services
    22. Autonomous services – creating bulkheads
    23. Asynchronous inter-service communication
    24. Fortified boundaries
    25. Event-first – valuing facts
    26. Inversion of responsibility
    27. Events as first-class citizens
    28. Idempotence and ordered tolerance
    29. Serverless-first – creating knowledge
    30. Self-service
    31. Disposable architecture
    32. Data life cycle – fighting data gravity
    33. Micro frontends – equalizing tiers
    34. Observability – optimizing everything
    35. Organic evolution – embracing change
    36. Summary
  8. Chapter 2: Defining Boundaries and Letting Go
    1. Building on SOLID principles
    2. Single Responsibility Principle
    3. Open-Closed Principle
    4. Liskov Substitution Principle
    5. Interface Segregation Principle
    6. Dependency Inversion Principle
    7. Thinking about events first
    8. Event storming
    9. Verbs versus nouns
    10. Facts versus ephemeral messages
    11. Contracts versus notifications
    12. React and evolve
    13. Powered by an event hub
    14. Dividing a system into autonomous subsystems
    15. By actor
    16. By business unit
    17. By business capability
    18. By data life cycle
    19. By legacy system
    20. Creating subsystem bulkheads
    21. Separate cloud accounts
    22. External domain events
    23. Decomposing a subsystem into autonomous services
    24. Context diagram
    25. Micro frontend
    26. Event hub
    27. Autonomous service patterns
    28. Backend For Frontend
    29. External Service Gateways
    30. Control services
    31. Dissecting an autonomous service
    32. Repository
    33. CI/CD pipeline and GitOps
    34. Tests
    35. Stack
    36. Persistence
    37. Trilateral API
    38. Events
    39. API Gateway
    40. Functions
    41. Micro-app
    42. Shared libraries
    43. Governing without impeding
    44. Leveraging observability
    45. Work metrics
    46. Resource metrics
    47. System events
    48. Team metrics
    49. Cost metrics
    50. Facilitating a culture of robustness
    51. Audit continuously
    52. Securing the perimeter
    53. Elevating TestOps
    54. Automating account creation
    55. Summary
  9. Section 2: Dissecting the Software Architecture Patterns
  10. Chapter 3: Taming the Presentation Tier
    1. Zigzagging through time
    2. Client-side versus server-side rendering
    3. Build-time versus runtime rendering
    4. Web versus mobile
    5. Breaking up the frontend monolith
    6. By subsystem
    7. By user activity
    8. By device type
    9. By version
    10. Dissecting micro frontends
    11. The main app
    12. The index file
    13. The importmap file
    14. Micro-app registration
    15. Micro-app
    16. The entry file
    17. Root component
    18. Micro-app activation
    19. Micro-app life cycle
    20. Route-based activation
    21. Manual activation
    22. Mount points
    23. Manifest deployer
    24. Inter-application communication
    25. Designing for offline-first
    26. Transparency
    27. Status indicators
    28. Outbox
    29. Inbox
    30. Local cache
    31. Installation
    32. Read-through cache
    33. Write-through cache
    34. Live updates
    35. WebSocket
    36. Long polling
    37. Regional failover
    38. Securing the user experience
    39. OpenID Connect
    40. Conditional rendering
    41. Protected routes
    42. Passing the JWT to BFF services
    43. Observing real user activity
    44. RUM
    45. Synthetics
    46. Summary
  11. Chapter 4: Trusting Facts and Eventual Consistency
    1. Living in an eventually consistent world
    2. Staging
    3. Cooperative
    4. Atomic
    5. Consistency
    6. Transparency
    7. Facts
    8. Chain reaction
    9. Concurrency and partitions
    10. Order tolerance and idempotence
    11. Parallelism
    12. Publishing to an event hub
    13. Event bus
    14. Domain events
    15. Event envelope
    16. Event carried state transfer
    17. Substitution
    18. Internal versus external
    19. Routing and channel topology
    20. Dissecting the Event Sourcing pattern
    21. Systemwide event sourcing
    22. Event lake
    23. Perpetual storage
    24. Indexing events
    25. Replaying events
    26. Event streams
    27. Temporal storage
    28. Stream-first event sourcing
    29. Micro event stores
    30. Processing event streams
    31. Batch size
    32. Functional reactive programming
    33. Unit of work
    34. Filtering and multiplexing
    35. Mapping
    36. Connectors
    37. Designing for failure
    38. Backpressure and rate limiting
    39. Poison events
    40. Fault events
    41. Resubmission
    42. Optimizing throughput
    43. Batch size
    44. Asynchronous non-blocking I/O
    45. Pipelines and multiplexing
    46. Pipeline patterns
    47. Sharding
    48. Batching and grouping
    49. Batching
    50. Grouping
    51. Observing throughput
    52. Work metrics
    53. Iterator age
    54. Fault events
    55. Accounting for regional failover
    56. Protracted eventual consistency
    57. Regional messaging channels
    58. Summary
  12. Chapter 5: Turning the Cloud into the Database
    1. Escaping data's gravity
    2. Competing demands
    3. Insufficient capacity
    4. Intractable volumes
    5. Embracing data life cycle
    6. Create phase
    7. Use phase
    8. Analyze phase
    9. Archive phase
    10. Turning the database inside out
    11. The transaction log
    12. Derived data
    13. Dissecting the CQRS pattern
    14. Systemwide CQRS
    15. Materialized views
    16. Inbound bulkheads
    17. Live cache
    18. Capacity per reader, per query
    19. Keeping data lean
    20. Projections
    21. Time to live
    22. Implementing idempotence and order tolerance
    23. Deterministic identifiers
    24. Inverse optimistic locking
    25. Immutable event triggers
    26. Modeling data for operational performance
    27. Nodes, edges, and aggregates
    28. Sharding and partition keys
    29. Single table design examples
    30. Restaurant service
    31. Customer service
    32. Cart service
    33. Delivery service
    34. Leveraging change data capture
    35. Database-first event sourcing
    36. Soft deletes
    37. Latching
    38. Replicating across regions
    39. Multi-master replication
    40. Round-robin replication
    41. Regional failover, protracted eventual consistency, and order tolerance
    42. Observing resource metrics
    43. Capacity
    44. Throttling and errors
    45. Performance
    46. Redacting sensitive data
    47. Envelope encryption
    48. General Data Protection Regulation (GDPR)
    49. Summary
  13. Chapter 6: A Best Friend for the Frontend
    1. Focusing on user activities
    2. A BFF service is responsible for a single user activity
    3. A BFF service is owned by the frontend team
    4. Decoupled, autonomous, and resilient
    5. Dissecting the Backend for Frontend (BFF) pattern
    6. Datastore
    7. API Gateway
    8. Query and command functions
    9. Listener function
    10. Trigger function
    11. Models and connectors
    12. Choosing between GraphQL and REST
    13. REST
    14. GraphQL
    15. Implementing different kinds of BFF services
    16. Task BFF services
    17. Search BFF services
    18. Action BFF services
    19. Dashboard BFF services
    20. Reporting BFF services
    21. Archive BFF services
    22. Securing a BFF in depth
    23. The perimeter
    24. Federated identity
    25. In transit
    26. JWT authorizer
    27. JWT assertion
    28. JWT filter
    29. Last modified by
    30. Least privilege
    31. At rest
    32. Leveraging multiple regions
    33. Latency-based routing
    34. Regional health checks
    35. Regional failover
    36. Observing BFF metrics
    37. Work metrics
    38. Throttling and concurrency limits
    39. Optimizing BFF performance
    40. Function memory allocation
    41. Cold starts
    42. Timeouts and retries
    43. cache-control
    44. Summary
  14. Chapter 7: Bridging Intersystem Gaps
    1. Creating an anti-corruption layer
    2. Dissecting the External Service Gateway pattern
    3. Connectivity
    4. Semantic transformation
    5. Action versus reaction
    6. Egress
    7. Ingress
    8. Packaging
    9. Separate cloud accounts
    10. Integrating with third-party systems
    11. Egress – API call
    12. Ingress – webhook
    13. Asynchronous request response
    14. Integrating with other subsystems
    15. Egress – upstream subsystem
    16. Ingress – downstream subsystem
    17. Integrating across cloud providers
    18. Integrating with legacy systems
    19. Ingress – Change Data Capture
    20. Egress – Direct SQL
    21. Egress – circuit breaker
    22. Ingress – relay
    23. Messages
    24. Files
    25. Egress – relay
    26. Messages
    27. Files
    28. Providing an external API and SPI
    29. Ingress – event
    30. Ingress – command
    31. Egress – webhook
    32. Egress – query
    33. Tackling common data challenges
    34. Idempotence
    35. Enriching data
    36. Latching and cross-referencing
    37. Slow data resync
    38. Managing shared secrets
    39. Securing secrets
    40. Using API keys
    41. Addressing multi-regional differences
    42. Egress routing and failover
    43. Ingress routing and failover
    44. Summary
  15. Chapter 8: Reacting to Events with More Events
    1. Promoting inter-service collaboration
    2. Dissecting the Control Service pattern
    3. collect
    4. correlate
    5. collate
    6. evaluate
    7. emit
    8. expire
    9. Orchestrating business processes
    10. Entry and exit events
    11. Parallel execution
    12. Employing the Saga pattern
    13. Compensating transactions
    14. Abort events
    15. Calculating event-sourcing snapshots
    16. What is ACID 2.0?
    17. Snapshot events
    18. Implementing CEP logic
    19. Decision tables
    20. Missing events
    21. Leveraging ML for control flow
    22. Models
    23. Predictions
    24. Implementing multi-regional cron jobs
    25. Job records and events
    26. Replication and idempotence
    27. Summary
  16. Section 3: Putting Everything in Motion
  17. Chapter 9: Choreographing Deployment and Delivery
    1. Optimizing testing for continuous deployment
    2. Continuous discovery
    3. Continuous testing
    4. Focusing on risk mitigation
    5. Small batch size
    6. Decoupling deployment from release
    7. Feature flags
    8. Fail forward fast
    9. Achieving zero-downtime deployments
    10. The Robustness principle
    11. Between the frontend and its backend
    12. Between producers and consumers
    13. Between the backend and its data store
    14. Planning at multiple levels
    15. Experiments
    16. Story backlog
    17. Story mapping
    18. Story planning
    19. Task roadmaps
    20. Turning the crank
    21. Task branch workflow
    22. Create task branch
    23. Create draft pull request
    24. Ready for review
    25. Merge to master
    26. Accept canary deployment
    27. Continuous integration pipeline
    28. Unit testing
    29. Integration testing
    30. Contract testing
    31. Transitive end-to-end testing
    32. Continuous deployment pipeline
    33. Regional canary deployments
    34. Synthetics
    35. Anomaly detection
    36. Feature flipping
    37. Exploratory testing
    38. Beta users
    39. General availability
    40. Summary
  18. Chapter 10: Don't Delay, Start Experimenting
    1. Gaining trust and changing culture
    2. Establishing a vision
    3. Building momentum
    4. Constructing an architectural runway
    5. Seed and split
    6. Funding products, not projects
    7. Architecture-driven
    8. Team capacity-driven
    9. Dissecting the Strangler pattern
    10. Event-first migration
    11. Micro frontend – headless mode
    12. Retirement
    13. Addressing event-first concerns
    14. System of record versus source of truth
    15. Duplicate data is good
    16. Avoid false reuse
    17. Poly everything
    18. Polyglot programming
    19. Polyglot persistence
    20. Polycloud
    21. Summary
    22. Why subscribe?
  19. Other Books You May Enjoy
    1. Packt is searching for authors like you
    2. Share Your Thoughts
3.133.108.241