<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>HUMANSREADCODE</title>
        <link>https://humansreadcode.com/</link>
        <description>Recent content on HUMANSREADCODE</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Mon, 02 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://humansreadcode.com/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>AI‑Augmented Architecture Option Exploration</title>
        <link>https://humansreadcode.com/post/2026-02-02-ai-augmented-architecture-option-exploration/</link>
        <pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2026-02-02-ai-augmented-architecture-option-exploration/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2026-02-02-ai-augmented-architecture-option-exploration/ai-augmented-architecture-option-exploration.svg" alt="Featured image of post AI‑Augmented Architecture Option Exploration" /&gt;&lt;h2 id=&#34;introduction-what-ai-changes-and-what-it-doesnt&#34;&gt;Introduction: what AI changes (and what it doesn’t)
&lt;/h2&gt;&lt;p&gt;AI changes the cost of exploring options. It does not change who is accountable for the decision.&lt;/p&gt;
&lt;p&gt;If you’re the architect, tech lead, or staff engineer, “AI‑assisted” is not a new accountability model; it’s a faster way to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Surface plausible architectures you might not have considered.&lt;/li&gt;
&lt;li&gt;Make tradeoffs explicit earlier (and with less friction).&lt;/li&gt;
&lt;li&gt;Leave a stronger evidence trail for future teams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But it only works if you treat AI as a generator and critic, not an authority. The workflow below is designed to be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tool‑agnostic (no vendor lock‑in).&lt;/li&gt;
&lt;li&gt;Enterprise‑safe (no secrets in prompts).&lt;/li&gt;
&lt;li&gt;Compatible with real constraints (compliance, integration, uptime, budgets).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;tldr-quick-start&#34;&gt;TL;DR: quick start
&lt;/h2&gt;&lt;p&gt;If you only do three things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Assemble a &lt;strong&gt;Context Pack&lt;/strong&gt; (constraints + current state + decision criteria).&lt;/li&gt;
&lt;li&gt;Generate &lt;strong&gt;3–6 concrete options&lt;/strong&gt; (at least one “boring” option), each with risks and a 2‑week validation experiment.&lt;/li&gt;
&lt;li&gt;Choose deliberately using a &lt;strong&gt;tradeoff matrix&lt;/strong&gt;, then capture the key decisions in &lt;strong&gt;one or more ADRs&lt;/strong&gt; with measurable &lt;strong&gt;fitness functions&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The full flow is: Context Pack → clarify → drivers → architecture characteristics → options + risks →
tradeoffs + mitigations → transition architectures → ADRs + fitness/enforcement + feedback.&lt;/p&gt;
&lt;h2 id=&#34;scenario-modernizing-policyquote-pricing&#34;&gt;Scenario: modernizing policy/quote pricing
&lt;/h2&gt;&lt;p&gt;You’ve inherited a policy/quote pricing capability that grew over a decade:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A monolith handles quoting, rating, underwriting rules, discounts, and taxes.&lt;/li&gt;
&lt;li&gt;Multiple channels depend on it: call center, partner portal, direct‑to‑consumer.&lt;/li&gt;
&lt;li&gt;Release cadence is slow, and pricing changes require “big bang” deployments.&lt;/li&gt;
&lt;li&gt;The business wants faster experimentation (A/B tests, segmented offers) without breaking regulatory guardrails.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Constraints (the ones that always show up in the real world):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Regulatory/compliance&lt;/strong&gt;: you must be able to explain how a price was calculated.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditability&lt;/strong&gt;: reproduce a quote months later.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Availability&lt;/strong&gt;: quoting is revenue critical; you need graceful degradation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integration&lt;/strong&gt;: downstream policy issuance and billing expect current interfaces.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance&lt;/strong&gt;: partners time out; call center productivity suffers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability&lt;/strong&gt;: quote/policy workloads spike (campaigns, renewals, partner traffic) and must scale predictably.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data sensitivity&lt;/strong&gt;: prompts cannot include PII, secrets, or proprietary pricing tables.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You want to explore multiple viable target architectures (not just “microservices!”), choose deliberately, and write down why.&lt;/p&gt;
&lt;h2 id=&#34;the-context-pack-minimum-artifacts-before-asking-ai-for-options&#34;&gt;The “Context Pack”: minimum artifacts before asking AI for options
&lt;/h2&gt;&lt;p&gt;Option exploration fails when the prompt is missing the constraints that matter.&lt;/p&gt;
&lt;p&gt;Before you ask AI to generate architectures, assemble a lightweight &lt;strong&gt;Context Pack&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Domain + goals (success, non‑goals).&lt;/li&gt;
&lt;li&gt;Constraints (regulatory, SLOs, performance budgets, data handling).&lt;/li&gt;
&lt;li&gt;Enterprise decision constraints (approved stacks, platform rules, security model).&lt;/li&gt;
&lt;li&gt;Current state (simple diagrams, critical flows, known pain points).&lt;/li&gt;
&lt;li&gt;Decision criteria (what decides, and how you’ll measure it).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want a copy/paste template, see the &lt;strong&gt;Appendix: Context Pack checklist&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&#34;stop-conditions-dont-proceed-without-these&#34;&gt;Stop conditions: don’t proceed without these
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; You cannot name the top 3 constraints that would invalidate an option.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; You cannot describe the most important runtime failure mode.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; You cannot explain what “auditability” means for this domain (what must be reproducible).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If any stop condition triggers, do not ask for architectures yet. Ask for missing artifacts.&lt;/p&gt;
&lt;h2 id=&#34;the-6stage-workflow&#34;&gt;The 6‑stage workflow
&lt;/h2&gt;&lt;p&gt;This is the workflow I use when I want AI to accelerate thinking without replacing judgment.&lt;/p&gt;
&lt;h3 id=&#34;stage-1--clarify-make-constraints-explicit&#34;&gt;Stage 1 — Clarify (make constraints explicit)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; turn fuzzy intent into a crisp problem statement and a bounded search space.&lt;/p&gt;
&lt;p&gt;Inputs: your Context Pack.&lt;/p&gt;
&lt;p&gt;Prompts that work well (tool‑agnostic and safe):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Summarize the problem in 5 bullets, then list 10 clarifying questions that would change the architecture choice.”&lt;/li&gt;
&lt;li&gt;“Restate the constraints as testable statements (e.g., ‘must reproduce quote for 7 years’).”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outputs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A validated problem statement.&lt;/li&gt;
&lt;li&gt;A list of constraints you can point at in a decision review.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Guardrail: do not accept new constraints invented by the model. Every constraint must map to a known source (policy, stakeholder, incident, contract).&lt;/p&gt;
&lt;h3 id=&#34;stage-2--from-business-drivers-to-architecture-characteristics&#34;&gt;Stage 2 — From business drivers to architecture characteristics
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; use the key business drivers to reveal the driving architecture characteristics (explicit) and the implicit ones that will still constrain you.&lt;/p&gt;
&lt;p&gt;This stage is where you turn “the business wants faster experimentation” into qualities you can actually design and test against.&lt;/p&gt;
&lt;p&gt;Prompts that work well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Extract the key business drivers from the Context Pack, then derive the driving architecture characteristics that follow from them.”&lt;/li&gt;
&lt;li&gt;“List implicit architecture characteristics that are not stated, but must be true for this domain (e.g., auditability, determinism, explainability). Mark each as: given vs inferred, and state the evidence.”&lt;/li&gt;
&lt;li&gt;“Rewrite each characteristic as a testable statement (SLO, retention rule, determinism requirement, operability constraint).”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outputs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A short list of key business drivers.&lt;/li&gt;
&lt;li&gt;A ranked list of architecture characteristics split into &lt;strong&gt;driving&lt;/strong&gt; (decision makers) vs &lt;strong&gt;implicit&lt;/strong&gt; (still mandatory).&lt;/li&gt;
&lt;li&gt;A first‑pass measurement idea for each characteristic (even if it’s approximate).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: if you previously used “transition complexity” as a criterion, it’s usually better expressed as the architecture characteristic &lt;strong&gt;evolvability&lt;/strong&gt; (how safely and incrementally the system can change over time).&lt;/p&gt;
&lt;p&gt;Guardrail: if a characteristic is inferred, label it as inferred and require an evidence link (regulation, contract, incident history, stakeholder statement).&lt;/p&gt;
&lt;h3 id=&#34;stage-3--generate-permutations-candidate-styles--options--isomorphism--risks&#34;&gt;Stage 3 — Generate permutations (candidate styles → options → isomorphism → risks)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; take the driving + implicit architecture characteristics and deliberately create optionality around candidate architecture styles that fit the problem domain.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Select candidate architecture styles (or combinations)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Examples (pick what actually fits your domain and org):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Modular monolith + façade (strangler)&lt;/li&gt;
&lt;li&gt;Layered / hexagonal with a rules boundary&lt;/li&gt;
&lt;li&gt;Domain services (coarse‑grained services, not “microservices by default”)&lt;/li&gt;
&lt;li&gt;Event‑driven / async integration for decoupling&lt;/li&gt;
&lt;li&gt;Event sourcing or append‑only audit log for replay/audit&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Create 3–6 concrete options&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For each candidate style (or combination), ask for an option that includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Core components and responsibilities&lt;/li&gt;
&lt;li&gt;Data ownership and audit/replay story&lt;/li&gt;
&lt;li&gt;Failure modes and degradation rules&lt;/li&gt;
&lt;li&gt;A first‑pass transition hypothesis from current state (incremental steps and major dependencies)&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Apply domain‑to‑architecture isomorphism&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For each option, validate that the architecture shape matches the domain shape:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where do underwriting rules, pricing/rating, discounts, taxes, and approvals live?&lt;/li&gt;
&lt;li&gt;What is the “unit of audit” (quote, rating run, rule set version), and how is it reproduced?&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;Align across the intersections (constraints that often kill options)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For each option, do a quick pass across architecture intersections that add real‑world constraints:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implementation (libraries, language/runtime constraints)&lt;/li&gt;
&lt;li&gt;Infrastructure (platform, runtime, deployment, scaling)&lt;/li&gt;
&lt;li&gt;Data topologies (stores, retention, lineage)&lt;/li&gt;
&lt;li&gt;Engineering practices (testing strategy, release controls)&lt;/li&gt;
&lt;li&gt;Team topologies (ownership boundaries, on‑call reality)&lt;/li&gt;
&lt;li&gt;Systems integration (contracts, sync/async, backwards compatibility)&lt;/li&gt;
&lt;li&gt;Business environment (regulatory approvals, audit workflows)&lt;/li&gt;
&lt;li&gt;Enterprise alignment (standards, shared platforms)&lt;/li&gt;
&lt;li&gt;Generative AI (what context is needed, what must not leave the boundary)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where permitted, MCP Servers can be a practical way to safely access internal enterprise and business‑unit decision documents (standards, policies, platform guidance) as you evaluate these intersections.
This helps you distinguish “violates a hard constraint” from “needs an exception” early, before you invest in deeper analysis.&lt;/p&gt;
&lt;ol start=&#34;5&#34;&gt;
&lt;li&gt;Perform a first‑pass risk analysis per option&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Have AI enumerate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Top risks (technical, operational, organizational)&lt;/li&gt;
&lt;li&gt;Assumptions that must be true&lt;/li&gt;
&lt;li&gt;The cheapest experiment that would validate/invalidate the option (≤ 2 weeks)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;stage-4--explore-tradeoffs-scoring--risk-comparison--mitigations&#34;&gt;Stage 4 — Explore tradeoffs (scoring + risk comparison + mitigations)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; make the decision legible. You’re not optimizing for a perfect score; you’re optimizing for a decision you can defend.&lt;/p&gt;
&lt;h4 id=&#34;tradeoff-matrix-template-headings&#34;&gt;Tradeoff matrix template (headings)
&lt;/h4&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Criterion&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Weight (1–5)&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Option A&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Option B&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Option C&lt;/th&gt;
          &lt;th&gt;Notes / evidence&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Auditability / replay&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;What must be reproducible?&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Performance (p95)&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Partner timeout budget; throughput assumptions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Scalability&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Peak load, bursts, and predictable degradation&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Evolvability&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Incremental change, parallel run, cutovers, reversibility, “stop‑anytime” states&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Operational complexity&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;On‑call, deployments, runbooks&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Change velocity&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Time to ship pricing change&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Cost to operate&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Infra + people&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Blast radius&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Failure containment&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Integration risk&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;Contracts, downstream dependencies&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Security / data handling&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;&lt;/td&gt;
          &lt;td&gt;PII boundaries&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id=&#34;scoring-rubric-keep-it-honest&#34;&gt;Scoring rubric (keep it honest)
&lt;/h4&gt;&lt;p&gt;Use a simple qualitative scale, but always include “why”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;5&lt;/strong&gt; = clearly meets the need with margin; known patterns; low uncertainty&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;3&lt;/strong&gt; = plausible but requires work or introduces notable risk&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1&lt;/strong&gt; = likely fails the requirement or creates unacceptable risk&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can help here by forcing completeness:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Fill out the tradeoff table. For each score, write the strongest argument against that score (steelman the critique).”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Risk comparison and mitigation prompts that work well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Compare the risk profiles across options. Which risks are unique vs shared, and which are existential?”&lt;/li&gt;
&lt;li&gt;“For the top 3 risks in each option, propose mitigations and the earliest point in the migration where each mitigation must exist.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This stage is where many “clever” architectures die in a good way.&lt;/p&gt;
&lt;h3 id=&#34;a-worked-miniexample-abridged&#34;&gt;A worked mini‑example (abridged)
&lt;/h3&gt;&lt;p&gt;To make the workflow more concrete, here’s what “3 options + a tradeoff slice” can look like.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Option A — Modular monolith + façade (strangler)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep a single deployable for now, but carve out a pricing boundary (clear module APIs).&lt;/li&gt;
&lt;li&gt;Add a façade in front of the monolith to create a seam for incremental replacement.&lt;/li&gt;
&lt;li&gt;Add an append‑only audit log of “pricing runs” (inputs + rule version + outputs).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Option B — Domain services (coarse‑grained)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Split into a small number of services aligned to stable domain boundaries (e.g., pricing, quote orchestration).&lt;/li&gt;
&lt;li&gt;Use contract tests and versioned APIs to protect channels and downstream systems.&lt;/li&gt;
&lt;li&gt;Centralize auditability via a shared audit store or per‑service append‑only logs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Option C — Event‑driven integration + audit log&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep synchronous quote calls where latency demands it, but decouple downstream effects via events.&lt;/li&gt;
&lt;li&gt;Use an append‑only audit log for replay/reproduction.&lt;/li&gt;
&lt;li&gt;Avoid “event sourcing everywhere” unless the org is ready for the operational complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tradeoff matrix (5‑criteria slice):&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Criterion&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;Weight (1–5)&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;A&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;B&lt;/th&gt;
          &lt;th style=&#34;text-align: right&#34;&gt;C&lt;/th&gt;
          &lt;th&gt;Notes / evidence&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Auditability / replay&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td&gt;C is strongest if audit log is first‑class&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Performance (p95)&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td&gt;A is simplest path to hit latency budgets&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Evolvability&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;5&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td&gt;B enables parallel evolution; C adds more moving parts&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Operational complexity&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;1&lt;/td&gt;
          &lt;td&gt;C risks overload without on‑call maturity&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Integration risk&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;4&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td style=&#34;text-align: right&#34;&gt;3&lt;/td&gt;
          &lt;td&gt;A preserves existing contracts; B/C require more interface work&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The goal is not to “win the table”. The goal is to make the decisive tradeoffs legible and
testable.&lt;/p&gt;
&lt;h3 id=&#34;stage-5--explore-transition-architectures-current--target-incrementally&#34;&gt;Stage 5 — Explore transition architectures (current → target, incrementally)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; now that you have a current state and a target direction, explore incremental transition architectures (stepping‑stone states) that keep the system evolvable and safe at every stage.&lt;/p&gt;
&lt;p&gt;This is distinct from picking a target. It’s about proving you can get there without a big bang,
and that each intermediate state is operationally viable if you need to pause (a “stop‑anytime”
state).&lt;/p&gt;
&lt;p&gt;Transition architecture prompts that work well:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Given the current architecture and the chosen target direction, propose 3 incremental transition paths. Each path must define stepping‑stone architectures, cutover points, and rollback strategy.”&lt;/li&gt;
&lt;li&gt;“For each transition step, list: what changes, what stays stable, how contracts remain compatible, and what the system looks like if you stop here for 6 months.”&lt;/li&gt;
&lt;li&gt;“Identify the key seams for strangling (facades, anti‑corruption layers, event capture, parallel run) and the fitness functions that must hold at each step.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Outputs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2–3 viable transition architectures (stepping‑stone states), not just a single migration plan.&lt;/li&gt;
&lt;li&gt;The “stop‑anytime” architecture for each step (so the design stays open to evolution).&lt;/li&gt;
&lt;li&gt;A small set of per‑step fitness functions (what must not regress while you transition).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;stage-6--hone-in-on-the-target-architecture-nfrs-fitnessenforcement-adrs-feedback&#34;&gt;Stage 6 — Hone in on the target architecture (NFRs, fitness/enforcement, ADRs, feedback)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Goal:&lt;/strong&gt; converge on a target architecture direction, then capture the decision and the quality gates that will keep it true over time.&lt;/p&gt;
&lt;h4 id=&#34;adrs-expect-more-than-one&#34;&gt;ADRs: expect more than one
&lt;/h4&gt;&lt;p&gt;Option exploration typically produces &lt;strong&gt;multiple ADRs&lt;/strong&gt;. At minimum you’ll usually want:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One ADR for the &lt;strong&gt;target architecture direction&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;One ADR for the &lt;strong&gt;transition strategy&lt;/strong&gt; (stepping‑stone states, cutovers, rollback).&lt;/li&gt;
&lt;li&gt;(Often) one ADR per &lt;strong&gt;cross‑cutting decision&lt;/strong&gt; that changes constraints (data/audit approach, integration patterns, deployment model, etc.).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;adr-outline-tailored-to-option-exploration&#34;&gt;ADR outline (tailored to option exploration)
&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;Title:&lt;/strong&gt; Decision on pricing architecture direction (Option X)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Status:&lt;/strong&gt; Proposed / Accepted / Superseded&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context:&lt;/strong&gt; key constraints, drivers, and what forced the decision&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decision:&lt;/strong&gt; what we chose and the boundaries (what’s in/out)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Options considered:&lt;/strong&gt; short summaries of the top alternatives&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tradeoffs:&lt;/strong&gt; the 3–5 decisive tradeoffs (with evidence links)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Consequences:&lt;/strong&gt; what gets harder, what we must invest in (ops, tooling, training)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration plan:&lt;/strong&gt; incremental steps, cutover strategy, rollback strategy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open questions:&lt;/strong&gt; explicitly tracked unknowns&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;fitness-functions-measurable-not-aspirational&#34;&gt;Fitness functions (measurable, not aspirational)
&lt;/h4&gt;&lt;p&gt;Define a small set of &lt;strong&gt;fitness functions&lt;/strong&gt; (measurable quality constraints that you check
continuously) that must improve (or must not regress):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quote performance p95 ≤ 400ms for partner channel&lt;/li&gt;
&lt;li&gt;Quote throughput scales to peak volume within the cost envelope&lt;/li&gt;
&lt;li&gt;“Reproduce quote” workflow completes with matching premium within tolerance&lt;/li&gt;
&lt;li&gt;Pricing change lead time ≤ 7 days (from request → production)&lt;/li&gt;
&lt;li&gt;Error budget policy and degradation behavior defined and tested&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI is helpful here to convert words into tests:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Rewrite these quality attributes as measurable fitness functions with owners and measurement frequency.”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Where you can, also define lightweight enforcement functions (the checks that make the fitness functions real), such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CI checks for contract compatibility, performance budgets, and security scanning&lt;/li&gt;
&lt;li&gt;Runtime checks/dashboards for SLOs and replay/audit workflows&lt;/li&gt;
&lt;li&gt;Release controls for pricing rule changes (approval workflow, versioning, rollback)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, establish a feedback loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Decide what telemetry and operational signals will cause you to revisit the ADR(s).&lt;/li&gt;
&lt;li&gt;Define who reviews it, how often, and what triggers escalation (error budget breach, audit failure, unacceptable performance).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;failure-modes-and-guardrails&#34;&gt;Failure modes and guardrails
&lt;/h2&gt;&lt;p&gt;AI‑assisted option exploration fails in predictable ways.&lt;/p&gt;
&lt;h3 id=&#34;failure-mode-novelty-bias&#34;&gt;Failure mode: novelty bias
&lt;/h3&gt;&lt;p&gt;The model prefers interesting architectures (event sourcing everywhere!) over boring ones that fit your org.&lt;/p&gt;
&lt;p&gt;Guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Require at least one “boring option” (e.g., modular monolith + façade).&lt;/li&gt;
&lt;li&gt;Score operational complexity with a high weight.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;failure-mode-hallucinated-constraints&#34;&gt;Failure mode: hallucinated constraints
&lt;/h3&gt;&lt;p&gt;The model invents rules you didn’t state (“must be multi‑region active‑active”).&lt;/p&gt;
&lt;p&gt;Guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every constraint in the output must trace to the Context Pack.&lt;/li&gt;
&lt;li&gt;Have a human reviewer mark each constraint as “given” vs “assumed”.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;failure-mode-overconfidence-in-estimates&#34;&gt;Failure mode: overconfidence in estimates
&lt;/h3&gt;&lt;p&gt;AI writes confident performance, cost, and migration timelines.&lt;/p&gt;
&lt;p&gt;Guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Treat all numbers as placeholders until measured.&lt;/li&gt;
&lt;li&gt;Force the model to provide ranges and uncertainty.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;failure-mode-decision-laundering&#34;&gt;Failure mode: decision laundering
&lt;/h3&gt;&lt;p&gt;Teams hide behind “the AI said” to avoid hard conversations.&lt;/p&gt;
&lt;p&gt;Guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Write ADRs in first person plural: “we chose… because…”&lt;/li&gt;
&lt;li&gt;Include the strongest argument against the chosen option.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;guardrail-adversarial-analysis-critique-each-stage&#34;&gt;Guardrail: adversarial analysis (critique each stage)
&lt;/h3&gt;&lt;p&gt;Option exploration gets safer and more accurate when you deliberately critique the output of each stage using adversarial analysis.
The goal is not to “win an argument” with the model; it’s to surface blind spots early.&lt;/p&gt;
&lt;p&gt;How to do it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use an alternative model (or at least a fresh chat) as a critic.&lt;/li&gt;
&lt;li&gt;Use multiple personas to force different failure modes to show up: security, architecture, engineering, operations, data, compliance/audit, enterprise platform.&lt;/li&gt;
&lt;li&gt;Require the critic to cite which input artifact/constraint each claim depends on (Context Pack vs assumption).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Prompt pack: see the &lt;strong&gt;Appendix: Adversarial review prompts&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;To avoid endless cycles of improvement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Timebox adversarial reviews (e.g., 30–60 minutes per stage).&lt;/li&gt;
&lt;li&gt;Cap review rounds (e.g., max 2 critique iterations per stage).&lt;/li&gt;
&lt;li&gt;Use an explicit stop rule: only iterate if a critique surfaces (1) a violated constraint, (2) an unmitigated existential risk, or (3) a missing artifact required for governance.&lt;/li&gt;
&lt;li&gt;Track deltas: capture changes as a short list (“what changed and why”) so you don’t re-litigate the same points.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;adoption-in-enterprise-reality&#34;&gt;Adoption in enterprise reality
&lt;/h2&gt;&lt;p&gt;In large organizations, option exploration is as much about governance and evidence as it is about diagrams.&lt;/p&gt;
&lt;h3 id=&#34;use-criticality-tiers&#34;&gt;Use criticality tiers
&lt;/h3&gt;&lt;p&gt;Not every system needs the same rigor. Define tiers (example):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tier 0 (revenue/regulatory critical):&lt;/strong&gt; full evidence bundle, ADR required, explicit fitness functions, architecture review.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tier 1 (important):&lt;/strong&gt; tradeoff matrix + ADR light.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tier 2 (low risk):&lt;/strong&gt; lightweight decision notes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;progressive-enforcement&#34;&gt;Progressive enforcement
&lt;/h3&gt;&lt;p&gt;Start with a small number of teams and make the workflow easy to adopt:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide Context Pack and ADR templates.&lt;/li&gt;
&lt;li&gt;Offer a “review clinic” for the first 3–5 decisions.&lt;/li&gt;
&lt;li&gt;Require evidence bundles only for Tier 0 initially.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;the-evidence-bundle&#34;&gt;The evidence bundle
&lt;/h3&gt;&lt;p&gt;What reviewers actually need is not more narrative; it’s better artifacts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Context Pack (bounded and safe)&lt;/li&gt;
&lt;li&gt;Options (with diagrams)&lt;/li&gt;
&lt;li&gt;Transition architectures (stepping‑stone states and stop‑anytime designs)&lt;/li&gt;
&lt;li&gt;Tradeoff matrix (with weights)&lt;/li&gt;
&lt;li&gt;Risks + experiments&lt;/li&gt;
&lt;li&gt;ADR(s) + fitness functions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can accelerate drafting every piece, but humans must validate each claim.&lt;/p&gt;
&lt;h2 id=&#34;conclusion-faster-exploration-better-accountability&#34;&gt;Conclusion: faster exploration, better accountability
&lt;/h2&gt;&lt;p&gt;AI makes it cheaper to explore architecture options and harder to pretend we didn’t consider alternatives.&lt;/p&gt;
&lt;p&gt;If you adopt the workflow above, you get outcomes that are faster, defensible, and executable.&lt;/p&gt;
&lt;p&gt;That’s the arc I care about in this series: quality → context → execution → feedback. AI helps in every stage, but only if we keep accountability where it belongs.&lt;/p&gt;
&lt;h2 id=&#34;appendix-templates-and-prompt-pack&#34;&gt;Appendix: templates and prompt pack
&lt;/h2&gt;&lt;h3 id=&#34;context-pack-checklist-copypaste&#34;&gt;Context Pack checklist (copy/paste)
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;Domain + goals&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; One‑paragraph problem statement (what is broken, what success looks like)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Top 3 business outcomes (e.g., weekly pricing changes, partner performance, audit readiness)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Non‑goals (what you are explicitly not trying to solve right now)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Regulatory/compliance constraints (explainability, retention, approvals)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Availability target (SLOs) and degradation rules&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Performance budget (p50/p95) and throughput expectations&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Scalability expectations (peak load, burst behavior, scaling limits, cost envelope)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Data classification (what can/can’t leave the boundary)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Budget and team constraints (people, skills, on‑call maturity)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Decision constraints (enterprise / business unit)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Compute strategy / technology constraints (cloud/on‑prem, regions, runtimes, managed services)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Security constraints (identity model, encryption standards, network segmentation, key management)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Technology constraints (approved stacks, platforms, vendors, lifecycle/end‑of‑support rules)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Patterns / practices constraints (integration patterns, deployment standards, SDLC controls)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Quality constraints (availability tiering, performance budgets, DR/RTO/RPO, observability requirements)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have internal decision documents (enterprise architecture standards, platform playbooks,
security policies), link them here.&lt;/p&gt;
&lt;p&gt;Where permitted, it can be useful to use MCP Servers to safely access these documents during
option evaluation so your options and target architecture align with enterprise and business‑unit
constraints.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Current state&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; C4‑ish diagram(s): context + container (keep it simple)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Critical flows: quote, re‑quote, bind, endorsement, renewal&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Known pain points and incident history (top 5)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; External dependencies (policy admin system, document generation, payments, CRM)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Decision criteria&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; The quality attributes that decide outcomes (e.g., auditability, evolvability, performance,
scalability)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; How you’ll measure them (even approximately)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;adversarial-review-prompts-copypaste&#34;&gt;Adversarial review prompts (copy/paste)
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;“Act as a security reviewer. Identify the top 10 security and data‑handling risks in this stage
output, including identity, secrets, encryption, tenancy, and audit trails. For each risk,
propose a mitigation and where it belongs (design‑time vs build‑time vs runtime).”&lt;/li&gt;
&lt;li&gt;“Act as an operations/SRE reviewer. Where will this fail at 2am? List the top failure modes,
required telemetry, runbooks, and the minimum viable operability baseline for each option.”&lt;/li&gt;
&lt;li&gt;“Act as an enterprise architect. Which enterprise/business‑unit constraints are violated or
likely to require exceptions? Identify the exact decision constraints impacted and what
evidence you would need to approve an exception.”&lt;/li&gt;
&lt;li&gt;“Act as a domain/audit reviewer. Can we reproduce a quote exactly months later? Identify what
must be versioned, retained, and replayable for auditability and explainability.”&lt;/li&gt;
&lt;li&gt;“Act as a skeptical staff engineer. Find contradictions, missing interfaces, and migration
steps that assume ‘magic rewrites’. Propose the smallest next step that reduces risk.”&lt;/li&gt;
&lt;li&gt;“Steelman the strongest case against the preferred option and against the preferred transition
path. What would make you reject it in a review?”&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Architecting Context: How Foundational Architecture Practices Power AI-Augmented Delivery</title>
        <link>https://humansreadcode.com/post/2025-10-31-architecting-context/</link>
        <pubDate>Fri, 31 Oct 2025 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2025-10-31-architecting-context/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2025-10-31-architecting-context/architecting-context.png" alt="Featured image of post Architecting Context: How Foundational Architecture Practices Power AI-Augmented Delivery" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;When we talk about AI-augmented delivery, that clarity becomes essential. Large language models and coding agents can’t intuit your intent — they need structured, high-quality context to operate safely and consistently.&lt;/p&gt;
&lt;p&gt;That’s where solid architecture practices come in. The methods defined by Neal Ford and Mark Richards in &lt;a class=&#34;link&#34; href=&#34;https://www.oreilly.com/library/view/fundamentals-of-software/9781098175504/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Fundamentals of Software Architecture&lt;/a&gt;
provide exactly the kind of disciplined thinking that fuels Context Engineering and Specification-Driven Development (SDD).&lt;/p&gt;
&lt;p&gt;Let’s break that down.&lt;/p&gt;
&lt;h2 id=&#34;1-architecture-creates-context&#34;&gt;1. Architecture Creates Context
&lt;/h2&gt;&lt;p&gt;Every time we make an architectural decision, we’re not just shaping a system — we’re creating context. Each artifact, model, and record we produce explains how the system works, why we made certain tradeoffs, and what rules or constraints apply.&lt;/p&gt;
&lt;p&gt;That context becomes a reusable source of truth for both humans and AI systems.&lt;/p&gt;
&lt;p&gt;Good architecture doesn’t just describe; it defines the decision space. It gives structure to reasoning — and that’s what context engineering depends on.&lt;/p&gt;
&lt;h2 id=&#34;2-the-architecture-context-cycle&#34;&gt;2. The Architecture Context Cycle
&lt;/h2&gt;&lt;p&gt;The cycle starts with business intent and ends with operational feedback. Each step creates artifacts that capture decisions, tradeoffs, and constraints — the building blocks of high-quality context.&lt;/p&gt;
&lt;h3 id=&#34;step-1-understand-the-key-business-drivers&#34;&gt;Step 1. Understand the Key Business Drivers
&lt;/h3&gt;&lt;p&gt;Start with why. Every architecture decision should connect back to the business drivers — performance, agility, cost, security, compliance, or growth. These drivers become your north star and define what “good” looks like for the system.&lt;/p&gt;
&lt;p&gt;Document them clearly. They’ll influence every step that follows and form the foundation of your architecture context.&lt;/p&gt;
&lt;h3 id=&#34;step-2-identify-the-driving-architecture-characteristics&#34;&gt;Step 2. Identify the Driving Architecture Characteristics
&lt;/h3&gt;&lt;p&gt;From the business drivers, extract the key architecture characteristics. Things like scalability, availability, and modifiability aren’t just buzzwords — they are the measurable qualities that shape the architecture.&lt;/p&gt;
&lt;p&gt;These characteristics turn abstract goals into something concrete and testable. They’re also critical inputs for AI agents — they describe what matters most when generating or evaluating solutions.&lt;/p&gt;
&lt;h3 id=&#34;step-3-select-candidate-architecture-styles&#34;&gt;Step 3. Select Candidate Architecture Styles
&lt;/h3&gt;&lt;p&gt;Now explore the options. Based on those characteristics, select architecture styles that fit — microservices, modular monolith, event-driven, layered, hexagonal, or combinations.&lt;/p&gt;
&lt;p&gt;Each style has strengths and tradeoffs. Document them. You’re building a map of possibilities that defines the constraints and degrees of freedom in your design. This becomes valuable context for humans and machines alike.&lt;/p&gt;
&lt;h3 id=&#34;step-4-apply-domain-to-architecture-isomorphism&#34;&gt;Step 4. Apply Domain-to-Architecture Isomorphism
&lt;/h3&gt;&lt;p&gt;This is where the real matching happens. Take the problem domain and map it to each candidate architecture. You’re looking for isomorphism — where the shape of your domain aligns with the shape of the architecture.&lt;/p&gt;
&lt;p&gt;This alignment tells you which style fits naturally and where friction exists. Capturing this analysis as an artifact provides rich, instructive context for anyone (human or AI) who needs to understand why you made that call.&lt;/p&gt;
&lt;h3 id=&#34;step-5-align-across-the-nine-intersections-of-architecture&#34;&gt;Step 5. Align Across the Nine Intersections of Architecture
&lt;/h3&gt;&lt;p&gt;Neal Ford and Mark Richards identify nine intersections where architecture meets the rest of the ecosystem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implementation&lt;/li&gt;
&lt;li&gt;Infrastructure&lt;/li&gt;
&lt;li&gt;Data topologies&lt;/li&gt;
&lt;li&gt;Engineering practices&lt;/li&gt;
&lt;li&gt;Team topologies&lt;/li&gt;
&lt;li&gt;Systems integration&lt;/li&gt;
&lt;li&gt;Business environment&lt;/li&gt;
&lt;li&gt;Enterprise alignment&lt;/li&gt;
&lt;li&gt;Generative AI&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each intersection adds constraints and dependencies — and each one adds context. When documented, these connections help AI systems understand how architecture fits within organisational and operational realities.&lt;/p&gt;
&lt;h3 id=&#34;step-6-perform-an-architecture-risk-analysis&#34;&gt;Step 6. Perform an Architecture Risk Analysis
&lt;/h3&gt;&lt;p&gt;Every architecture choice carries risk. Assess it, document it, and define mitigation strategies. These risk artifacts become part of the knowledge base for future decisions and for AI systems that need to understand tradeoffs.&lt;/p&gt;
&lt;p&gt;When context engineering references these risks, AI agents can make safer, more informed recommendations.&lt;/p&gt;
&lt;h3 id=&#34;step-7-identify-nfrs-fitness-functions-and-enforcement-functions&#34;&gt;Step 7. Identify NFRs, Fitness Functions, and Enforcement Functions
&lt;/h3&gt;&lt;p&gt;This step defines how quality is measured and maintained. Non-functional requirements (NFRs), fitness functions, and enforcement functions turn architectural intent into measurable constraints.&lt;/p&gt;
&lt;p&gt;They set the quality gates. In Context Engineering, they become guardrails — standards that AI systems can apply automatically to ensure consistency and compliance.&lt;/p&gt;
&lt;h3 id=&#34;step-8-document-decisions-in-architecture-decision-records&#34;&gt;Step 8. Document Decisions in Architecture Decision Records
&lt;/h3&gt;&lt;p&gt;Every major decision should live in an Architecture Decision Record (ADR). An ADR tells you what decision was made, why it was made, and what alternatives were considered.&lt;/p&gt;
&lt;p&gt;They’re short, structured, and easy to read — which makes them perfect for both people and LLMs. When included in the architecture context, ADRs give AI systems traceable reasoning and historical perspective.&lt;/p&gt;
&lt;h3 id=&#34;step-9-establish-feedback-loops&#34;&gt;Step 9. Establish Feedback Loops
&lt;/h3&gt;&lt;p&gt;Architecture isn’t a one-and-done process. Use telemetry, operational insights, and incident reviews to feed back into your architecture decisions.&lt;/p&gt;
&lt;p&gt;This creates a living context — one that reflects the real-world performance and evolution of your systems. AI-assisted feedback loops can even help detect drift, monitor adherence, and flag emerging risks.&lt;/p&gt;
&lt;h2 id=&#34;3-architecture-artifacts-as-context-assets&#34;&gt;3. Architecture Artifacts as Context Assets
&lt;/h2&gt;&lt;p&gt;Each step in this cycle produces something useful — and together, they form a high-quality, interconnected knowledge system:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Business drivers define &lt;strong&gt;purpose&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Architecture characteristics define &lt;strong&gt;priorities&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Styles and isomorphism define &lt;strong&gt;structure&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Intersections define &lt;strong&gt;dependencies&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Risks and NFRs define &lt;strong&gt;guardrails&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;ADRs define &lt;strong&gt;reasoning&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Feedback defines &lt;strong&gt;evolution&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When structured and stored properly — Markdown, YAML, or Mermaid — these artifacts become the context substrate that Context Engineering and Specification-Driven Development rely on.&lt;/p&gt;
&lt;h2 id=&#34;4-the-role-of-c4-diagrams&#34;&gt;4. The Role of C4 Diagrams
&lt;/h2&gt;&lt;p&gt;C4 diagrams bring structure to the visual side of context. They move from broad to detailed, giving both humans and AI a layered understanding of the system.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Level 1: Context — What the system is and who it interacts with.&lt;/li&gt;
&lt;li&gt;Level 2: Container — Major deployable units and responsibilities.&lt;/li&gt;
&lt;li&gt;Level 3: Component — Key modules and internal flows.&lt;/li&gt;
&lt;li&gt;Level 4: Code — The implementation detail.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Captured as code (Mermaid or Structurizr DSL), these diagrams are machine-readable. That means they can be included directly in your context pipeline to guide code generation, architecture validation, and SDD workflows.&lt;/p&gt;
&lt;h2 id=&#34;5-from-architecture-to-ai-augmented-delivery&#34;&gt;5. From Architecture to AI-Augmented Delivery
&lt;/h2&gt;&lt;p&gt;Architecture produces the clearest, richest form of context an organisation can have. When we feed that context into AI-augmented workflows, we bridge strategy and execution.&lt;/p&gt;
&lt;p&gt;Here’s the chain of context: &lt;em&gt;Business Drivers → Characteristics → Styles → Domain Mapping → Intersections → Risks → NFRs → ADRs → Feedback&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That chain doesn’t just describe the system — it teaches it. Each link provides a layer of understanding that Context Engineering and SDD can use to generate reliable, explainable, and compliant outputs.&lt;/p&gt;
&lt;h2 id=&#34;6-architecture-as-context-infrastructure&#34;&gt;6. Architecture as Context Infrastructure
&lt;/h2&gt;&lt;p&gt;Architecture is no longer just about design decisions. It’s about building the context infrastructure that allows AI systems and humans to collaborate safely and effectively.&lt;/p&gt;
&lt;p&gt;When we apply these practices consistently, we create architectures that are understandable by machines and trustworthy by design.&lt;/p&gt;
&lt;p&gt;That’s how we move from architecture as craft to architecture as context — the foundation of AI-augmented modernisation.
What Context Infrastructure Really Means&lt;/p&gt;
&lt;p&gt;When we talk about context infrastructure, we’re not talking about servers, networks, or pipelines. We’re talking about the architecture of knowledge — the structured, reusable foundation that makes our systems understandable by both humans and machines.&lt;/p&gt;
&lt;p&gt;It’s everything that defines intent and meaning: business drivers, architecture characteristics, styles, NFRs, fitness and enforcement functions, ADRs, standards, diagrams, and the feedback loops that connect them. Captured in consistent, machine-readable formats like Markdown, YAML, or DSLs, these artifacts form a living system of knowledge that defines why things exist, how they work, and what good looks like.&lt;/p&gt;
&lt;p&gt;This is what allows AI systems to reason safely within enterprise boundaries. It turns architecture from static documentation into an active system of context — continuously accessible, verifiable, extensible, and executable. That’s the real foundation of AI-augmented delivery.&lt;/p&gt;
&lt;h2 id=&#34;7-ai-as-a-partner-in-the-architecture-process&#34;&gt;7. AI as a Partner in the Architecture Process
&lt;/h2&gt;&lt;p&gt;AI isn’t replacing architects — it’s extending their reach. At each step of this process, AI can act as a force multiplier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Business Drivers — Summarise drivers from documentation, highlight inconsistencies, and suggest clarifying questions and missing context.&lt;/li&gt;
&lt;li&gt;Architecture Characteristics — Suggest architecture characteristics appropriate for the stated key business drivers.&lt;/li&gt;
&lt;li&gt;Candidate Styles — Propose architecture styles that align with the stated drivers and characteristics.&lt;/li&gt;
&lt;li&gt;Domain-to-Architecture Mapping — Generate architecture diagrams as code, validate the fit between the problem domain and architecture components.&lt;/li&gt;
&lt;li&gt;Intersections — Surface dependency conflicts across infrastructure, data, team topologies, and constraints.&lt;/li&gt;
&lt;li&gt;Risk Analysis — Identify potential failure points, gaps, or performance risks based on prior patterns.&lt;/li&gt;
&lt;li&gt;NFRs and Fitness Functions — Grade coverage, suggest measurable metrics, and flag gaps.&lt;/li&gt;
&lt;li&gt;ADRs — Review language for clarity, completeness, and rationale consistency.&lt;/li&gt;
&lt;li&gt;Feedback Loops — Analyse telemetry to detect drift and recommend architectural refinements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can also grade and quality gate the outputs of each step — checking for structure, completeness, clarity, and alignment with established standards. By embedding these checks into the workflow, we build a continuous assurance layer that reinforces good practice instead of inspecting for it later.&lt;/p&gt;
&lt;p&gt;It’s a feedback loop: better architecture creates better context for AI, and better AI augments the quality of architecture. That’s how we raise the floor on architectural excellence while freeing humans to focus on the creative, strategic, and system-level thinking we excel at.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>From Quality to Context to Execution: Engineering the Next Stage of AI-Augmented Delivery</title>
        <link>https://humansreadcode.com/post/2025-10-14-quality-context-execution/</link>
        <pubDate>Tue, 14 Oct 2025 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2025-10-14-quality-context-execution/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2025-10-14-quality-context-execution/quality-context-execution.png" alt="Featured image of post From Quality to Context to Execution: Engineering the Next Stage of AI-Augmented Delivery" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;This is where Context Engineering comes in: the discipline of designing, curating, and maintaining structured, high-quality context across the SDLC so AI systems can operate effectively within enterprise boundaries.&lt;/p&gt;
&lt;h2 id=&#34;1-from-built-in-quality-to-high-quality-context&#34;&gt;1. From Built-In Quality to High-Quality Context
&lt;/h2&gt;&lt;p&gt;Every artifact we create through the SDLC — from requirements to architecture, from test cases to runbooks — contributes to the context fabric of our organisation. When quality is built in at each step, that fabric becomes strong, consistent, and richly descriptive — the perfect substrate for AI augmentation.&lt;/p&gt;
&lt;p&gt;Within this context are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;High-quality requirements — acceptance criteria, use cases, and user journeys&lt;/li&gt;
&lt;li&gt;Architecture artifacts — key business drivers, architecture characteristics, risk analysis, NFRs, fitness functions, and diagrams&lt;/li&gt;
&lt;li&gt;Enterprise constraints — standards, decisions, patterns, tooling, technology, security&lt;/li&gt;
&lt;li&gt;Operational knowledge — runbooks, observability frameworks, and lessons learned&lt;/li&gt;
&lt;li&gt;Consistent engineering practices — standards, quality targets, templates, automation, and metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, these form a shared system of understanding — the living context that explains not only what we are building, but how and why we build it that way.&lt;/p&gt;
&lt;p&gt;Every time we work with an AI system, we must ensure that this context — from enduring architectural principles to the most recent design decisions — is available and relevant. Mechanisms such as RAG (Retrieval-Augmented Generation) and MCP (Model Context Protocol) allow us to dynamically load and update this information, ensuring every interaction starts well-informed and stays aligned as work evolves.&lt;/p&gt;
&lt;p&gt;And here’s where it gets interesting: The same LLMs that depend on high-quality context can also help us maintain and improve it.&lt;/p&gt;
&lt;p&gt;AI can assist in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reviewing and grading artifacts for completeness or consistency&lt;/li&gt;
&lt;li&gt;Detecting drift or outdated information&lt;/li&gt;
&lt;li&gt;Suggesting missing dependencies or unclear logic&lt;/li&gt;
&lt;li&gt;Generating structured documentation and linking related artifacts automatically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This creates a reinforcing feedback loop — humans produce and refine context, LLMs enhance and maintain it, and together they raise the quality bar over time.&lt;/p&gt;
&lt;h2 id=&#34;2-why-context-matters-llms-are-new-hires&#34;&gt;2. Why Context Matters: LLMs Are New Hires
&lt;/h2&gt;&lt;p&gt;Every time you start a new session with a large language model, you’re effectively onboarding a brand-new engineer.&lt;/p&gt;
&lt;p&gt;The model understands coding — but it has no idea how your business operates, what your architectural patterns look like, how your teams collaborate, or what “good” means in your organisation.&lt;/p&gt;
&lt;p&gt;We don’t have the luxury of letting an LLM shadow a senior engineer for months, observe pull requests, attend design reviews, or absorb the organisation’s nuances organically. Instead, we must deliver that understanding through context — structured, high-quality, and relevant every time.&lt;/p&gt;
&lt;p&gt;That’s why Context Engineering is essential. Each new interaction with an AI agent requires us to re-establish a shared understanding of standards, goals, and constraints. The richer and more structured the context, the faster the “onboarding” — and the better the outcomes.&lt;/p&gt;
&lt;p&gt;The side benefit? Humans thrive on this same structure. Well-formed context makes engineers more productive, decisions more traceable, and knowledge more durable.&lt;/p&gt;
&lt;h2 id=&#34;3-from-context-to-code-specification-driven-development&#34;&gt;3. From Context to Code: Specification-Driven Development
&lt;/h2&gt;&lt;p&gt;Once we’ve built up high-quality context, we can start turning that context into action through Specification-Driven Development (SDD) — a workflow that transforms structured context into executable specifications for coding agents.&lt;/p&gt;
&lt;p&gt;Using tools like Spec Kit, we can orchestrate this process step by step:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Constitution – Load foundational context, standards, and objectives into the workflow to ground subsequent steps.&lt;/li&gt;
&lt;li&gt;High-level specifications – Define what to build (requirements, user stories, and goals).&lt;/li&gt;
&lt;li&gt;Clarifications – Resolve ambiguity and fill gaps before technical planning.&lt;/li&gt;
&lt;li&gt;Technical plans – Create detailed implementation plans aligned to the chosen tech stack.&lt;/li&gt;
&lt;li&gt;Tasks – Generate actionable implementation tasks.&lt;/li&gt;
&lt;li&gt;Artifact analysis – Check consistency and coverage across generated artifacts.&lt;/li&gt;
&lt;li&gt;Implementation – Have the coding agent execute the tasks to build the feature according to plan.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these artifacts is stored within the repository — versioned, reviewable, and auditable — giving both humans and coding agents shared visibility and traceability. Furthermore, these artifacts can be refined and tuned by humans and agents at each step in the SDD process.&lt;/p&gt;
&lt;p&gt;By curating these executable specifications, we create a clear, structured foundation that allows multiple coding agents to work in parallel — each implementing different tasks marked “parallel” within a specification, or on separate specifications within the same codebase. This parallelisation becomes practical and safe when the codebase is modular, well-structured, and covered by robust tests.&lt;/p&gt;
&lt;p&gt;Where systems are not yet ready for this level of parallelised automation, SDD provides a path forward. We can use the same specification-driven workflow to incrementally refactor and improve codebases — step by step — until they reach the maturity required for safe, concurrent AI collaboration.&lt;/p&gt;
&lt;p&gt;In this way, SDD is both a delivery framework and a modernisation engine. It helps us scale the work of development safely across human and AI contributors while continuously improving the technical foundation underneath.&lt;/p&gt;
&lt;p&gt;This approach eliminates brittle &amp;ldquo;long prompt&amp;rdquo; interactions and replaces them with a repeatable, inspectable workflow, where each stage can be reviewed, refined, and reused.&lt;/p&gt;
&lt;h2 id=&#34;4-the-new-skill-context-engineering&#34;&gt;4. The New Skill: Context Engineering
&lt;/h2&gt;&lt;p&gt;The emerging skill in AI-augmented delivery isn’t prompting — it’s context engineering.&lt;/p&gt;
&lt;p&gt;Prompting is transient; context endures. Prompting says “do this”; context says “here’s how we do things here.”&lt;/p&gt;
&lt;p&gt;In this new paradigm, the role of the engineer evolves from coder to context architect — someone who builds and maintains the structured environment that allows AI agents to work effectively and safely within enterprise constraints.&lt;/p&gt;
&lt;p&gt;And while this helps AI coding agents perform better, it also strengthens human teams — creating a shared foundation of clarity, standards, and alignment across the delivery ecosystem.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Every engineer — human or AI — performs best when given clarity, context, and structure.&lt;/p&gt;
&lt;p&gt;By combining built-in quality with Context Engineering and Specification-Driven Development, we create an environment where AI coding agents and human engineers work together — safely, efficiently, and at scale.&lt;/p&gt;
&lt;p&gt;We can&amp;rsquo;t teach LLMs our culture through osmosis — we must encode it through context. That&amp;rsquo;s how we transform modernisation from an experiment into an engineered system of continuous understanding.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>AI-Augmented Quality Across the SDLC: Building It In, Not Testing It In</title>
        <link>https://humansreadcode.com/post/2025-09-27-ai-augmented-quality/</link>
        <pubDate>Sat, 27 Sep 2025 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2025-09-27-ai-augmented-quality/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2025-09-27-ai-augmented-quality/ai-augmented-quality.png" alt="Featured image of post AI-Augmented Quality Across the SDLC: Building It In, Not Testing It In" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Too often, enterprises treat quality as a reactionary step during testing. By then, it&amp;rsquo;s too late – defects are costly, drift is entrenched, and risks multiply. The better path is to treat quality as a continuous discipline, woven through requirements, architecture, build, and operations.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how quality can – and must – be designed into every stage of the lifecycle, with AI serving as an augmentation layer to scale and strengthen the practice.&lt;/p&gt;
&lt;h2 id=&#34;1-requirements-building-clarity-from-the-start&#34;&gt;1. Requirements: Building clarity from the start
&lt;/h2&gt;&lt;p&gt;High-quality requirements are the foundation of everything that follows. Yet requirements are often rushed, inconsistent, or ambiguous. To build quality in, we must:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ask the right clarifying questions up front.&lt;/li&gt;
&lt;li&gt;Capture requirements in standardised templates.&lt;/li&gt;
&lt;li&gt;Define clear, testable acceptance criteria.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI strengthens this process by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Suggesting questions we may not have thought of.&lt;/li&gt;
&lt;li&gt;Highlighting ambiguities, contradictions, or missing edge cases.&lt;/li&gt;
&lt;li&gt;Grading requirements against quality standards.&lt;/li&gt;
&lt;li&gt;Enhancing acceptance criteria for completeness and clarity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The outcome: requirements that are sharper, more consistent, and ready to drive quality downstream.&lt;/p&gt;
&lt;h2 id=&#34;2-architecture--design-guardrails-for-sustainable-solutions&#34;&gt;2. Architecture &amp;amp; Design: Guardrails for sustainable solutions
&lt;/h2&gt;&lt;p&gt;Architecture decisions shape the system&amp;rsquo;s long-term health. Quality at this stage means ensuring that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Critical business needs are mapped to the right architecture characteristics.&lt;/li&gt;
&lt;li&gt;Candidate styles are identified through those characteristics.&lt;/li&gt;
&lt;li&gt;The most appropriate architecture style(s) is chosen for the given problem domain.&lt;/li&gt;
&lt;li&gt;Risks are identified, with mitigations designed in.&lt;/li&gt;
&lt;li&gt;Decisions are captured throughout in Architecture Decision Records (ADRs) capturing the &amp;ldquo;why&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Designs are expressed as living artifacts (e.g., C4 diagrams in mermaid syntax).&lt;/li&gt;
&lt;li&gt;Fitness functions continuously measure the adherence of the implementation to the architecture design.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI can augment every step here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Suggesting architecture options and trade-offs.&lt;/li&gt;
&lt;li&gt;Detecting drift between intended and actual designs.&lt;/li&gt;
&lt;li&gt;Rapidly producing architecture diagrams and design models.&lt;/li&gt;
&lt;li&gt;Grading outputs against standardised practices.&lt;/li&gt;
&lt;li&gt;Architecture artifacts feed context engineering.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By building quality into architecture, we reduce risk, improve alignment, and create strong feedback loops as systems evolve.&lt;/p&gt;
&lt;h2 id=&#34;3-build--test-raising-the-engineering-baseline&#34;&gt;3. Build &amp;amp; Test: Raising the engineering baseline
&lt;/h2&gt;&lt;p&gt;The build and test phases benefit enormously from high-quality context established upstream. Instead of scrambling to &amp;ldquo;test in&amp;rdquo; quality, we now have rich context to leverage where we can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use AI to suggest additional test cases, edge cases, and coverage improvements.&lt;/li&gt;
&lt;li&gt;Apply standardised engineering practices (with AI verifying compliance).&lt;/li&gt;
&lt;li&gt;Leverage the testing pyramid effectively to minimise costly duplication.&lt;/li&gt;
&lt;li&gt;Focus humans on high-value work in the problem space, while AI enforces the basics.&lt;/li&gt;
&lt;li&gt;Enable developers to parallelise certain tasks which would in the past be done sequentially.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where context engineering and Specification-Driven Development (SDD) shines – combining high-quality context with engineering standards so AI can guide teams toward compliant, consistent, and valuable outputs.&lt;/p&gt;
&lt;h2 id=&#34;4-operations-predict-failures-detect-anomalies&#34;&gt;4. Operations: Predict failures, detect anomalies
&lt;/h2&gt;&lt;p&gt;Quality does not end at release – it extends into how systems behave in production. Operations is where organisations often pay the price for weak upstream practices, but with AI augmentation we can move from reactive firefighting to proactive assurance.&lt;/p&gt;
&lt;p&gt;AI enables operations to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Predict failures before they occur, allowing preventive action.&lt;/li&gt;
&lt;li&gt;Detect anomalies in real time, spotting drift or unusual behavior early.&lt;/li&gt;
&lt;li&gt;Correlate signals across monitoring, logging, and observability data.&lt;/li&gt;
&lt;li&gt;Feed insights back into design and build, creating a closed-loop lifecycle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This shifts operations from a cost center into a learning system that strengthens quality everywhere else.&lt;/p&gt;
&lt;h2 id=&#34;conclusion-quality-is-not-a-phase&#34;&gt;Conclusion: Quality is not a phase
&lt;/h2&gt;&lt;p&gt;The lesson is clear: &lt;strong&gt;quality cannot be tested in – it must be built in&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When quality is designed into requirements, architecture, build, and operations – and when AI augments human expertise at each stage – modernisation becomes safer, more resilient, and more scalable.&lt;/p&gt;
&lt;p&gt;This is how we lower transformation risk, empower engineers to innovate, and create a foundation where AI augmentation thrives.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Modernisation Guardrails &amp; AI</title>
        <link>https://humansreadcode.com/post/2025-09-07-modernisation-guardrails/</link>
        <pubDate>Sun, 07 Sep 2025 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2025-09-07-modernisation-guardrails/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2025-09-07-modernisation-guardrails/modernisation-guardrails.png" alt="Featured image of post Modernisation Guardrails &amp; AI" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Without these standards applied, measured, and enforced across the SDLC — from requirements and analysis to architecture, design, build, test, security, release, and operations — enterprises risk fragmentation, drift, and poor outcomes.&lt;/p&gt;
&lt;h2 id=&#34;the-path-forward&#34;&gt;The Path Forward
&lt;/h2&gt;&lt;p&gt;The path forward is clear:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Define standards&lt;/strong&gt; - set consistent expectations across the SDLC.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable easy adoption&lt;/strong&gt; - provide frameworks, tooling, and practices for easy uptake.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Measure adherence&lt;/strong&gt; - track metrics, targets, and thresholds across the SDLC.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ensure with care&lt;/strong&gt; - apply governance functions within criticality and organisational constraints.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;quality-gates-as-more-than-checklists&#34;&gt;Quality Gates as More Than Checklists
&lt;/h2&gt;&lt;p&gt;When these foundations are in place, quality gates become more than checklists. They provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Guardrails&lt;/strong&gt; that ensure the right activities happen, at the right stage, at the right quality.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability and trust&lt;/strong&gt; — not just detecting drift, but building confidence in the process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The freedom for engineers to innovate&lt;/strong&gt;, knowing the basics are safeguarded.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;where-ai-comes-in&#34;&gt;Where AI Comes In
&lt;/h2&gt;&lt;p&gt;And here&amp;rsquo;s where human-directed AI comes in. Quality gates grounded in consistent standards create the perfect substrate for AI augmentation. AI can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Grade outputs against standards&lt;/strong&gt;, ensuring consistency and reliability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Alert on drift or non-adherence&lt;/strong&gt;, helping teams course-correct early.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automate repetitive compliance checks&lt;/strong&gt;, freeing humans for higher-value work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leverage high quality context in context engineering&lt;/strong&gt; to produce smarter, more relevant AI-driven decisions.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;That&amp;rsquo;s how modernisation, foundations, and AI intersect: quality gates as the bridge from standards to safe AI augmentation.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Modernisation &amp; AI</title>
        <link>https://humansreadcode.com/post/2025-08-23-modernisation-ai/</link>
        <pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2025-08-23-modernisation-ai/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2025-08-23-modernisation-ai/modernisation-ai.png" alt="Featured image of post Modernisation &amp; AI" /&gt;&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;Now, with the rise of AI and LLMs, we&amp;rsquo;re at an inflection point. The reality is that AI initiatives will struggle — or fail — without the solid architecture, engineering, and standards that modernisation provides.&lt;/p&gt;
&lt;h2 id=&#34;where-modernisation-and-ai-converge&#34;&gt;Where Modernisation and AI Converge
&lt;/h2&gt;&lt;p&gt;Where modernisation and AI converge, we can industrialise the SDLC:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Built-in governance&lt;/strong&gt;: Architecture standards, engineering standards, fitness functions, and quality gates — enforced by AI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Quality everywhere&lt;/strong&gt;: Embedding automated quality measures across the SDLC ensures quality is built into the product and issues are caught early and continuously, not late in the cycle.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More time in the problem space&lt;/strong&gt;: Engineers spend less time battling compliance, and more time planning early, iterating rapidly, and solving meaningful business problems.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context engineering&lt;/strong&gt;: High-quality requirements, data, and standardised practices give AI the knowledge it needs to reason safely about complex systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-future-of-enterprise-delivery&#34;&gt;The Future of Enterprise Delivery
&lt;/h2&gt;&lt;p&gt;The next evolution of enterprise delivery is AI-augmented modernisation and the industrialised SDLC.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be sharing patterns and lessons as I explore this frontier — bridging architecture, engineering, quality, and AI to create sustainable, scalable delivery.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>About</title>
        <link>https://humansreadcode.com/page/about/</link>
        <pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/page/about/</guid>
        <description>&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/page/about/avatar.jpg&#34;
	width=&#34;200&#34;
	height=&#34;200&#34;
	srcset=&#34;https://humansreadcode.com/page/about/avatar_hu13650519016259257788.jpg 480w, https://humansreadcode.com/page/about/avatar_hu14315565564303296689.jpg 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Picture of Karl Kyck&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;100&#34;
		data-flex-basis=&#34;240px&#34;
	
&gt;
&lt;em&gt;Karl Kyck&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hi, I’m Karl Kyck, a software architect specialising in managing risk and complexity in large enterprise software systems. I focus on delivering optimal solutions that drive real business value through sustainable software engineering practices.&lt;/p&gt;
&lt;p&gt;HUMANSREADCODE is dedicated to promoting sustainable software engineering practices and demonstrating how this approach enables the creation of effective, value-driven solutions. This blog explores topics such as software architecture, engineering practices, organisational structure, delivery methodologies, and product-thinking. By integrating these elements, we aim to help you build the right product, at the right time, using the right methods.&lt;/p&gt;
&lt;p&gt;You can follow me on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://linkedin.com/in/karlkyck&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Archives</title>
        <link>https://humansreadcode.com/page/archives/</link>
        <pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/page/archives/</guid>
        <description></description>
        </item>
        <item>
        <title>Privacy</title>
        <link>https://humansreadcode.com/page/privacy/</link>
        <pubDate>Sat, 21 Dec 2024 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/page/privacy/</guid>
        <description>&lt;p&gt;We collect usage data using google analytics for the purposes of visualizing the traffic on this website.&lt;/p&gt;
&lt;p&gt;All data is anonymized and we do not sell or share any data with third parties.&lt;/p&gt;
&lt;p&gt;If you choose to deny, no info will be collected whatsoever.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>The Known and Unknown Framework</title>
        <link>https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/</link>
        <pubDate>Sat, 12 Aug 2023 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/known-unknown.png" alt="Featured image of post The Known and Unknown Framework" /&gt;&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/known-unknown.png&#34;
	width=&#34;768&#34;
	height=&#34;864&#34;
	srcset=&#34;https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/known-unknown_hu2536220541307784154.png 480w, https://humansreadcode.com/post/2023-08-12-known-unknown-frameworks/known-unknown_hu6800705039147781747.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The Known and Unknown Framework&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;88&#34;
		data-flex-basis=&#34;213px&#34;
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction
&lt;/h2&gt;&lt;p&gt;In the complex and ever-evolving landscape of software development, operating in the gray, with it’s many uncertainties and ambiguities, is a reality that every software engineer faces. It is in this realm of uncertainty, the “Known and Unknown Framework” emerges as a guiding beacon, offering a structured approach to achieve continuous clarity of purpose. This framework empowers developers to identify the facts upon which their work can be firmly grounded, driving successful project outcomes.&lt;/p&gt;
&lt;h2 id=&#34;the-known-and-unknown-framework&#34;&gt;The Known and Unknown Framework
&lt;/h2&gt;&lt;p&gt;At its core, the Known and Unknown Framework is a powerful tool that helps teams navigate the intricacies of the gray area by classifying information into distinct categories: known knowns, known unknowns, unknown knowns, and unknown unknowns. Let’s delve into each of these categories to understand their significance and how they contribute to achieving clarity of purpose.&lt;/p&gt;
&lt;h3 id=&#34;known-knowns-the-foundation-of-solid-work&#34;&gt;Known Knowns: The Foundation of Solid Work
&lt;/h3&gt;&lt;p&gt;Known knowns represent the bedrock of factual information upon which sound decisions and work can be built. These are the certainties, the established truths that provide a reliable starting point for any software development endeavor. For example, well-documented specifications, existing codebase details, and proven algorithms fall into this category. Leveraging known knowns allows developers to undertake tasks with confidence, knowing they are on a solid foundation.&lt;/p&gt;
&lt;h3 id=&#34;known-unknowns-igniting-the-quest-for-answers&#34;&gt;Known Unknowns: Igniting the Quest for Answers
&lt;/h3&gt;&lt;p&gt;Known unknowns are the questions that arise when faced with uncertainties. They represent gaps in understanding that, once addressed, can transform ambiguity into clarity. Embracing known unknowns is key to proactive problem-solving and ensuring that no stone is left unturned. These questions become a roadmap for further exploration, research, and discovery, enabling developers to convert uncertainties into known knowns.&lt;/p&gt;
&lt;h3 id=&#34;unknown-knowns-harnessing-intuition&#34;&gt;Unknown Knowns: Harnessing Intuition
&lt;/h3&gt;&lt;p&gt;Sometimes, software development engineers possess a deep-rooted intuition that guides their decisions. These are the unknown knowns, the unspoken hunches that hold untapped potential. By acknowledging and converting these intuitive insights into known unknowns (questions), developers can subject them to scrutiny, leading to a deeper understanding of their value and relevance. This transformation ensures that intuition is not lost but rather refined and channeled toward concrete outcomes.&lt;/p&gt;
&lt;h3 id=&#34;unknown-unknowns-embracing-the-journey-of-discovery&#34;&gt;Unknown Unknowns: Embracing the Journey of Discovery
&lt;/h3&gt;&lt;p&gt;The realm of the unknown unknowns is where groundbreaking discoveries lie in wait. These are the surprises, the unforeseen challenges, and the unexplored opportunities that emerge as development progresses. Engaging in deliberate discovery sessions and research efforts helps developers unveil these hidden treasures, gradually transforming them into known unknowns and even known knowns. By proactively seeking the unknown, developers can expand their horizons and stay ahead in a rapidly evolving field.&lt;/p&gt;
&lt;h2 id=&#34;putting-the-framework-into-action&#34;&gt;Putting the Framework into Action
&lt;/h2&gt;&lt;p&gt;To harness the power of the Known and Unknown Framework, consider the following step-by-step process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Assumptions go into the Known Unknowns section&lt;/strong&gt; – assumptions need to be turned into facts, so start there.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Populate the Known Knowns and Known Unknowns Quadrants&lt;/strong&gt;: Work with what you know and what you don’t know. This establishes a clear starting point for your project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Leverage Known Knowns for Solid Work&lt;/strong&gt;: Utilize facts as building blocks for tasks that require certainty. These established facts become the pillars upon which your work stands.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iterative Clarity Building&lt;/strong&gt;: Continuously identify new known knowns, turn known unknowns into known knowns, and prioritize tasks based on this evolving clarity. This iterative process ensures that your project remains aligned with emerging insights.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Explore the Unknowns&lt;/strong&gt;: Use brainstorming sessions to uncover unknown knowns, use discovery and research activities to unveil unknown unknowns. Turn these into known unknowns and continue the cycle.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;In the dynamic world of software development, achieving continuous clarity of purpose amid uncertainties is a formidable challenge. The Known and Unknown Framework emerges as a beacon of guidance, offering a structured approach to categorize and leverage information effectively. By harnessing the power of known knowns, known unknowns, unknown knowns, and unknown unknowns, software development engineers can navigate the gray area with confidence, making informed decisions, and ultimately delivering successful outcomes. Remember, assumptions are the silent assassins that must be eliminated – this framework equips you to replace assumptions with solid facts, paving the way for excellence in your projects.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Text generated from my summarised list of bullet points by ChatGPT, August 12, 2023, OpenAI, &lt;a class=&#34;link&#34; href=&#34;https://chat.openai.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://chat.openai.com&lt;/a&gt;. Edited for style and content.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>Automation testing as an upfront software design technique</title>
        <link>https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/</link>
        <pubDate>Thu, 10 Aug 2023 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/the-homer.png" alt="Featured image of post Automation testing as an upfront software design technique" /&gt;&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/the-homer.png&#34;
	width=&#34;660&#34;
	height=&#34;363&#34;
	srcset=&#34;https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/the-homer_hu12790884048952618977.png 480w, https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/the-homer_hu8890425231612913337.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;The Homer car design from the Simpsons&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;181&#34;
		data-flex-basis=&#34;436px&#34;
	
&gt;
&lt;em&gt;Credit: The Simpsons/20th Century Animation&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Effective software development testing practices play a pivotal role in crafting robust, reliable, and high-quality software systems. While testing is traditionally seen as a validation mechanism, it’s increasingly being recognized as a potent tool for upfront software design.&lt;/p&gt;
&lt;p&gt;By incorporating testing practices into the early stages of software development, teams can not only catch defects early but also shape the architecture, behavior, and interactions of the system. This proactive approach not only enhances software quality but also fosters a more streamlined development process.&lt;/p&gt;
&lt;p&gt;In this article, we will delve into various testing practices that serve as upfront software design techniques, highlighting their significance in shaping software systems from inception.&lt;/p&gt;
&lt;h2 id=&#34;behavour-driven-development-bdd&#34;&gt;Behavour-Driven Development (BDD)
&lt;/h2&gt;&lt;p&gt;Behavour-Driven Development (BDD) stands as a testament to the philosophy that upfront design of a system’s behavior is crucial for success. BDD shifts the focus from writing traditional requirements to defining the expected behavior of the system through executable specifications.&lt;/p&gt;
&lt;p&gt;This promotes a shared understanding among stakeholders and helps to align development efforts with the desired outcomes. BDD encourages collaboration between developers, testers, and business representatives, fostering a holistic view of the software’s functionality right from the outset.&lt;/p&gt;
&lt;p&gt;Having these conversations upfront, clarifying requirements, and implementing the executable specifications as tests before implementing code, avoids costly mistakes that can be made due to the premature implementation of code, when a full understanding of the requirements has not been reached.&lt;/p&gt;
&lt;h2 id=&#34;integration-testing&#34;&gt;Integration Testing
&lt;/h2&gt;&lt;p&gt;Integration testing extends the upfront design of a system’s behavior to its interactions with external dependencies. By simulating the integration points with other systems, services, or components, integration testing ensures that the software’s interactions are well-defined, reliable, and consistent.&lt;/p&gt;
&lt;p&gt;Taking a test-first approach to integration testing makes us consider the nuances of how the application will interact with external dependencies, plan accordingly, and design the behavior of how the application will interact with external dependencies before a line of code has been written.&lt;/p&gt;
&lt;p&gt;This practice aids in early identification of compatibility issues, communication protocols, and data exchange mechanisms, enabling a smoother integration process and reducing late-stage surprises.&lt;/p&gt;
&lt;h2 id=&#34;consumer-driven-contract-testing&#34;&gt;Consumer-Driven Contract Testing
&lt;/h2&gt;&lt;p&gt;Consumer-Driven Contract Testing emphasizes the upfront design of how an application interacts with external services. Adopting a contract-first approach, this practice defines expectations and interfaces between systems from the outset.&lt;/p&gt;
&lt;p&gt;By ensuring that both the consumer and provider of a service adhere to a predefined contract, this approach promotes compatibility, reduces integration challenges, and enables smoother interactions.&lt;/p&gt;
&lt;p&gt;The process of consumer-driven contract testing demands that the consumer design upfront, the behavior of how the application will interact with the external service. The resultant contract, with the expected request and response, must be agreed by both parties before it can be used for the purposes of testing and implementing code.&lt;/p&gt;
&lt;p&gt;Furthermore, this approach creates an automated communication channel and feedback loop between consumer and provider, automatically raising alerts should incompatibilities arise during development. The relevant parties are alerted to issues before they impact running systems – allowing those parties to intervene and make informed decisions on how to proceed.&lt;/p&gt;
&lt;h2 id=&#34;test-driven-development-tdd&#34;&gt;Test-Driven Development (TDD)
&lt;/h2&gt;&lt;p&gt;Test-Driven Development (TDD) embodies the idea of upfront design at the code level. With TDD, developers design and write tests before writing the actual code. This approach enforces a clear understanding of the desired functionality, leading to well-structured, modular, and maintainable code. TDD’s red-green-refactor cycle encourages developers to iterate through design decisions, making the design process an integral part of writing code.&lt;/p&gt;
&lt;h2 id=&#34;performance-testing&#34;&gt;Performance Testing
&lt;/h2&gt;&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/slas-slos-slis.png&#34;
	width=&#34;1480&#34;
	height=&#34;800&#34;
	srcset=&#34;https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/slas-slos-slis_hu18418515621985908875.png 480w, https://humansreadcode.com/post/2023-08-10-automation-testing-upfront-design-technique/slas-slos-slis_hu16473336192554267188.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;Image with words describing SLAs, SLOs, and SLIs&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;185&#34;
		data-flex-basis=&#34;444px&#34;
	
&gt;
&lt;em&gt;Credit: Atlassian&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Performance testing embraces the upfront consideration and design of a system’s responsiveness under varying load profiles. By simulating real-world usage scenarios and stress conditions, performance testing aids in uncovering bottlenecks, resource constraints, and scalability concerns early in the development lifecycle. This proactive approach allows for architectural adjustments and optimizations that can significantly impact the system’s overall performance.&lt;/p&gt;
&lt;p&gt;The upfront consideration and design of how the application will behave under various load profiles requires the research and identification of those load profiles, establishing SLAs, and even considering customer happiness indicators: SLOs and SLIs.&lt;/p&gt;
&lt;h2 id=&#34;end-to-end-testing&#34;&gt;End-to-End Testing
&lt;/h2&gt;&lt;p&gt;End-to-End testing focuses on the upfront design of a system’s intercommunication across distributed components. By simulating user interactions and data flow through the entire software stack, end-to-end testing uncovers integration issues, data inconsistencies, and communication failures. This practice ensures that the system’s components collaborate seamlessly, fulfilling business requirements cohesively.&lt;/p&gt;
&lt;p&gt;With upfront planning, a smoke test with a very limited range of paths can be defined, such that it uncovers the intricacies of how each component within the overall system needs to be interconnected to allow data to flow through that system. COME BACK TO THIS&lt;/p&gt;
&lt;h2 id=&#34;security-testing&#34;&gt;Security Testing
&lt;/h2&gt;&lt;p&gt;Security testing advocates for the upfront design of a system’s resistance to potential attacks. By simulating various attack vectors and vulnerabilities, security testing helps identify weak points and design flaws that could lead to security breaches. This proactive stance ensures that the software is fortified against potential threats, safeguarding sensitive data and user privacy.&lt;/p&gt;
&lt;p&gt;Certain practices such as Threat Modelling push teams to think upfront of how their application may be vulnerable to attack and to take mitigating action, making appropriate architectural decisions prior to the implementation of code.&lt;/p&gt;
&lt;p&gt;Those decisions can then be captured as security tests that validate the application is resilient to these attacks. Teams can take a test-driven approach, writing the security tests before writing code, then writing code that ensures the tests pass.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Incorporating testing practices as upfront software design techniques not only enhances the quality and reliability of software systems but also contributes to a more efficient and collaborative development process.&lt;/p&gt;
&lt;p&gt;From defining behavior through BDD to ensuring security resilience through security testing, these practices collectively empower software teams to shape their creations proactively, minimizing rework, improving architectural decisions, and ultimately delivering software that meets and exceeds user expectations.&lt;/p&gt;
&lt;p&gt;By embracing these testing practices as integral components of upfront design, software development can navigate challenges with foresight and finesse, ensuring a robust foundation for successful products.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Text generated from my summarised list of bullet points by ChatGPT, August 10, 2023, OpenAI, &lt;a class=&#34;link&#34; href=&#34;https://chat.openai.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://chat.openai.com&lt;/a&gt;. Edited for style and content.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        <item>
        <title>Self Testing Code - Changing Code with Confidence</title>
        <link>https://humansreadcode.com/post/2023-08-06-self-testing-code/</link>
        <pubDate>Sun, 06 Aug 2023 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2023-08-06-self-testing-code/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2023-08-06-self-testing-code/tdd.png" alt="Featured image of post Self Testing Code - Changing Code with Confidence" /&gt;&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2023-08-06-self-testing-code/tdd.png&#34;
	width=&#34;768&#34;
	height=&#34;510&#34;
	srcset=&#34;https://humansreadcode.com/post/2023-08-06-self-testing-code/tdd_hu7822992156745580606.png 480w, https://humansreadcode.com/post/2023-08-06-self-testing-code/tdd_hu9557446098462206733.png 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;test driven development cycle&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;150&#34;
		data-flex-basis=&#34;361px&#34;
	
&gt;
&lt;em&gt;Test Driven Development&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In the ever-evolving landscape of software development, where change is the only constant, the need for robust testing practices has never been more critical. &lt;a class=&#34;link&#34; href=&#34;https://martinfowler.com/bliki/SelfTestingCode.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Martin Fowler’s insightful exploration of self-testing code&lt;/a&gt; has illuminated a path that not only enhances the quality of our code but empowers developers with a newfound confidence to shape and mould systems with agility.&lt;/p&gt;
&lt;p&gt;Self-testing code is “the practice of writing comprehensive automated tests in conjunction with the functional software.”&lt;/p&gt;
&lt;p&gt;At the heart of self-testing code lies a profound benefit: the confidence to implement changes. In traditional development cycles, every alteration, no matter how minor, can lead to a cascade of unintended consequences. This uncertainty can stifle progress and hinder innovation. However, by cultivating a culture of self-testing code, we unlock greater confidence that our changes will not break existing functionality. This confidence liberates us to experiment, optimize, and innovate, transforming the development process into a journey of continuous improvement rather than a daunting tightrope walk.&lt;/p&gt;
&lt;p&gt;One renowned technique that embodies the spirit of self-testing code is Test-Driven Development (TDD). TDD is more than just a testing approach; it’s a design philosophy that guides us to build code with a clear purpose and a well-defined structure. By writing tests before the actual code, TDD encourages a thoughtful and intentional approach to software development. This, in turn, naturally leads to the creation of self-testing code. TDD’s iterative cycle of red-green-refactor not only enforces test coverage but also shapes the architecture of our applications, resulting in a harmonious blend of robustness and design.&lt;/p&gt;
&lt;p&gt;With this early focus on design, TDD prompts us to envision the end result before we start coding, driving us to think critically about interfaces, interactions, and system boundaries. This proactive design aspect of TDD sets the stage for cleaner, more maintainable codebases. Therefore, while self-testing code is a prominent outcome of TDD, its latent design benefits are equally, if not more, beneficial.&lt;/p&gt;
&lt;p&gt;It’s important to clarify that the journey to self-testing code isn’t dictated by the sequence of writing tests. Whether tests are crafted before or after the code implementation is a tactical choice. What truly matters is the presence of these tests in the end. The essence of self-testing code revolves around having a safety net in place that ensures the reliability and stability of our systems. The path we take to arrive at these tests is secondary to the profound advantage they bring.&lt;/p&gt;
&lt;p&gt;By embracing this paradigm, we equip ourselves with the tools to confidently move forward, knowing that our changes are built on a solid foundation. Whether we embark on this journey through TDD or other means, the destination remains the same—a realm where code is not only tested but is inherently self-testing, and where we can make changes confidently with speed and reliability.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Serving Static Content using AWS CloudFront and AWS S3</title>
        <link>https://humansreadcode.com/post/2021-03-08-cloudfront-s3-static-hosting/</link>
        <pubDate>Mon, 08 Mar 2021 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2021-03-08-cloudfront-s3-static-hosting/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2021-03-08-cloudfront-s3-static-hosting/cloudfront-s3-static-hosting.png" alt="Featured image of post Serving Static Content using AWS CloudFront and AWS S3" /&gt;&lt;p&gt;AWS CloudFront can be leveraged for caching and routing to APIs, CMSes, etc. It’s a nice cheap setup with quite a lot of flexibility and integration with AWS services. If you want something light and quick you can check out &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/amplify/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Amplify&lt;/a&gt; or &lt;a class=&#34;link&#34; href=&#34;https://www.netlify.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Netflify&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This
tutorial covers creating the base for this stack by serving static
content using AWS CloudFront (the CDN), S3 (storage for the static
content). The S3 bucket will be private with serverside encryption
enabled by default. AWS Route 53 (DNS service) will be configured to
have requests sent to a custom domain routed to the CloudFront
distribution created in this tutorial.&lt;/p&gt;
&lt;p&gt;The source code for this tutorial can be found &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/cloudfront-s3-static-hosting&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;what-if-i-dont-want-a-custom-domain&#34;&gt;What if I don’t want a custom domain
&lt;/h3&gt;&lt;p&gt;If no custom domain is required, and hitting the CloudFront distribution domain directly is adequate for your needs, then &lt;a class=&#34;link&#34; href=&#34;#no-domain-no-problem&#34; &gt;follow these instructions instead&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;costs&#34;&gt;Costs
&lt;/h3&gt;&lt;p&gt;Warning! You will incur costs by following this tutorial.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Service&lt;/th&gt;
          &lt;th&gt;Cost&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Domain name&lt;/td&gt;
          &lt;td&gt;.com goes for around €8 for one year (€11 to renew) with &lt;a class=&#34;link&#34; href=&#34;https://effectiveserverless.com/www.namecheap.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Namecheap&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/route53/pricing&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Route 53 hosted zone&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;1 x €0.50 per month&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/cloudfront/pricing/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CloudFront&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;Charged on data transfer out &amp;amp; http/https requests&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a class=&#34;link&#34; href=&#34;https://effectiveserverless.com/cloudfront-s3-static-hosting&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS S3&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;You pay for storage, requests, and retrievals - Caching will make retrieval minimal&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;step-1-register-a-domain-name&#34;&gt;Step 1: Register a Domain Name
&lt;/h3&gt;&lt;p&gt;You can use AWS Route 53 to register a domain name by following &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;these instructions&lt;/a&gt;. Alternatively you can use your favourite domain registrar to register a domain. My favourite is &lt;a class=&#34;link&#34; href=&#34;https://effectiveserverless.com/www.namecheap.com&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Namecheap&lt;/a&gt; due to their low prices, customer support, and tooling.&lt;/p&gt;
&lt;p&gt;This tutorial will use Route 53 to alias your domain name and the subdomain &lt;code&gt;www&lt;/code&gt; to route traffic to the CloudFront distribution e.g.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;example.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;www.example.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-2-create-a-hosted-zone&#34;&gt;Step 2: Create a Hosted Zone
&lt;/h3&gt;&lt;p&gt;If
you decided to use AWS Route 53 to register a domain name then a Route
53 hosted zone will already have been created for you. Take note of the
Hosted Zone Id. Now go straight to step 4.&lt;/p&gt;
&lt;p&gt;Otherwise, if you
decided to use a domain registrar other than AWS Route 53 then create an
AWS Route 53 hosted zone by using the following CloudFormation
template:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZone&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Route53::HostedZone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Outputs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;The Hosted Zone Id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref HostedZone&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-HostedZoneId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneNameServers&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;The Hosted Zone Name Servers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Join&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;, &amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt HostedZone.NameServers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-HostedZoneNameServers&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Use the following AWS CLI command to create the hosted zone:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--template-file hosted-zone.yaml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-hosted-zone &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--parameter-overrides &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;DomainName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;your fully qualified domain name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following AWS CLI command to get the hosted zone id and the hosted zone nameservers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation describe-stacks &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-hosted-zone
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Look for the &lt;code&gt;&amp;quot;Outputs&amp;quot;&lt;/code&gt; JSON element in the output of the above command. It should look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Outputs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputKey&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HostedZoneId&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputValue&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;this will be your hosted zone id&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The Hosted Zone Id&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ExportName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-hosted-zone-HostedZoneId&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputKey&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;HostedZoneNameServers&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputValue&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;this will be a comma separated list of the nameservers associated with your hosted zone&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The Hosted Zone Name Servers&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ExportName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-hosted-zone-HostedZoneNameServers&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Take note of the hosted zone id, and the comma separated list of hosted zone name servers.&lt;/p&gt;
&lt;h3 id=&#34;step-3-set-route-53-as-the-dns-service-for-the-domain&#34;&gt;Step 3: Set Route 53 as the DNS service for the domain
&lt;/h3&gt;&lt;p&gt;To
successfully have traffic to the domain routed to the CloudFront
distribution, Route 53 needs to be set as the DNS service for the
domain. To achieve this, the nameservers for the domain need to be set
to the nameservers for the Route 53 hosted zone created in Step 2. The
nameservers for the Route 53 hosted zone can be found in the comma
separated list of the &lt;code&gt;&amp;quot;OutputValue&amp;quot;&lt;/code&gt; in the output from the CloudFormation describe CLI command in Step 2.&lt;/p&gt;
&lt;p&gt;The
domain registrar used to register the domain will have a console that
can be used to update the nameservers for the domain. For example &lt;a class=&#34;link&#34; href=&#34;https://www.namecheap.com/support/knowledgebase/article.aspx/767/10/how-to-change-dns-for-a-domain/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;these are the instructions for Namecheap&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&#34;step-4-create-the-certificate&#34;&gt;Step 4: Create the Certificate
&lt;/h3&gt;&lt;p&gt;With
the creation of the Route 53 hosted zone, and with Route 53 as the DNS
service for the domain, the certificate for the static website and can
be created and automatically validated by AWS Route 53. The following
CloudFormation template creates the certificate using AWS ACM, however
it must be created in the &lt;code&gt;us-east-1&lt;/code&gt; region otherwise it cannot be used with CloudFront:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Certificate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CertificateManager::Certificate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;SubjectAlternativeNames&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub www.${DomainName}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DomainValidationOptions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref HostedZoneId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub www.${DomainName}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref HostedZoneId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ValidationMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;DNS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Outputs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;CertificateArn&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;The Certificate ARN&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref Certificate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-CertificateArn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is the AWS CLI command to create the stack:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--template-file acm-certificate.yaml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-acm-certificate &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--region us-east-1 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--parameter-overrides &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;DomainName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;your fully qualified domain name&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;HostedZoneId&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;hosted zone id&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice the region is set to &lt;code&gt;us-east-1&lt;/code&gt;. This is necessary otherwise the certificate won’t work with CloudFront.&lt;/p&gt;
&lt;p&gt;Once
the stack is created, run the following command to get the certificate
ARN, this is required when creating the CloudFront distribution.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation describe-stacks &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--region us-east-1 &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-acm-certificate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Outputs&lt;/code&gt; JSON element will look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Outputs&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f92672&#34;&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputKey&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CertificateArn&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OutputValue&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;arn:aws:acm:us-east-1:111111111111:certificate/b8d0e2c9-daf7-42e8-a59b-3693bc299c32&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Description&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;The Certificate ARN&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;ExportName&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-acm-certificate-CertificateArn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;]&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Take note of the ARN which will look like this: &lt;code&gt;arn:aws:acm:us-east-1:111111111111:certificate/b8d0e2c9-daf7-42e8-a59b-3693bc299c32&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;step-5-create-the-cloudfront-distribution&#34;&gt;Step 5: Create The CloudFront Distribution
&lt;/h3&gt;&lt;p&gt;The
following CloudFormation template creates the Origin Access Identity,
static resources S3 bucket, and CloudFront distribution:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;CertificateArn&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;OriginAccessIdentity&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudFront::CloudFrontOriginAccessIdentity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;CloudFrontOriginAccessIdentityConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Comment&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-s3-origin-oai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucket&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::S3::Bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;BucketEncryption&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ServerSideEncryptionConfiguration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;ServerSideEncryptionByDefault&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;SSEAlgorithm&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AES256&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;PublicAccessBlockConfiguration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;BlockPublicAcls&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;BlockPublicPolicy&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;IgnorePublicAcls&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;RestrictPublicBuckets&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucketPolicy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::S3::BucketPolicy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Bucket&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref StaticResourcesBucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;PolicyDocument&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;AWS&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${OriginAccessIdentity}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;s3:GetObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:aws:s3:::${StaticResourcesBucket}/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Distribution&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudFront::Distribution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DistributionConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Aliases&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub www.${DomainName}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Origins&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${StaticResourcesBucket}.s3.${AWS::Region}.amazonaws.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;S3Origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;S3OriginConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;OriginAccessIdentity&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub origin-access-identity/cloudfront/${OriginAccessIdentity}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;DefaultRootObject&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;DefaultCacheBehavior&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AllowedMethods&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;DELETE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;GET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;HEAD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;OPTIONS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;PATCH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;PUT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;TargetOriginId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;S3Origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ForwardedValues&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;QueryString&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Cookies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Forward&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;none&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ViewerProtocolPolicy&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;redirect-to-https&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;CachePolicyId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;658327ea-f89d-4fab-a63d-7e88639e58f6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;PriceClass&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PriceClass_All&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ViewerCertificate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AcmCertificateArn&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref CertificateArn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;SslSupportMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;sni-only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Outputs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DistributionId&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CloudFront Distribution Id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref Distribution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-DistributionId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DistributionDomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CloudFront Distribution Domain Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt Distribution.DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucketName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Static Resources Bucket Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref StaticResourcesBucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-StaticResourcesBucketName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following command to create the CloudFormation stack:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--template-file cloudfront-distribution.yaml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-cloudfront-distribution &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--parameter-overrides &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;DomainName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;your domain name&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;CertificateArn&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;certificate arn&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;origin-access-identity&#34;&gt;Origin Access Identity
&lt;/h4&gt;&lt;p&gt;The Origin Access Identity allows CloudFront to read from the S3 bucket without having to make the S3 bucket public.&lt;/p&gt;
&lt;h4 id=&#34;s3-bucket&#34;&gt;S3 Bucket
&lt;/h4&gt;&lt;p&gt;The
static content is stored in the S3 bucket from which CloudFront will
serve the content. My preference is to encrypt all data whether it’s at
rest or in-flight, so here serverside encryption is enabled by default.
It’s data that will be publicly accessible through CloudFront, so the
default AWS S3 key would appear to be adequate here despite it being a
shared key across AWS accounts.&lt;/p&gt;
&lt;p&gt;The S3 bucket is explicitly configured as private with the &lt;code&gt;PublicAccessBlockConfiguration&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id=&#34;s3-bucket-policy&#34;&gt;S3 Bucket Policy
&lt;/h4&gt;&lt;p&gt;It is necessary to give &lt;code&gt;s3:GetObject&lt;/code&gt;
permission to the Origin Access Identity so that CloudFront can request
items from the S3 bucket. This means that the bucket can be kept
private but that CloudFront can still access the static content within.&lt;/p&gt;
&lt;h4 id=&#34;cache-policy&#34;&gt;Cache Policy
&lt;/h4&gt;&lt;p&gt;The cache policy id for the default cache behaviour is set to the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-cache-policies.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;managed cache policy&lt;/a&gt; &lt;code&gt;658327ea-f89d-4fab-a63d-7e88639e58f6&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Managed-CachingOptimized - which means caching is enabled and
CloudFront cache invalidation is required after making changes to static
content files.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&#34;try-it-out&#34;&gt;Try It Out
&lt;/h4&gt;&lt;p&gt;It should now be possible test the CloudFront distribution. Upload an &lt;code&gt;index.html&lt;/code&gt;
file to the S3 bucket then send an HTTP request to the CloudFront URL.
The name of the S3 bucket and CloudFront URL are required. Run the
following command to get the CloudFront distribution stack outputs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation describe-stacks &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-cloudfront-distribution
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output should look like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Outputs&amp;#34;: &lt;/span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DistributionId&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;distribution Id&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CloudFront Distribution Id&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-DistributionId&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DistributionDomainName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;d1111111111111.cloudfront.net&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CloudFront Distribution Domain Name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-DistributionDomainName&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;StaticResourcesBucketName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-staticresourcesbucket-1ab0a0a0a9abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Static Resources Bucket Name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-StaticResourcesBucketName&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Take note of the &lt;code&gt;OutputValue&lt;/code&gt; of &lt;code&gt;&amp;quot;OutputKey&amp;quot;: &amp;quot;DistributionDomainName&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;OutputKey&amp;quot;: &amp;quot;StaticResourcesBucketName&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Run the following command to create a file name &lt;code&gt;index.html&lt;/code&gt; and upload it to the S3 bucket:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My Static Content&amp;#39;&lt;/span&gt; &amp;gt; index.html &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;aws s3 cp index.html s3://&amp;lt;static resources bucket name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With
a browser, request the CloudFront URL taken from the stack output to
see the content returned from CloudFront. Alternatively the following
cURL command can be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl https://&amp;lt;cloudfront distribution domain&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The response should look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;My Static Content
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;step-6-route-traffic-to-the-cloudfront-distribution&#34;&gt;Step 6: Route Traffic To The CloudFront Distribution
&lt;/h3&gt;&lt;p&gt;A
further step is required to have requests to the domain routed to the
CloudFront distribution. It requires Route 53 alias records to be
created:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;IPV4 alias record (A) pointing the root domain to the CloudFront distribution&lt;/li&gt;
&lt;li&gt;IPV4 alias record (A) pointing the &lt;code&gt;www&lt;/code&gt; subdomain to the CloudFront distribution&lt;/li&gt;
&lt;li&gt;IPV6 alias record (AAAA) pointing the root domain to the CloudFront distribution&lt;/li&gt;
&lt;li&gt;IPV6 alias record (AAAA) pointing the &lt;code&gt;www&lt;/code&gt; subdomain to the CloudFront distribution&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The following CloudFormation template sets up the appropriate records:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DistributionDomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneRecordSetGroup&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Route53::RecordSetGroup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref HostedZoneId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;RecordSets&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AliasTarget&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Z2FDTNDATAQYW2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;DNSName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub www.${DomainName}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;A&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AliasTarget&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Z2FDTNDATAQYW2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;DNSName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AAAA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AliasTarget&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Z2FDTNDATAQYW2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;DNSName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub www.${DomainName}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AAAA&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AliasTarget&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;HostedZoneId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Z2FDTNDATAQYW2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;DNSName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following command to create the CloudFormation stack:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--template-file mystaticwebsite-record-set-group.yaml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-record-set-group &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--parameter-overrides &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;DomainName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;your domain name&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;HostedZoneId&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;hosted zone id&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;DistributionDomainName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&amp;lt;cloudfront distribution domain name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;try-it-out-1&#34;&gt;Try it Out
&lt;/h4&gt;&lt;p&gt;Navigate to the domain name in a browser or run the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl https://&amp;lt;your domain name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The following should be returned:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;My Static Content
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;no-domain-no-problem&#34;&gt;No domain no problem
&lt;/h3&gt;&lt;p&gt;If
no domain is required, and hitting the CloudFront distribution domain
directly is adequate for your needs, then this single CloudFormation
template will suffice:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;OriginAccessIdentity&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudFront::CloudFrontOriginAccessIdentity&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;CloudFrontOriginAccessIdentityConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Comment&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-s3-origin-oai&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucket&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::S3::Bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;BucketName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-static-resources&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;BucketEncryption&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ServerSideEncryptionConfiguration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;ServerSideEncryptionByDefault&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;SSEAlgorithm&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AES256&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;PublicAccessBlockConfiguration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;BlockPublicAcls&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;BlockPublicPolicy&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;IgnorePublicAcls&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;RestrictPublicBuckets&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucketPolicy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::S3::BucketPolicy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Bucket&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref StaticResourcesBucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;PolicyDocument&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;AWS&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${OriginAccessIdentity}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;s3:GetObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:aws:s3:::${StaticResourcesBucket}/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Distribution&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudFront::Distribution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DistributionConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Origins&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;DomainName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${StaticResourcesBucket}.s3.${AWS::Region}.amazonaws.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Id&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;S3Origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;S3OriginConfig&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;OriginAccessIdentity&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub origin-access-identity/cloudfront/${OriginAccessIdentity}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Enabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;DefaultRootObject&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;DefaultCacheBehavior&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AllowedMethods&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;DELETE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;GET&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;HEAD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;OPTIONS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;PATCH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;PUT&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;TargetOriginId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;S3Origin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ForwardedValues&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;QueryString&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Cookies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Forward&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;none&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ViewerProtocolPolicy&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;redirect-to-https&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;CachePolicyId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;658327ea-f89d-4fab-a63d-7e88639e58f6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;PriceClass&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PriceClass_All&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Outputs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DistributionId&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CloudFront Distribution Id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref Distribution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-DistributionId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DistributionDomainName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CloudFront Distribution Domain Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt Distribution.DomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-DistributionDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;StaticResourcesBucketName&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Static Resources Bucket Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref StaticResourcesBucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Export&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${AWS::StackName}-StaticResourcesBucketName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following command to create the CloudFormation stack:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--template-file cloudfront-distribution-no-custom-domain.yaml &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-cloudfront-distribution
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Run the following command to retrieve the CloudFront distribution domain:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation describe-stacks &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--stack-name mystaticwebsite-cloudfront-distribution
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The output should look like the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Outputs&amp;#34;: &lt;/span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DistributionId&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&amp;lt;distribution Id&amp;gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CloudFront Distribution Id&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-DistributionId&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DistributionDomainName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;d1111111111111.cloudfront.net&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;CloudFront Distribution Domain Name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-DistributionDomainName&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputKey&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;StaticResourcesBucketName&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;OutputValue&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-staticresourcesbucket-1ab0a0a0a9abc&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;Description&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Static Resources Bucket Name&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;ExportName&amp;#34;: &lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mystaticwebsite-cloudfront-distribution-StaticResourcesBucketName&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Take note of the &lt;code&gt;OutputValue&lt;/code&gt; of &lt;code&gt;&amp;quot;OutputKey&amp;quot;: &amp;quot;DistributionDomainName&amp;quot;&lt;/code&gt; and &lt;code&gt;&amp;quot;OutputKey&amp;quot;: &amp;quot;StaticResourcesBucketName&amp;quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Run the following command to create a file name &lt;code&gt;index.html&lt;/code&gt; and upload it to the S3 bucket:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;My Static Content&amp;#39;&lt;/span&gt; &amp;gt; index.html &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;aws s3 cp index.html s3://&amp;lt;static resources bucket name&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With
a browser, request the CloudFront URL taken from the stack output to
see the content returned from CloudFront. Alternatively the following
cURL command can be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl https://&amp;lt;cloudfront distribution domain&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The response should look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;My Static Content
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        </item>
        <item>
        <title>Safer Deployments with CodeDeploy Canary Deployments</title>
        <link>https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/</link>
        <pubDate>Wed, 30 Dec 2020 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/codedeploy-canary-deployments.webp" alt="Featured image of post Safer Deployments with CodeDeploy Canary Deployments" /&gt;&lt;p&gt;Without a good rollout and rollback strategy, there is greater risk of releasing breaking changes or broken software that impacts all users for an extended period of time. This can erode confidence in your releases and customers’ confidence in your products.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/canary-deployment.webp&#34;
	width=&#34;1180&#34;
	height=&#34;486&#34;
	srcset=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/canary-deployment_hu17060720738567462467.webp 480w, https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/canary-deployment_hu3009562045132757956.webp 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;canary deployment&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;242&#34;
		data-flex-basis=&#34;582px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://martinfowler.com/bliki/CanaryRelease.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Canary deployments&lt;/a&gt; can help minimise this risk by first routing a small percentage of traffic to the new version for a configured amount of time, before routing the remaining traffic to the new version. If any errors are detected during the initial routing then all traffic is routed back to the previous version.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/codedeploy&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS CodeDeploy&lt;/a&gt; provides native support for canary deployments of Lambdas. The &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/serverless/sam/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Serverless Application Model&lt;/a&gt; (SAM) provides abstractions to more easily configure CodeDeploy canary deployments of Lambdas using CloudFormation.&lt;/p&gt;
&lt;p&gt;This blog post describes how to implement Lambda canary deployments using CodeDeploy and SAM, with the added bonus of a pre-traffic automated test Lambda for smoke testing the new version. &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CloudWatch Alarms&lt;/a&gt; trigger automatic rollback on increased error detection during the initial traffic shifting phase of the deployment.&lt;/p&gt;
&lt;p&gt;CodeDeploy requires &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda Versions&lt;/a&gt; and a &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lambda Alias&lt;/a&gt; to provide support for canary deployments. A Lambda Version is an immutable snapshot of a Lambda at a point in time, and a Lambda Alias routes traffic to a specific Lambda Version. CodeDeploy begins a canary deployment by creating a new Lambda Version, then routes a certain percentage of traffic to that Lambda Version. If no errors are detected during the deployment timeframe, which is configurable, CodeDeploy will point the Lambda Alias to the new Lambda Version, thereby shifting 100% traffic to the new version.&lt;/p&gt;
&lt;h3 id=&#34;example-serverless-application&#34;&gt;Example Serverless Application
&lt;/h3&gt;&lt;p&gt;Here’s a CloudFormation stack with a simple example of this in action. An API Gateway RESTful API backed by two Lambdas uses CodeDeploy for canary deployments. Test Lambdas are defined to run pre and post-traffic tests against the new versions of ExampleAFunction and ExampleBFunction. CloudWatch Alarms for the alias and current version of ExampleALambda and ExampleBLambda are also defined. &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/lambda-codedeploy-canary&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;The code&lt;/a&gt; for this example can be found &lt;a class=&#34;link&#34; href=&#34;https:/github.com/karlkyck/lambda-codedeploy-canary&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Globals&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Function&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Runtime&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nodejs12.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;MemorySize&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleApi&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;StageName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleAFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        exports.handler = (event, context, callback) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        	callback(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			statusCode: 200,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			body: JSON.stringify({
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        				message: &amp;#39;Hello World A&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			})
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		});
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        };&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AutoPublishAlias&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ExampleApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/example/a&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DeploymentPreference&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Canary10Percent5Minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Alarms&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleAAliasErrorMetricGreaterThanZeroAlarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleALatestVersionErrorMetricGreaterThanZeroAlarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Hooks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;PreTraffic&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref PreTrafficLambdaFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;PostTraffic&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref PostTrafficLambdaFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleAAliasErrorMetricGreaterThanZeroAlarm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudWatch::Alarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AlarmDescription&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Lambda Function Error &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ComparisonOperator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;GreaterThanThreshold&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Dimensions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${ExampleAFunction}:live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;FunctionName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleAFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EvaluationPeriods&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MetricName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS/Lambda&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Statistic&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Sum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Threshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleALatestVersionErrorMetricGreaterThanZeroAlarm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudWatch::Alarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AlarmDescription&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Lambda Function Error &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ComparisonOperator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;GreaterThanThreshold&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Dimensions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${ExampleAFunction}:live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;FunctionName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleAFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ExecutedVersion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Fn::GetAtt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;ExampleAFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EvaluationPeriods&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MetricName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS/Lambda&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Statistic&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Sum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Threshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleBFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        exports.handler = (event, context, callback) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        	callback(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			statusCode: 200,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			body: JSON.stringify({
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        				message: &amp;#39;Hello World B&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			})
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		});
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        };&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AutoPublishAlias&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ExampleAApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/example/b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DeploymentPreference&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Canary10Percent5Minutes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Alarms&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBAliasErrorMetricGreaterThanZeroAlarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBLatestVersionErrorMetricGreaterThanZeroAlarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Hooks&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;PreTraffic&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref PreTrafficLambdaFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;PostTraffic&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref PostTrafficLambdaFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleBAliasErrorMetricGreaterThanZeroAlarm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudWatch::Alarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AlarmDescription&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Lambda Function Error &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ComparisonOperator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;GreaterThanThreshold&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Dimensions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${ExampleBFunction}:live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;FunctionName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EvaluationPeriods&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MetricName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS/Lambda&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Statistic&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Sum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Threshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleBLatestVersionErrorMetricGreaterThanZeroAlarm&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::CloudWatch::Alarm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AlarmDescription&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Lambda Function Error &amp;gt; 0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;ComparisonOperator&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;GreaterThanThreshold&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Dimensions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Resource&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub ${ExampleBFunction}:live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;FunctionName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ExecutedVersion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Value&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Fn::GetAtt&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;ExampleBFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EvaluationPeriods&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;MetricName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Errors&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Namespace&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS/Lambda&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Period&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;60&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Statistic&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Sum&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Threshold&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;PreTrafficLambdaFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        &amp;#34;use strict&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        const AWS = require(&amp;#34;aws-sdk&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        const codedeploy = new AWS.CodeDeploy();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        exports.handler = (event, context, callback) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          console.log(&amp;#34;Entering PreTraffic hook.&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const deploymentId = event.DeploymentId;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          var validationTestResult = &amp;#34;Failed&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Perform PreTraffic validation tests here. Set the test result
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // to &amp;#34;Succeeded&amp;#34; for this tutorial.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          console.log(&amp;#34;This is where PreTraffic validation tests happen.&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          validationTestResult = &amp;#34;Succeeded&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Complete the PreTraffic hook by sending CodeDeploy the validation status
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const params = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            deploymentId: deploymentId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            status: validationTestResult // status can be &amp;#39;Succeeded&amp;#39; or &amp;#39;Failed&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          };
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Pass AWS CodeDeploy the prepared validation test results.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          codedeploy.putLifecycleEventHookExecutionStatus(params, (err, data) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           if (err) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             // Validation failed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(&amp;#39;PreTraffic validation tests failed&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(err, err.stack);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             callback(&amp;#34;CodeDeploy Status update failed&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           } else {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             // Validation succeeded.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(&amp;#34;PreTraffic validation tests succeeded&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             callback(null, &amp;#34;PreTraffic validation tests succeeded&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        }&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Policies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2012-10-17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;codedeploy:PutLifecycleEventHookExecutionStatus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2012-10-17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;lambda:InvokeFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt ExampleAFunction.Arn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt ExampleBFunction.Arn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;FunctionName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CodeDeployHook_preTrafficHook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ExampleAFunctionCurrentVersion&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleAFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ExampleBFunctionCurrentVersion&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;PostTrafficLambdaFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        &amp;#34;use strict&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        const AWS = require(&amp;#34;aws-sdk&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        const codedeploy = new AWS.CodeDeploy();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        exports.handler = (event, context, callback) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          console.log(&amp;#34;Entering PostTraffic hook.&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Read the DeploymentId and LifecycleEventHookExecutionId from the event payload
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const deploymentId = event.DeploymentId;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          var validationTestResult = &amp;#34;Failed&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Perform PostTraffic validation tests here. Set the test result
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // to &amp;#34;Succeeded&amp;#34; for this tutorial.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          console.log(&amp;#34;This is where PostTraffic validation tests happen.&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          validationTestResult = &amp;#34;Succeeded&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Complete the PostTraffic hook by sending CodeDeploy the validation status
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          const params = {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            deploymentId: deploymentId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            status: validationTestResult // status can be &amp;#39;Succeeded&amp;#39; or &amp;#39;Failed&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          };
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          // Pass AWS CodeDeploy the prepared validation test results.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          codedeploy.putLifecycleEventHookExecutionStatus(params, (err, data) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           if (err) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             // Validation failed.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(&amp;#39;PostTraffic validation tests failed&amp;#39;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(err, err.stack);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             callback(&amp;#34;CodeDeploy Status update failed&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           } else {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             // Validation succeeded.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             console.log(&amp;#34;PostTraffic validation tests succeeded&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;             callback(null, &amp;#34;PostTraffic validation tests succeeded&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;           }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          });
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        }&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Policies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2012-10-17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;codedeploy:PutLifecycleEventHookExecutionStatus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:${AWS::Partition}:codedeploy:${AWS::Region}:${AWS::AccountId}:deploymentgroup:${ServerlessDeploymentApplication}/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;2012-10-17&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;lambda:InvokeFunction&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt ExampleAFunction.Arn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt ExampleBFunction.Arn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;FunctionName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CodeDeployHook_postTrafficHook&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Variables&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ExampleAFunctionCurrentVersion&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleAFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;ExampleBFunctionCurrentVersion&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ExampleBFunction.Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;sam-reduces-boilerplate&#34;&gt;SAM Reduces Boilerplate
&lt;/h3&gt;&lt;p&gt;Just a few lines in the CloudFormation applies the CodeDeploy canary configuration courtesy of the SAM transformation:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DeploymentPreference:
  Type: Canary10Percent5Minutes
    Alarms:
      - !Ref ExampleAAliasErrorMetricGreaterThanZeroAlarm
      - !Ref ExampleALatestVersionErrorMetricGreaterThanZeroAlarm
    Hooks:
      PreTraffic: !Ref PreTrafficLambdaFunction
      PostTraffic: !Ref PostTrafficLambdaFunction
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;SAM transforms the CloudFormation to create the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CodeDeploy Application&lt;/li&gt;
&lt;li&gt;CodeDeploy DeploymentGroup per Lambda&lt;/li&gt;
&lt;li&gt;CodeDeployServiceRole&lt;/li&gt;
&lt;li&gt;Lambda Alias with an UpdatePolicy applying CodeDeploy Application, Deployment Group, and pre/post-traffic hooks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;prepost-traffic-tests&#34;&gt;Pre/Post-Traffic Tests
&lt;/h3&gt;&lt;p&gt;Pre-
traffic tests against the new version, validating service contracts and
using known test scenarios, provide greater confidence in a deployment
being successful. Additional tests can be added over time as the system
evolves and more weaknesses are revealed. If these tests fail then no
traffic is shifted to the new version and no customers are affected.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/pre-traffic-tests.webp&#34;
	width=&#34;837&#34;
	height=&#34;1086&#34;
	srcset=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/pre-traffic-tests_hu17409145946866838229.webp 480w, https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/pre-traffic-tests_hu2462689423497856489.webp 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;pre-traffic tests&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;77&#34;
		data-flex-basis=&#34;184px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;The example includes a post-traffic test Lambda for some post-traffic shifting smoke testing should the need arise.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/post-traffic-tests.webp&#34;
	width=&#34;590&#34;
	height=&#34;766&#34;
	srcset=&#34;https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/post-traffic-tests_hu4211066826716031876.webp 480w, https://humansreadcode.com/post/2020-12-30-lambda-deploy-canary/post-traffic-tests_hu15487065505530653735.webp 1024w&#34;
	loading=&#34;lazy&#34;
	
		alt=&#34;post-traffic tests&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;77&#34;
		data-flex-basis=&#34;184px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;Ideally these tests can be run in parallel to minimise
execution time and provide rapid feedback. Tests in non-production
environments can be more thorough and numerous, employing test data and
mocked boundaries to exercise known scenarios that may not be possible
to test in production.&lt;/p&gt;
&lt;h3 id=&#34;cloudwatch-alarms-trigger-rollback&#34;&gt;CloudWatch Alarms Trigger Rollback
&lt;/h3&gt;&lt;p&gt;During
initial traffic shifting, CloudWatch Alarms monitor error rates of the
new version and if triggered will fail the deployment and automatically
rollback to the previous version. Only a small number of requests will
be negatively impacted before rollback occurs and traffic is shifted
back to the previous version. If all goes well, the remainder of the
traffic is shifted to the new version.&lt;/p&gt;
&lt;h3 id=&#34;phased-rollouts&#34;&gt;Phased Rollouts
&lt;/h3&gt;&lt;p&gt;This
strategy encourages you to adopt a phased rollout strategy that
introduces no breaking changes, and therefore requires no downtime for
your applications. Thought has to go into architecting and coding your
applications so that multiple versions can co-exist. For example how
will database, contract, or configuration changes be handled and rolled
back?&lt;/p&gt;
&lt;h3 id=&#34;business-case&#34;&gt;Business Case
&lt;/h3&gt;&lt;p&gt;There
needs to be business cases behind the architectural design decisions
that you make; in this case not all solutions require 100% uptime, with
phased rollout of changes. It may not even be possible in certain
circumstances. However, when services like AWS CodeDeploy make it so
easy to apply these strategies it’s almost more work not to adopt this
strategy.&lt;/p&gt;
&lt;h3 id=&#34;aws-well-architected-best-practice&#34;&gt;AWS Well-Architected Best Practice
&lt;/h3&gt;&lt;p&gt;This strategy is described as a best practice by the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/welcome.html?did=wp_card&amp;amp;trk=wp_card&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Serverless Application Lens&lt;/a&gt; of the &lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/architecture/well-architected/?wa-lens-whitepapers.sort-by=item.additionalFields.sortDate&amp;amp;wa-lens-whitepapers.sort-order=desc&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Well-Architected Framework&lt;/a&gt;, falling within the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/wellarchitected/latest/operational-excellence-pillar/welcome.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Operational Excellence Pillar&lt;/a&gt;.
The ability to build applications that run with 0% downtime is a
valuable, marketable skill. Operation excellence is a bar that continues
to rise and with expectations on developers only increasing it makes
sense to keep your skills sharp.&lt;/p&gt;
&lt;p&gt;With Lambdas, you pay for what
you use, so previous versions, now unused, will not incur costs and can
be retired as necessary. Adopting this strategy helps you &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/welcome.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;optimise costs&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;caveats&#34;&gt;Caveats
&lt;/h3&gt;&lt;p&gt;CodeDeploy
canary deployments use request based traffic shifting, not user based
traffic shifting so some or all of your users could be impacted, albeit a
much smaller number of requests.&lt;/p&gt;
&lt;p&gt;CloudWatch Alarms gather metrics
against the alias and not the version so it may lead to false positives
against the new version should the previous version begin to fail.&lt;/p&gt;
&lt;p&gt;The
automatic cleanup of old versions is encouraged so as not to run out of
Lambda storage space, which typically occurs at exactly the wrong
moment, and can prevent you from deploying. An &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;EventBridge Scheduled Event&lt;/a&gt; can be configured to periodically run a Lambda that removes older versions.&lt;/p&gt;
&lt;p&gt;When using SAM to apply a CodeDeploy deployment configuration to a Lambda, pre/post traffic hook Lambda names must start with: &lt;code&gt;CodeDeployHook_&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&#34;charges-apply&#34;&gt;Charges Apply!
&lt;/h3&gt;&lt;p&gt;Charges apply so be sure to remove all resources created after experimentation.&lt;/p&gt;
&lt;h3 id=&#34;references&#34;&gt;References
&lt;/h3&gt;&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/architecture/well-architected/?wa-lens-whitepapers.sort-by=item.additionalFields.sortDate&amp;amp;wa-lens-whitepapers.sort-order=desc&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Well-Architected Framework&lt;/a&gt;: &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/wellarchitected/latest/serverless-applications-lens/welcome.html?did=wp_card&amp;amp;trk=wp_card&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Serverless lens&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://aws.amazon.com/serverless/sam/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Serverless Application Model&lt;/a&gt; (SAM): &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS::Serverless::Function&lt;/a&gt; (&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-deploymentpreference.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DeploymentPreference&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;AWS Serverless Application Model Developer Guide: &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/automating-updates-to-serverless-apps.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Deploying serverless applications gradually&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://theburningmonk.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Burning Monk&lt;/a&gt; (guest post for &lt;a class=&#34;link&#34; href=&#34;https://lumigo.io/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Lumigo&lt;/a&gt;): &lt;a class=&#34;link&#34; href=&#34;https://lumigo.io/aws-lambda-deployment/canary-deployment-for-aws-lambda/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS Lambda Canary Deployment&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Encrypt DynamoDB with a Customer Managed KMS Key</title>
        <link>https://humansreadcode.com/post/2020-10-22-dynamodb-encryption-kms/</link>
        <pubDate>Thu, 22 Oct 2020 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2020-10-22-dynamodb-encryption-kms/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2020-10-22-dynamodb-encryption-kms/dynamodb-kms.webp" alt="Featured image of post Encrypt DynamoDB with a Customer Managed KMS Key" /&gt;&lt;p&gt;Customer managed CMKs can be fully
controlled (key rotation, key policies, IAM policies, etc). The examples
use CloudFormation to create the CMK, DynamoDB table, and test Lambda.&lt;/p&gt;
&lt;h3 id=&#34;charges-apply&#34;&gt;Charges Apply!
&lt;/h3&gt;&lt;p&gt;Charges apply so be sure to remove all resources created after experimentation.&lt;/p&gt;
&lt;h3 id=&#34;tldr&#34;&gt;TL;DR
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Use a Customer managed customer master key (CMK)&lt;/li&gt;
&lt;li&gt;Add a condition to the CMK key policy to allow DynamoDB to use it&lt;/li&gt;
&lt;li&gt;Configure a DynamoDB table with SSE using the CMK&lt;/li&gt;
&lt;li&gt;1 CMK is ~$1.00 per month + $0.03 per 10,000 requests&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;keep-it-secret-keep-it-safe&#34;&gt;Keep it secret, keep it safe
&lt;/h3&gt;&lt;p&gt;DynamoDB is an AWS managed key-value and document database. Server side encryption is enabled by default and uses an AWS owned customer master key (CMK).&lt;/p&gt;
&lt;p&gt;There are three types of CMK that can be used with DynamoDB to encrypt data at rest:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS owned CMK&lt;/a&gt; (shared across multiple accounts, cannot be managed, charges do not apply)&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS managed CMK&lt;/a&gt; (shared across a single account, cannot be managed, charges apply)&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Customer managed CMK&lt;/a&gt; (can be fully managed, charges apply)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use a Customer managed CMK for the greatest level of control. There are several advantages to using a Customer managed CMK for DynamoDB SSE.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Full control over these keys means fine grained control over key rotation, key and IAM policies, etc&lt;/li&gt;
&lt;li&gt;Reduces blast radius when using one Customer managed CMK per table&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;cloudformation&#34;&gt;CloudFormation
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DynamoDbTableKmsKey&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::KMS::Key&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EnableKeyRotation&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;KeyPolicy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2012-10-17&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;AWS&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub arn:aws:iam::${AWS::AccountId}:root&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;kms:*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;AWS&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;kms:Encrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;kms:Decrypt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Condition&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;StringEquals&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;kms:CallerAccount&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref AWS::AccountId&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;kms:ViaService&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub dynamodb.${AWS::Region}.amazonaws.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DynamoDbTable&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::DynamoDB::Table&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;AttributeDefinitions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;AttributeName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;AttributeType&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;S&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;KeySchema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;AttributeName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;KeyType&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;HASH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;BillingMode&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;PAY_PER_REQUEST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;SSESpecification&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;KMSMasterKeyId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DynamoDbTableKmsKey&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;SSEEnabled&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;SSEType&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;KMS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DynamoDbWriteFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          def handler(event, context):
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            import boto3
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            dynamodb = boto3.client(&amp;#39;dynamodb&amp;#39;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            id = event[&amp;#39;id&amp;#39;]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            return dynamodb.put_item(TableName=&amp;#39;${TableName}&amp;#39;, Item={&amp;#39;id&amp;#39;:{&amp;#39;S&amp;#39;:f&amp;#39;{id}&amp;#39;}})&lt;/span&gt;          
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;TableName&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref DynamoDbTable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Runtime&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;python3.7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Policies&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              - &lt;span style=&#34;color:#ae81ff&#34;&gt;dynamodb:PutItem&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;GetAtt DynamoDbTable.Arn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;Specify
a CMK key policy condition to allow the DynamoDB service to use the CMK
for server side encryption and only from the same account&lt;/li&gt;
&lt;li&gt;Reference the KMS CMK above when defining the DynamoDB table&lt;/li&gt;
&lt;li&gt;Use the Lambda for inserting data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;deploying-to-aws&#34;&gt;Deploying to AWS
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation deploy --stack-name dynamodb-sse-with-kms-cmk --template-file sam.yaml --capabilities CAPABILITY_IAM
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;invoke-the-test-lambda-using-the-aws-cli&#34;&gt;Invoke the test Lambda using the AWS CLI
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws lambda invoke &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--function-name &amp;lt;lambda name goes here&amp;gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;--payload &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{ &amp;#34;id&amp;#34;: &amp;#34;1&amp;#34; }&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;&lt;/span&gt;response.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;delete-the-cloudformation-stack&#34;&gt;Delete the CloudFormation Stack
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aws cloudformation delete-stack --stack-name dynamodb-sse-with-kms-cmk
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
        </item>
        <item>
        <title>Split CloudFormation Stacks</title>
        <link>https://humansreadcode.com/post/2019-07-14-split-cloudformation-stacks/</link>
        <pubDate>Sun, 14 Jul 2019 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2019-07-14-split-cloudformation-stacks/</guid>
        <description>&lt;p&gt;Placing all your resources into a single stack is going to create
pain for you later on. Moving and renaming resources between stacks can
be quite tricky. Once a resource is managed by a CloudFormation stack
it’s not possible to remove that resource without deleting it, and it’s
not possible to move a resource from one stack to another. Splitting up
your resources across multiple stacks can really help. Here are some
suggestions on how you can achieve that.&lt;/p&gt;
&lt;h3 id=&#34;resources-that-change-together-stay-together&#34;&gt;Resources that change together stay together
&lt;/h3&gt;&lt;p&gt;Your application may consist of an API Gateway with multiple Lambdas
and SNS/SQS resources for internal processing. RDS databases with
clustering. VPCs with Subnets, Security Groups, etc. These resources are
logically grouped and belong in a dedicated stack.&lt;/p&gt;
&lt;h3 id=&#34;stateful-resources&#34;&gt;Stateful Resources
&lt;/h3&gt;&lt;p&gt;Stateful resources such as RDS, S3, DynamoDB, etc should get their
own stack. The only way to move or rename these resources is to define a
new resource with a different name and copy the data across. By mixing
these resources with more volatile resources you risk having to do this.
Best to avoid such a scenario.&lt;/p&gt;
&lt;h3 id=&#34;configuration-resources&#34;&gt;Configuration Resources
&lt;/h3&gt;&lt;p&gt;Configuration Resources such as ParameterStore and SecretsManager
belong in their own stack. Changes to these resources should not require
a redeployment of the application that uses them.&lt;/p&gt;
&lt;h3 id=&#34;application-boundaries&#34;&gt;Application Boundaries
&lt;/h3&gt;&lt;p&gt;Resources that make up the boundary of an application such as API
Gateway, SNS, Kinesis, etc should get their own stack. Other
applications access these resources through a “public” contract and
minimising disruption to these resources is important.&lt;/p&gt;
&lt;h3 id=&#34;shared-resources&#34;&gt;Shared Resources
&lt;/h3&gt;&lt;p&gt;Any resources shared by multiple applications should get their own
stack. VPCs, Subnets, KMS, S3, etc. VPCs cannot be deleted if they are
using by any resources. Removing a KMS key means losing access to data,
and moving an S3 bucket means creating a new one and copying the data
over to the new bucket.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;These are some guidelines that have come in handy over time. Comment below with your experiences and recommendations.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to use OpenAPI with AWS API Gateway</title>
        <link>https://humansreadcode.com/post/2019-05-15-openapi-api-gateway/</link>
        <pubDate>Wed, 29 May 2019 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2019-05-15-openapi-api-gateway/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2019-05-15-openapi-api-gateway/openapi-api-gateway.webp" alt="Featured image of post How to use OpenAPI with AWS API Gateway" /&gt;&lt;p&gt;Use an &lt;a class=&#34;link&#34; href=&#34;https://swagger.io/docs/specification/about/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAPI&lt;/a&gt; specification to define API Gateway APIs. This is good practice because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The specification forces you to think about the design upfront before touching code which is expensive to correct later&lt;/li&gt;
&lt;li&gt;This contract first approach allows frontend, backend, and test developers to work in parallel&lt;/li&gt;
&lt;li&gt;Endpoints can be mocked for developers to test against&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Serverless Application Model&lt;/a&gt; (SAM)
uses the specification to configure the API Gateway API, this makes it
living documentation, evolving alongside code and infrastructure.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Create an OpenAPI specification with &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;API Gateway Extensions to OpenAPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Copy the file to an S3 bucket&lt;/li&gt;
&lt;li&gt;Define an API Gateway (&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;AWS::Serverless::Api&lt;/strong&gt;&lt;/a&gt;) resource in your SAM template&lt;/li&gt;
&lt;li&gt;Use the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;AWS::Include&lt;/strong&gt;&lt;/a&gt; transform to include and transform the OpenAPI specification from S3&lt;/li&gt;
&lt;li&gt;Assign the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;AWS::Include&lt;/strong&gt;&lt;/a&gt; transform function to the &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DefinitionBod&lt;/a&gt;&lt;/strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;y&lt;/strong&gt;&lt;/a&gt; property of the API Gateway resource&lt;/li&gt;
&lt;li&gt;Package and deploy your SAM application&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;source-code&#34;&gt;Source Code
&lt;/h2&gt;&lt;p&gt;The source code and instructions to build and deploy this example to AWS can be found here: &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/api-gateway-openapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/karlkyck/api-gateway-openapi&lt;/a&gt;.
Running this example on AWS will incur costs so be sure to delete the
CloudFormation stacks when you are finished experimenting.&lt;/p&gt;
&lt;h2 id=&#34;openapi-definition&#34;&gt;OpenAPI Definition
&lt;/h2&gt;&lt;p&gt;Start by creating your OpenAPI specification in a dedicated file.&lt;/p&gt;
&lt;p&gt;The following OpenAPI specification defines one RESTful endpoint with two operations on that endpoint.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;API Gateway OpenAPI Example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;/api/posts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;summary&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;List Posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;operationId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;listPosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;requestBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;required&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;$ref&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/CreatePostRequestBody&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Retrieve the list of Posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;$ref&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/ListPostsResponseBody&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-integration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uri&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Fn::Sub&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListPostsFunction.Arn}/invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;httpMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws_proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;post&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;summary&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Create a new Post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;operationId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;createPost&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;$ref&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/Post&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-integration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uri&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Fn::Sub&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CreatePostFunction.Arn}/invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;httpMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws_proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;components&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;schemas&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;BasePost&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;description&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;publishedDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;publishedDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Post&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;allOf&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/BasePost&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;createdDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;updatedDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;id&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;createdDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;updatedDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;CreatePostRequestBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;allOf&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/BasePost&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ListPostsResponseBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;items&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/Post&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The two &lt;strong&gt;x-amazon-apigateway-integration&lt;/strong&gt; &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;API Gateway Extensions to OpenAPI&lt;/a&gt; references allow us to refer to the relevant Lambda function in our SAM template.&lt;/p&gt;
&lt;p&gt;By using CloudFormation &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;Intrinsic Functions&lt;/strong&gt;&lt;/a&gt; in your OpenAPI specification such as the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;Fn::Sub&lt;/strong&gt;&lt;/a&gt;
(variable substitution) function calls in the example above, you can
refer to the relevant Lambdas backing your API in your SAM template.&lt;/p&gt;
&lt;h2 id=&#34;sam-definition&#34;&gt;SAM Definition
&lt;/h2&gt;&lt;p&gt;The following SAM template creates an API Gateway API and two Lambdas, each with an API Gateway event defined.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DeploymentBucket&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Globals&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Function&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Runtime&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nodejs8.10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;180&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApi&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;StageName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EndpointConfiguration&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;REGIONAL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DefinitionBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;Fn::Transform&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Include&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Location&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub s3://${DeploymentBucket}/openapi.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ListPostsFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ListPostsHandler.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;CodeUri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;./dist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ApiGatewayApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;CreatePostFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;CreatePostHandler.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;CodeUri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;./dist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ApiGatewayApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;post&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important part to focus on here is the &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DefinitionBod&lt;/a&gt;&lt;/strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;y&lt;/strong&gt;&lt;/a&gt; parameter of the &lt;strong&gt;ApiGatewayApi&lt;/strong&gt; resource. We are using the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;AWS::Include&lt;/strong&gt;&lt;/a&gt; transform to include the OpenAPI specification from its S3 location.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AWS::Include&lt;/a&gt;&lt;/strong&gt; transform allows you to use CloudFormation &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;Intrinsic Functions&lt;/strong&gt;&lt;/a&gt; in your OpenAPI specification such as the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-sub.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;Fn::Sub&lt;/strong&gt;&lt;/a&gt; (variable substitution) function calls in the example OpenAPI specification.&lt;/p&gt;
&lt;h2 id=&#34;deployment&#34;&gt;Deployment
&lt;/h2&gt;&lt;p&gt;When deploying your SAM project CloudFormation will load the OpenAPI
specification from the specified S3 location performing an AWS::Include
transform. Intrinsic Function calls within the OpenAPI specification
will be executed, thereby transforming your OpenAPI specification
accordingly.&lt;/p&gt;
&lt;h2 id=&#34;api-documentation&#34;&gt;API Documentation
&lt;/h2&gt;&lt;p&gt;The API documentation is now linked to the API Gateway API. The
OpenAPI specification is also bound to your SAM template by way of
references to Lambda functions and other resources and parameters.
Therefore the specification and SAM template evolve together.&lt;/p&gt;
&lt;p&gt;The OpenAPI specification is also made available in the AWS console for other developers and teams to export and consume.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Safe Deployments with API Gateway and Lambda AutoPublishAlias</title>
        <link>https://humansreadcode.com/post/2019-05-29-safe-deployments-with-api-gateway/</link>
        <pubDate>Wed, 29 May 2019 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2019-05-29-safe-deployments-with-api-gateway/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2019-05-29-safe-deployments-with-api-gateway/api-gateway-lambda-autopublishalias.webp" alt="Featured image of post Safe Deployments with API Gateway and Lambda AutoPublishAlias" /&gt;&lt;h2 id=&#34;tldr&#34;&gt;TL;DR
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Use the &lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Serverless Application Model&lt;/a&gt; (SAM) &lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/docs/safe_lambda_deployments.rst#instant-traffic-shifting-using-lambda-aliases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;strong&gt;AutoPublishAlias&lt;/strong&gt;&lt;/a&gt; parameter to have CloudFormation automatically version and alias your Lambdas upon deployment&lt;/li&gt;
&lt;li&gt;Reference your Lambda Alias from your OpenAPI definition&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;source-code&#34;&gt;Source Code
&lt;/h2&gt;&lt;p&gt;The source code and instructions to build and deploy this example to AWS can be found here: &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/api-gateway-lambda-autopublishalias&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/karlkyck/api-gateway-lambda-autopublishalias&lt;/a&gt;.
Running this example on AWS will incur costs so be sure to delete the
CloudFormation stacks when you are finished experimenting.&lt;/p&gt;
&lt;h2 id=&#34;sam-serverless-application-model-template&#34;&gt;SAM (Serverless Application Model) Template
&lt;/h2&gt;&lt;p&gt;Begin by defining your SAM template. By specifying the
AutoPublishAlias parameter in our Globals section applies the
AutoPublishAlias parameter to each of the functions defined in the
template.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;DeploymentBucket&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;String&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Globals&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Function&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Runtime&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nodejs10.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;180&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;AutoPublishAlias&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApi&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;StageName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EndpointConfiguration&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;REGIONAL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DefinitionBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;Fn::Transform&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Include&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Location&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Sub s3://${DeploymentBucket}/openapi.yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ListPostsFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ListPostsHandler.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;CodeUri&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;./dist&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ApiGatewayApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the above CloudFormation, &lt;code&gt;live&lt;/code&gt; is specified as
the Alias name for our newly deployed Lambda. When CloudFormation
deploys this Lambda for the first time it will automatically create a
new Lambda Version of 1 and a Lambda Alias called &lt;code&gt;live&lt;/code&gt;. CloudFormation
will point the Lambda Alias &lt;code&gt;live&lt;/code&gt; to the newly created Lambda Version
1.&lt;/p&gt;
&lt;p&gt;When there is an update to the Lambda code, upon deployment
CloudFormation will create a new Lambda Version using the previous
Lambda Version number incremented by 1. CloudFormation will then point
the Lambda Alias ‘live’ to this new Lambda Version.&lt;/p&gt;
&lt;p&gt;The SAM template defines the API Gateway resource that references an
OpenAPI specification. The OpenAPI specification describes the API and
also links API endpoints to Lambda resources within the SAM template.
See &lt;a class=&#34;link&#34; href=&#34;https://www.humansreadcode.com/how-to-use-openapi-with-api-gateway/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;how to use OpenAPI with API Gateway&lt;/a&gt; for more details.&lt;/p&gt;
&lt;h2 id=&#34;openapi-specification&#34;&gt;OpenAPI Specification
&lt;/h2&gt;&lt;p&gt;The key here is to specify the Lambda Alias when making reference to a
Lambda from the OpenAPI specification. If the Lambda Alias is left out
when making reference to a Lambda function the API call will not work.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;API Gateway Lambda AutoPublishAlias Example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;/api/posts&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;summary&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;List Posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;operationId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;listPosts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Retrieve the list of Posts&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;application/json&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;schema&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;$ref&amp;#39;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/ListPostsResponseBody&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-integration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uri&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Fn::Sub&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListPostsFunction.Arn}:live/invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;httpMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws_proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;components&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;schemas&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;BasePost&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;title&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;description&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;publishedDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;content&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;publishedDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;content&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Post&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;allOf&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/BasePost&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;required&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;createdDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#ae81ff&#34;&gt;updatedDate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;id&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;createdDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;updatedDate&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;format&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;date-time&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;ListPostsResponseBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;array&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;items&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;$ref&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#/components/schemas/Post&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important line is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListPostsFunction.Arn}:**live**/invocations
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping Up
&lt;/h2&gt;&lt;p&gt;Upon deployment the API Gateway endpoint will point to a Lambda
Alias. If in an emergency a rollback is required the Lambda Alias can be
repointed to a previous version. This can be done manually through the
AWS Console. There is a way to automate this process which will be
covered in a separate blog post.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/automating-updates-to-serverless-apps.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/automating-updates-to-serverless-apps.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/automating-updates-to-serverless-apps.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://swagger.io/docs/specification/about/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/automating-updates-to-serverless-apps.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>IP Filtering with AWS API Gateway Resource Policies</title>
        <link>https://humansreadcode.com/post/2019-05-03-ip-filtering-aws-gateway/</link>
        <pubDate>Fri, 03 May 2019 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2019-05-03-ip-filtering-aws-gateway/</guid>
        <description>&lt;img src="https://humansreadcode.com/post/2019-05-03-ip-filtering-aws-gateway/cover.webp" alt="Featured image of post IP Filtering with AWS API Gateway Resource Policies" /&gt;&lt;h3 id=&#34;tldr&#34;&gt;TL;DR
&lt;/h3&gt;&lt;p&gt;Use an &lt;a class=&#34;link&#34; href=&#34;https://swagger.io/docs/specification/about/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAPI&lt;/a&gt; specification with the &lt;code&gt;x-amazon-apigateway-policy&lt;/code&gt; API Gateway Extension to OpenAPI to apply an API Gateway Resource Policy when deploying:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3.0.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-policy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2012-10-17&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:Invoke&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:/*/*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Condition&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;IpAddress&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;aws:SourceIp&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Ref&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AllowedIpsList&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where &lt;strong&gt;AllowedIpsList&lt;/strong&gt; is a comma separated list of IPs or CIDR blocks defined as a parameter in your CloudFormation template.&lt;/p&gt;
&lt;h3 id=&#34;rationale&#34;&gt;Rationale
&lt;/h3&gt;&lt;p&gt;When it comes to accessing and consuming resources on the cloud a least privileged approach is best. IP restriction on your API Gateway APIs can help.&lt;/p&gt;
&lt;p&gt;It is possible to apply an API Gateway Resource Policy to an API Gateway API during deployment via CloudFormation.&lt;/p&gt;
&lt;h3 id=&#34;cloudformation-template&#34;&gt;CloudFormation Template
&lt;/h3&gt;&lt;p&gt;Your API Gateway API definition and reference to your OpenAPI specification is defined in your SAM (Serverless Application Model) template.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;AWSTemplateFormatVersion&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2010-09-09&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Transform&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless-2016-10-31&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Parameters&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;AllowedIpsList&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;List&amp;lt;String&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Globals&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Function&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Runtime&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;nodejs12.x&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Timeout&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;AutoPublishAlias&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;Resources&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApi&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;StageName&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;EndpointConfiguration&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;REGIONAL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;DefinitionBody&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3.0.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;API Gateway IP Filtering Example API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-policy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2012-10-17&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:Invoke&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                - &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:/*/*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;Condition&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;IpAddress&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;aws:SourceIp&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#f92672&#34;&gt;Ref&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AllowedIpsList&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;/api/example&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;summary&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Example API Endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;operationId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-integration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;uri&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#f92672&#34;&gt;Fn::Sub&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExampleFunction.Arn}:live/invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;httpMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws_proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;ExampleFunction&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS::Serverless::Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Handler&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;index.handler&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;InlineCode&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        exports.handler = (event, context, callback) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        	callback(
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		null,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			statusCode: 200,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			body: JSON.stringify({
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        				message: &amp;#39;Hello World&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        			})
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        		});
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        };&lt;/span&gt;        
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Events&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;ApiGatewayApiEvent&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Api&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Properties&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;RestApiId&lt;/span&gt;: !&lt;span style=&#34;color:#ae81ff&#34;&gt;Ref ApiGatewayApi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Path&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;/api/example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Method&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;get&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;a class=&#34;link&#34; href=&#34;https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DefinitionBody&lt;/a&gt; property of the &lt;strong&gt;ApiGatewayApi&lt;/strong&gt; allows you to specify an OpenAPI specification definition which is transformed and applied by CloudFormation upon deployment.&lt;/p&gt;
&lt;p&gt;The list of allowed IPs is passed to the SAM template as the &lt;strong&gt;AllowedIpsList&lt;/strong&gt; parameter. This parameter is referenced from within the OpenAPI specification using the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ref&lt;/a&gt; function.&lt;/p&gt;
&lt;h3 id=&#34;openapi-specification&#34;&gt;OpenAPI Specification
&lt;/h3&gt;&lt;p&gt;The OpenAPI specification, embedded in the CloudFormation template above, contains the definition of your API. The API Gateway Resource Policy is declared in the specification as an &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;API Gateway Extension&lt;/a&gt; to OpenAPI.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;---
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;openapi&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;3.0.3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;info&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;title&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;API Gateway IP Filtering Example API&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;version&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1.0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-policy&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;2012-10-17&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;Statement&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    - &lt;span style=&#34;color:#f92672&#34;&gt;Effect&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Allow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Principal&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Action&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:Invoke&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Resource&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        - &lt;span style=&#34;color:#ae81ff&#34;&gt;execute-api:/*/*/*&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;Condition&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;IpAddress&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;aws:SourceIp&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;Ref&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AllowedIpsList&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;paths&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;/api/example&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;get&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;summary&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Example API Endpoint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;operationId&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;responses&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#39;200&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;description&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Success&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;x-amazon-apigateway-integration&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uri&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;Fn::Sub&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ExampleFunction.Arn}:live/invocations&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;httpMethod&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;POST&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;type&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws_proxy&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we see the &lt;a class=&#34;link&#34; href=&#34;https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-ref.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ref&lt;/a&gt; function referring to the &lt;strong&gt;AllowedIpsList&lt;/strong&gt; parameter.&lt;/p&gt;
&lt;p&gt;This API Gateway Resource Policy is allowing all invocations where the source IP is in the list of IPs supplied.&lt;/p&gt;
&lt;h3 id=&#34;source-code&#34;&gt;Source Code
&lt;/h3&gt;&lt;p&gt;The source code and instructions to build and deploy this example to AWS can be found here: &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/api-gateway-ip-filtering&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/karlkyck/api-gateway-ip-filtering&lt;/a&gt;. Running this example on AWS will incur costs so be sure to delete the CloudFormation stacks when you are finished experimenting.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h3&gt;&lt;p&gt;This
is a simple, cheap way to allow access to your API Gateway APIs only from certain IP addresses. AWS WAF is an alternative, but it incurs costs.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Non-blocking Webapps with Spring Boot &amp; CompletableFuture</title>
        <link>https://humansreadcode.com/post/2017-07-19-spring-boot-completablefuture/</link>
        <pubDate>Wed, 19 Jul 2017 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2017-07-19-spring-boot-completablefuture/</guid>
        <description>&lt;p&gt;CompletableFuture, introduced in Java 8, provides an easy way to write asynchronous, non-blocking, multithreaded code. Since Spring 4.2 it’s now possible to have Controllers, Services, and Repositories return &lt;code&gt;CompletableFuture&lt;/code&gt; from non-private methods annotated with &lt;code&gt;@Async&lt;/code&gt;. In this blog post we will see how we can take advantage of this to write non-blocking, asynchronous code across multiple layers within our application.&lt;/p&gt;
&lt;p&gt;You can find the source code for the sample project for this post &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/spring-boot-completablefuture&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;interface-driven-multilayered-architecture&#34;&gt;Interface Driven Multilayered Architecture
&lt;/h2&gt;&lt;p&gt;Our application will consist of 3 layers of responsibility with each layer performing a specific role in the application:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The Controller layer for presentation (JSON)&lt;/li&gt;
&lt;li&gt;The Service layer for business logic&lt;/li&gt;
&lt;li&gt;The Repository layer for persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using a multilayered architecture pattern allows us to write modular code. With the Interface Driven Design architecture pattern we can establish a well known contract at the boundary of each module. This allows us to encapsulate the implementation details of each module and prevent those implementation details from leaking and causing coupling between modules.&lt;/p&gt;
&lt;p&gt;With this approach we can substitute the implementation of a module for an alternative implementation using the same well known contract as defined by that module’s interface e.g. an RDBMS implementation for a MongoDB implementation, or a mock implementation.&lt;/p&gt;
&lt;p&gt;This approach makes it much easier unit test our code by being able to mock each module by virtue of it’s interface.&lt;/p&gt;
&lt;h2 id=&#34;asyncconfiguration&#34;&gt;AsyncConfiguration
&lt;/h2&gt;&lt;p&gt;To achieve non-blocking with&lt;code&gt;CompletableFuture&lt;/code&gt;in our application we will need to configure &lt;code&gt;ThreadPoolTaskExecutor&lt;/code&gt; instances for each layer within our application. The reason for this is to ensure that one layer cannot starve another of threads and cause deadlock.&lt;/p&gt;
&lt;p&gt;A bounded thread pool is better for performance as spawning a new thread for each request can be costly. It is also useful to bound a thread pool as it makes you to consider the nature of your application and the resource and tuning requirements it will need in production.&lt;/p&gt;
&lt;p&gt;We make use of custom configuration properties, &lt;code&gt;ApplicationProperties&lt;/code&gt;, to configure each &lt;code&gt;ThreadPoolExecutor&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@EnableAsync&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AsyncConfiguration&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; AsyncConfigurer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_DEFAULT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_DEFAULT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_REPOSITORY)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getRepositoryAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_REPOSITORY);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_SERVICE)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getServiceAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_SERVICE);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_CONTROLLER)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getControllerAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_CONTROLLER);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; AsyncUncaughtExceptionHandler &lt;span style=&#34;color:#a6e22e&#34;&gt;getAsyncUncaughtExceptionHandler&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; SimpleAsyncUncaughtExceptionHandler();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;newTaskExecutor&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String taskExecutorNamePrefix) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;Async&lt;/span&gt; asyncProperties &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; applicationProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getAsync&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ThreadPoolTaskExecutor executor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ThreadPoolTaskExecutor();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setCorePoolSize&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getCorePoolSize&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setMaxPoolSize&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getMaxPoolSize&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setQueueCapacity&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getQueueCapacity&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setThreadNamePrefix&lt;/span&gt;(taskExecutorNamePrefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; executor;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;repository-layer&#34;&gt;Repository Layer
&lt;/h2&gt;&lt;p&gt;Here is our repository interface. As we are using MongoDB for this example we extend &lt;code&gt;MongoRepository&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserRepository&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; MongoRepository&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User, String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_REPOSITORY&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Page&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findAllBy&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable pageable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_REPOSITORY&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String id);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We specify our User domain model as the type this &lt;code&gt;Repository&lt;/code&gt; will manage. The id type for the User entity is of type String.&lt;/p&gt;
&lt;p&gt;Spring Data allows us to create &lt;a class=&#34;link&#34; href=&#34;http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories.query-methods&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;query methods&lt;/a&gt;, methods whose very signature defines a database query. When Spring Data creates a proxy bean for a &lt;code&gt;Repository&lt;/code&gt; it will use the query method signatures to implement the query you wish to execute. The &lt;code&gt;findByconvention&lt;/code&gt; allows us to define query methods and return &lt;code&gt;CompletableFuture&lt;/code&gt; instances from our query methods thus making them asynchronous and non-blocking.&lt;/p&gt;
&lt;p&gt;Check out my &lt;a class=&#34;link&#34; href=&#34;http://humansreadcode.com/spring-data-completablefuture/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;blog post&lt;/a&gt; on creating asynchronous query methods with Spring Data and &lt;code&gt;CompletableFuture&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;find-all-users&#34;&gt;Find All Users
&lt;/h3&gt;&lt;p&gt;With the following query method we can run a query to find all users in our database:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Page&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findAllBy&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable pageable);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Spring Data supports pagination out of the box and provides the &lt;code&gt;Page&lt;/code&gt; type that represents a page of entity objects. The &lt;code&gt;CompletableFuture&amp;lt;Page&amp;lt;User&amp;gt;&amp;gt;&lt;/code&gt; being returned by our method is yielding a page of User entity objects. To specify the pagination criteria to use in the query the &lt;code&gt;Pageable&lt;/code&gt; parameter is used. &lt;code&gt;Pageable&lt;/code&gt; is another type provided by Spring for this very purpose.&lt;/p&gt;
&lt;h3 id=&#34;find-one-user&#34;&gt;Find One User
&lt;/h3&gt;&lt;p&gt;The query method to find one user should return only one result so we use the prefix &lt;code&gt;findOne&lt;/code&gt;. We are also searching by the id of the user so we specify that by naming the method &lt;code&gt;findOneById&lt;/code&gt;. The parameter id allows us to pass the id of the user we are searching for. To make the method asynchronous we give it a return type of &lt;code&gt;CompletableFuture&amp;lt;User&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String id);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If no user is found the&lt;code&gt;CompletableFuture&lt;/code&gt; will yield a null result. Spring Data supports returning &lt;code&gt;Optional&lt;/code&gt; from standard query methods, but unfortunately there is no support for returning &lt;code&gt;CompletableFuture&amp;lt;Optional&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;service-layer&#34;&gt;Service Layer
&lt;/h2&gt;&lt;p&gt;Now to create our service layer. First we create an interface to define the contract for our service. Other than providing a contract on how you expose the functionality of your service, interface driven development is great for testing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserService&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Page&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findAll&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable pageable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String id);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The implementation for our service is very simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Service&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserServiceImpl&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; UserService {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; UserRepository userRepository;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserServiceImpl&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; UserRepository userRepository) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;userRepository&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userRepository;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_SERVICE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Page&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findAll&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable pageable) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; userRepository.&lt;span style=&#34;color:#a6e22e&#34;&gt;findAllBy&lt;/span&gt;(pageable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_SERVICE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String id) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; userRepository
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(id)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;thenApply&lt;/span&gt;(Optional::ofNullable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To let Spring and maintainers of your code (that includes you) know that we are creating a bean that will be used as a service we annotate the class with &lt;code&gt;@Service&lt;/code&gt;. &lt;code&gt;@Service&lt;/code&gt; doesn’t provide any additional behaviour over &lt;code&gt;@Component&lt;/code&gt; but it may do so at some point in the future and it helps to be explicit in your intentions for the bean.&lt;/p&gt;
&lt;p&gt;We are also using the recommended injection method of constructor based injection. If there is only one constructor in the bean then Spring doesn’t require the constructor be annotated with &lt;code&gt;@Inject&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To enable asynchronous execution using Spring we annotate our method implementations with &lt;code&gt;@Async&lt;/code&gt; and also provide the name of the executor we want the work to be dispatched to. Here we are using the &lt;code&gt;TASK_EXECUTOR_SERVICE&lt;/code&gt; executor.&lt;/p&gt;
&lt;p&gt;In the method &lt;code&gt;findOneById&lt;/code&gt; we are transforming our response object of User to &lt;code&gt;Optional&amp;lt;User&amp;gt;&lt;/code&gt; as the requested user may not exist. By wrapping the potentially null returned value in &lt;code&gt;Optional&lt;/code&gt; we are explicitly stating that the returned element may or may not be present.&lt;/p&gt;
&lt;h2 id=&#34;restcontroller&#34;&gt;RestController
&lt;/h2&gt;&lt;p&gt;Here’s what our RESTful controller looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@RestController&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@RequestMapping&lt;/span&gt;(value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; UserController.&lt;span style=&#34;color:#a6e22e&#34;&gt;REQUEST_PATH_API_USERS&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserController&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String REQUEST_PATH_API_USERS &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/api/users&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Logger log &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; LoggerFactory.&lt;span style=&#34;color:#a6e22e&#34;&gt;getLogger&lt;/span&gt;(UserController.&lt;span style=&#34;color:#a6e22e&#34;&gt;class&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String REQUEST_PATH_API_USERS_INDIVIDUAL_USER &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/{userId}&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; UserService userService;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserController&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; UserService userService) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;userService&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userService;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_CONTROLLER&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@GetMapping&lt;/span&gt;(produces &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; MediaType.&lt;span style=&#34;color:#a6e22e&#34;&gt;APPLICATION_JSON_UTF8_VALUE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getUsers&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable paging) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; userService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;findAll&lt;/span&gt;(paging)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;thenApply(ResponseEntity::ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;exceptionally&lt;/span&gt;(handleGetUsersFailure);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_CONTROLLER&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@GetMapping&lt;/span&gt;(value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; REQUEST_PATH_API_USERS_INDIVIDUAL_USER,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                produces &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; MediaType.&lt;span style=&#34;color:#a6e22e&#34;&gt;APPLICATION_JSON_UTF8_VALUE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getUser&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;@PathVariable&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String userId) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; userService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(userId)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;thenApply&lt;/span&gt;(mapMaybeUserToResponse)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;exceptionally&lt;/span&gt;(handleGetUserFailure.&lt;span style=&#34;color:#a6e22e&#34;&gt;apply&lt;/span&gt;(userId));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Throwable, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; handleGetUsersFailure &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; throwable &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Unable to retrieve users&amp;#34;&lt;/span&gt;, throwable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;INTERNAL_SERVER_ERROR&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; mapMaybeUserToResponse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; maybeUser &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; maybeUser
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;map(ResponseEntity::ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#a6e22e&#34;&gt;orElse&lt;/span&gt;(ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;notFound&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Throwable, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; handleGetUserFailure &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userId &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; throwable &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        log.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(String.&lt;span style=&#34;color:#a6e22e&#34;&gt;format&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Unable to retrieve user for id: %s&amp;#34;&lt;/span&gt;, userId), throwable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;INTERNAL_SERVER_ERROR&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To make our request methods asynchronous and non-blocking we annotate them with the &lt;code&gt;@Async&lt;/code&gt; annotation and specify the executor we want to dispatch the work on.&lt;/p&gt;
&lt;h3 id=&#34;get-all-users&#34;&gt;Get All Users
&lt;/h3&gt;&lt;p&gt;Here’s the method we use to return all users when an HTTP GET request is received:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;@Async(AsyncConfiguration.TASK_EXECUTOR_CONTROLLER)
@GetMapping(produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CompletableFuture&amp;lt;ResponseEntity&amp;gt; getUsers(final Pageable paging) {
    return userService
            .findAll(paging)
            .&amp;lt;ResponseEntity&amp;gt;thenApply(ResponseEntity::ok)
            .exceptionally(handleGetUsersFailure);
}
 
private static Function&amp;lt;Throwable, ResponseEntity&amp;gt; handleGetUsersFailure = throwable -&amp;gt; {
    log.error(&amp;#34;Unable to retrieve users&amp;#34;, throwable);
    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
};
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The return type from our method is &lt;code&gt;CompletableFuture&amp;lt;ResponseEntity&amp;gt;&lt;/code&gt; and we annotate the method with &lt;code&gt;@Async&lt;/code&gt; and specify the task executor we want to dispatch the work on. In this case we are using the &lt;code&gt;TASK_EXECUTOR_CONTROLLER&lt;/code&gt; task executor.&lt;/p&gt;
&lt;p&gt;It is possible to specify the type returned in your &lt;code&gt;ResponseEntity&lt;/code&gt; however in order to return error codes and error information of our own leaving this specificity out is necessary.&lt;/p&gt;
&lt;p&gt;The method takes a &lt;code&gt;Pageable&lt;/code&gt; parameter. This is a type provided by Spring and allows the caller to specify paging parameters e.g.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://localhost:8080/api/users?page=2&amp;amp;size=10
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With this URL we are requesting the users resource and specifying the page offset and the number of results to return.&lt;/p&gt;
&lt;p&gt;Our service and repository methods for finding all users take this Pageable parameter so all we need to do is pass it on.&lt;/p&gt;
&lt;p&gt;When we invoke our service method &lt;code&gt;findAll&lt;/code&gt; we get a &lt;code&gt;CompleteableFuture&amp;lt;Page&amp;lt;User&amp;gt;&amp;gt;&lt;/code&gt; back. Our job is to map this type to the expected type &lt;code&gt;CompletableFuture&amp;lt;ResponseEntity&amp;gt;&lt;/code&gt;. By using the method thenApply on&lt;code&gt;CompletableFuture&lt;/code&gt;we can do something with the return value in this case &lt;code&gt;Page&amp;lt;User&amp;gt;&lt;/code&gt;. All we need to do is wrap the &lt;code&gt;Page&amp;lt;User&amp;gt;&lt;/code&gt; object in a &lt;code&gt;ResponseEntity&lt;/code&gt; and give it a HTTP response code of &lt;code&gt;200&lt;/code&gt; (OK). Spring provides a handy way of instantiating just such a &lt;code&gt;ResponseEntity&lt;/code&gt; with the &lt;code&gt;ResponseEntity.ok()&lt;/code&gt; method.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;thenApply(ResponseEntity::ok)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We have to explicitly define the return type when invoking the &lt;code&gt;thenApply&lt;/code&gt; method to tell Java that we are creating a &lt;code&gt;ResponseEntity&amp;lt;Page&amp;lt;User&amp;gt;&amp;gt;&lt;/code&gt; object but we want it to be treated as a plain &lt;code&gt;ResponseEntity&lt;/code&gt; object. This helps us when we define our error recovery:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;exceptionally&lt;/span&gt;(handleGetUsersFailure);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;By specifying error handling code to be run in the event of an exception we can create an appropriate response to the client making the HTTP request. In this case we want to recover from any error and return a status code of &lt;code&gt;500&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;INTERNAL_SERVER_ERROR&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;get-one-user&#34;&gt;Get One User
&lt;/h3&gt;&lt;p&gt;This is the method we use to retrieve one user:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_CONTROLLER&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@GetMapping&lt;/span&gt;(value &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; REQUEST_PATH_API_USERS_INDIVIDUAL_USER,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            produces &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; MediaType.&lt;span style=&#34;color:#a6e22e&#34;&gt;APPLICATION_JSON_UTF8_VALUE&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;getUser&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;@PathVariable&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String userId) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; userService
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(userId)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#a6e22e&#34;&gt;thenApply&lt;/span&gt;(mapMaybeUserToResponse)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .&lt;span style=&#34;color:#a6e22e&#34;&gt;exceptionally&lt;/span&gt;(handleGetUserFailure.&lt;span style=&#34;color:#a6e22e&#34;&gt;apply&lt;/span&gt;(userId));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; mapMaybeUserToResponse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; maybeUser &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; maybeUser
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;map(ResponseEntity::ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#a6e22e&#34;&gt;orElse&lt;/span&gt;(ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;notFound&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Throwable, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; handleGetUserFailure &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userId &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; throwable &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(String.&lt;span style=&#34;color:#a6e22e&#34;&gt;format&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Unable to retrieve user for id: %s&amp;#34;&lt;/span&gt;, userId), throwable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;INTERNAL_SERVER_ERROR&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, to make this method asynchronous and non-blocking we annotate it with &lt;code&gt;@Async&lt;/code&gt; and return &lt;code&gt;CompletableFuture&amp;lt;ResponseEntity&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We need to bind the &lt;code&gt;{userId}&lt;/code&gt; path variable to the &lt;code&gt;userId&lt;/code&gt; parameter. This is done with &lt;code&gt;@PathVariable&lt;/code&gt;. Issuing a &lt;code&gt;GET&lt;/code&gt; request to the following URL will invoke this method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;http://localhost:8080/api/users/1234
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As with the &lt;code&gt;getAllUsers&lt;/code&gt; method we need to transform the &lt;code&gt;CompletableFuture&amp;lt;Optional&amp;lt;User&amp;gt;&amp;gt;&lt;/code&gt; response we get from the &lt;code&gt;UserService&lt;/code&gt; to &lt;code&gt;ResponseEntity&lt;/code&gt;. To do this we again use the &lt;code&gt;CompletableFuture.thenApplymethod&lt;/code&gt;. This time we create a pure function to transform the response:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Optional&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; mapMaybeUserToResponse &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; maybeUser &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; maybeUser
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;map(ResponseEntity::ok)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .&lt;span style=&#34;color:#a6e22e&#34;&gt;orElse&lt;/span&gt;(ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;notFound&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the case where the user exists we are mapping the &lt;code&gt;Optional&amp;lt;User&amp;gt;&lt;/code&gt; parameter to a &lt;code&gt;ResponseEntity&lt;/code&gt; with the User object as the body and a status code of &lt;code&gt;200&lt;/code&gt; (OK). If the &lt;code&gt;Optional&amp;lt;User&amp;gt;&lt;/code&gt; is empty we instead return a &lt;code&gt;ResponseEntity&lt;/code&gt; with no body and a status code of &lt;code&gt;404&lt;/code&gt; (Not Found).&lt;/p&gt;
&lt;p&gt;If there an exception is thrown we recover by sending a response with a status code of &lt;code&gt;500&lt;/code&gt; (Internal Server Error):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;String, Function&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Throwable, ResponseEntity&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; handleGetUserFailure &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; userId &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; throwable &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    log.&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;(String.&lt;span style=&#34;color:#a6e22e&#34;&gt;format&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Unable to retrieve user for id: %s&amp;#34;&lt;/span&gt;, userId), throwable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; ResponseEntity.&lt;span style=&#34;color:#a6e22e&#34;&gt;status&lt;/span&gt;(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;INTERNAL_SERVER_ERROR&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;wrapping-up&#34;&gt;Wrapping Up
&lt;/h2&gt;&lt;p&gt;By using this technique you can split up your application into separate layers and have each layer perform tasks asynchronously. This separation of concerns makes it easier for you to conceptualise your logic, combine and recombine your code and logic, and make it easier to tune, and test your code from unit to integration to system testing.&lt;/p&gt;
&lt;p&gt;Take a look at this code in action by cloning the &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/spring-boot-completablefuture&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;source code&lt;/a&gt;.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Asynchronous Query Methods with Spring Data &amp; Completable Future</title>
        <link>https://humansreadcode.com/post/2017-06-08-spring-boot-completablefuture/</link>
        <pubDate>Thu, 08 Jun 2017 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2017-06-08-spring-boot-completablefuture/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CompletableFuture&lt;/a&gt;, introduced in Java 8, provides an easy way to write asynchronous, non-blocking, multithreaded code. Since Spring 4.2 it’s now possible to write asynchronous code by returning &lt;code&gt;CompletableFuture&lt;/code&gt; from non-private methods annotated with &lt;code&gt;@Async&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Spring Data has taken advantage of this advancement and now allows you to to write non-blocking, asynchronous &lt;a class=&#34;link&#34; href=&#34;https://docs.spring.io/spring-data/jpa/reference/repositories/query-keywords-reference.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;code&gt;Repository&lt;/code&gt; queries using &lt;code&gt;CompletableFuture&lt;/code&gt;&lt;/a&gt;. This is done by returning &lt;code&gt;CompletableFuture&lt;/code&gt; from a query method and annotating the method with the &lt;code&gt;@Async&lt;/code&gt; annotation.&lt;/p&gt;
&lt;p&gt;When invoked the query method will return immediately with the actual query execution taking place in a task submitted to a Spring &lt;code&gt;TaskExecutor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can find the source code for this blog post &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/spring-boot-completablefuture/blob/master/src/main/java/com/humansreadcode/example/repository/UserRepository.java&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;repository&#34;&gt;Repository
&lt;/h2&gt;&lt;p&gt;Creating asynchronous query methods in a &lt;code&gt;Repository&lt;/code&gt; is as simple as returning &lt;code&gt;CompletableFuture&lt;/code&gt; from your query method and annotating it with &lt;code&gt;@Async&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserRepository&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; MongoRepository&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User, String&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_REPOSITORY&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;Page&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findAllBy&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; Pageable pageable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Async&lt;/span&gt;(AsyncConfiguration.&lt;span style=&#34;color:#a6e22e&#34;&gt;TASK_EXECUTOR_REPOSITORY&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompletableFuture&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;User&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;findOneById&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String id);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Spring even allows you to specify the &lt;code&gt;TaskExecutor&lt;/code&gt; to run the query on. In this case the query methods are using a &lt;code&gt;TaskExecutor&lt;/code&gt; configured in the custom &lt;code&gt;AsyncConfiguration&lt;/code&gt; file.&lt;/p&gt;
&lt;h2 id=&#34;task-executor&#34;&gt;Task Executor
&lt;/h2&gt;&lt;p&gt;When configuring a &lt;code&gt;TaskExecutor&lt;/code&gt; to use with asynchronous query method it is often advantageous to use a bounded &lt;code&gt;ThreadPoolTaskExecutor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;A bounded thread pool is better for performance as spawning a new thread for each request can be costly. It is also useful to bound a thread pool as it makes you to consider the nature of your application and the resource and tuning requirements it will need in production.&lt;/p&gt;
&lt;p&gt;Here’s an example of how to create a &lt;code&gt;ThreadPoolTaskExecutor&lt;/code&gt;, the source code for which can be found here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Configuration&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@EnableAsync&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AsyncConfiguration&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;implements&lt;/span&gt; AsyncConfigurer {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String TASK_EXECUTOR_DEFAULT &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;taskExecutor&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String TASK_EXECUTOR_NAME_PREFIX_DEFAULT &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;taskExecutor-&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String TASK_EXECUTOR_NAME_PREFIX_REPOSITORY &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;serviceTaskExecutor-&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String TASK_EXECUTOR_REPOSITORY &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;repositoryTaskExecutor&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationProperties applicationProperties;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AsyncConfiguration&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationProperties applicationProperties) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;applicationProperties&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; applicationProperties;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_DEFAULT)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_DEFAULT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;(name &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; TASK_EXECUTOR_REPOSITORY)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;getRepositoryAsyncExecutor&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; newTaskExecutor(TASK_EXECUTOR_NAME_PREFIX_REPOSITORY);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; AsyncUncaughtExceptionHandler &lt;span style=&#34;color:#a6e22e&#34;&gt;getAsyncUncaughtExceptionHandler&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; SimpleAsyncUncaughtExceptionHandler();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; Executor &lt;span style=&#34;color:#a6e22e&#34;&gt;newTaskExecutor&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; String taskExecutorNamePrefix) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ApplicationProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;Async&lt;/span&gt; asyncProperties &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; applicationProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getAsync&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; ThreadPoolTaskExecutor executor &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; ThreadPoolTaskExecutor();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setCorePoolSize&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getCorePoolSize&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setMaxPoolSize&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getMaxPoolSize&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setQueueCapacity&lt;/span&gt;(asyncProperties.&lt;span style=&#34;color:#a6e22e&#34;&gt;getQueueCapacity&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        executor.&lt;span style=&#34;color:#a6e22e&#34;&gt;setThreadNamePrefix&lt;/span&gt;(taskExecutorNamePrefix);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; executor;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The thread pool configuration parameters are being supplied by the custom configuration properties singleton that is injected into the constructor.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;SimpleAsyncUncaughtExceptionHandler&lt;/code&gt; simply logs any exceptions that occur during the execution of a task.&lt;/p&gt;
&lt;p&gt;Hopefully this gives you an idea of the powerful asynchronous features Spring with its support for &lt;code&gt;CompletableFuture&lt;/code&gt; brings.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Self contained projects with Gradle Wrapper</title>
        <link>https://humansreadcode.com/post/2017-06-03-gradle-wrapper/</link>
        <pubDate>Sat, 03 Jun 2017 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2017-06-03-gradle-wrapper/</guid>
        <description>&lt;p&gt;The Gradle Wrapper is a handy way of bundling a Gradle runtime with your project. That way you provide a specific version of Gradle to be used with your project and Gradle does not have to be installed separately. This is very useful for anyone who clones your repo and wants to build your project.&lt;/p&gt;
&lt;p&gt;To generate a Gradle Wrapper for your project you will need to have Gradle installed. This is necessary to first generate the Gradle Wrapper but from then on the Wrapper can be used to run Gradle commands against your project without having to have Gradle installed.&lt;/p&gt;
&lt;p&gt;You can find a sample project using the Gradle Wrapper &lt;a class=&#34;link&#34; href=&#34;https://github.com/karlkyck/spring-boot-completablefuture&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;install-gradle&#34;&gt;Install Gradle
&lt;/h2&gt;&lt;p&gt;Begin by installing Gradle. This is a simple as&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ensuring you have Java 7 or higher&lt;/li&gt;
&lt;li&gt;Downloading a Gradle distribution&lt;/li&gt;
&lt;li&gt;Unzipping the Gradle distribution to a location of your choice&lt;/li&gt;
&lt;li&gt;Adding the &lt;code&gt;&amp;lt;gradle-install-path/bin&lt;/code&gt; folder to your PATH&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Official instructions can be found &lt;a class=&#34;link&#34; href=&#34;https://gradle.org/install&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;generate-the-gradle-wrapper&#34;&gt;Generate the Gradle Wrapper
&lt;/h2&gt;&lt;p&gt;To generate a Gradle Wrapper for your project and make it self contained execute the following command in the root folder of the project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gradle wrapper --gradle-version 3.5
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Be sure to set the &amp;ndash;gradle-version flag to the version of Gradle you wish to use with your project.&lt;/p&gt;
&lt;h2 id=&#34;add-generated-files-to-vcs&#34;&gt;Add Generated Files to VCS
&lt;/h2&gt;&lt;p&gt;Now that the Gradle Wrapper has been generated for you project you will see the following new files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;your project folder&amp;gt;/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gradlew
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gradlew.bat
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  gradle/wrapper/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gradle-wrapper.jar
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    gradle-wrapper.properties
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;All of the above files must be checked into your version control system.&lt;/p&gt;
&lt;h2 id=&#34;add-sha-256-checksum-verification&#34;&gt;Add SHA-256 Checksum Verification
&lt;/h2&gt;&lt;p&gt;For added security and to ensure the integrity of the Gradle distribution downloaded by the Gradle Wrapper you can configure the SHA-256 checksum verification. To do this you will need to generate a SHA-256 hash of the target distribution:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; shasum -a &lt;span style=&#34;color:#ae81ff&#34;&gt;256&lt;/span&gt; gradle-3.5-all.zip 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d84bf6b6113da081d0082bcb63bd8547824c6967fe68704d1e3a6fde822b7212  gradle-3.5-all.zip
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Add the hash sum to your project’s gradle-wrapper.properties file with the distributionSha256Sum property:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;distributionSha256Sum=d84bf6b6113da081d0082bcb63bd8547824c6967fe68704d1e3a6fde822b7212
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;run-the-gradle-wrapper&#34;&gt;Run the Gradle Wrapper
&lt;/h2&gt;&lt;p&gt;Run the Gradle Wrapper to make sure everything is working by executing the following command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./gradlew clean
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The Gradle Wrapper should download the target Gradle distribution, verify the integrity of the file using the SHA-256 checksum and then run the specified command.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Performance Testing with ab and Docker</title>
        <link>https://humansreadcode.com/post/2017-05-29-ab-testing-docker/</link>
        <pubDate>Mon, 29 May 2017 22:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/post/2017-05-29-ab-testing-docker/</guid>
        <description>&lt;p&gt;Whenever possible I use official Docker images to run applications, services, and tools so I don’t have to install and maintain a myriad of different applications on my development machine. The Apache HTTP server benchmarking tool &lt;code&gt;ab&lt;/code&gt; is a handy utility you can use to quickly performance test your HTTP services. It comes bundled as part of the Apache HTTP server installation, but why bother installing it when you can just use the official Docker image.&lt;/p&gt;
&lt;h2 id=&#34;docker-run&#34;&gt;Docker Run
&lt;/h2&gt;&lt;p&gt;To run the latest Docker image for the Apache HTTP server on linux:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker run -dit --name httpd-ab -v /var/www/html:/usr/local/apache2/htdocs/ httpd
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will pull down the latest official Apache HTTP server Docker image, start the httpdserver, and name the container httpd-ab. The volume -v /var/www/html:/usr/local/apache2/htdocs/ is used to serve HTML from the /var/www/html directory on the host machine.&lt;/p&gt;
&lt;h2 id=&#34;docker-exec&#34;&gt;Docker Exec
&lt;/h2&gt;&lt;p&gt;You can access the ab command line tool on the running container by running the following command on linux:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;docker exec -it httpd-ab bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will drop you into a bash session running on the container. You can now run the abcommand to performance test your application.&lt;/p&gt;
&lt;h2 id=&#34;example-command&#34;&gt;Example Command
&lt;/h2&gt;&lt;p&gt;Here’s an example command you can run to performance test a server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ab -c &lt;span style=&#34;color:#ae81ff&#34;&gt;350&lt;/span&gt; -n &lt;span style=&#34;color:#ae81ff&#34;&gt;20000&lt;/span&gt; example.com/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This command will execute 20000 HTTP &lt;code&gt;GET&lt;/code&gt; requests to &lt;code&gt;example.com&lt;/code&gt; maxing out at 350 simultaneous requests.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Search</title>
        <link>https://humansreadcode.com/page/search/</link>
        <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
        
        <guid>https://humansreadcode.com/page/search/</guid>
        <description></description>
        </item>
        
    </channel>
</rss>
