{"id":51395,"date":"2025-08-07T10:20:20","date_gmt":"2025-08-07T10:20:20","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=51395"},"modified":"2025-08-07T10:20:20","modified_gmt":"2025-08-07T10:20:20","slug":"ansible-execution-strategies-delegation-fact-caching-and-async-jobs","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/ansible-execution-strategies-delegation-fact-caching-and-async-jobs\/","title":{"rendered":"Ansible Execution: Strategies, Delegation, Fact Caching, and Async Jobs"},"content":{"rendered":"\n<p>Below is a <strong>detailed Ansible tutorial<\/strong> covering execution strategies (linear vs free), task delegation, fact caching, and async jobs\u2014with <strong>clear code examples, explanations, and a professional tutorial structure<\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><\/h1>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1. Understanding Ansible Execution Strategies<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is an Execution Strategy?<\/strong><\/h3>\n\n\n\n<p>Ansible\u2019s execution strategy determines <strong>how tasks are scheduled and run across all targeted hosts<\/strong> in your inventory during a playbook run.<br>The two main built-in strategies are <strong><code>linear<\/code><\/strong> and <strong><code>free<\/code><\/strong>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>A. The <code>linear<\/code> Execution Strategy (Default)<\/strong><\/h3>\n\n\n\n<p><strong>How it works:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ansible runs each task on <strong>all hosts<\/strong> in the play <em>before<\/em> proceeding to the next task.<\/li>\n\n\n\n<li>If any host fails on a task, Ansible stops running tasks for that host (unless you use <code>ignore_errors<\/code>).<\/li>\n\n\n\n<li>Ensures all hosts remain \u201cin sync\u201d across tasks.<\/li>\n<\/ul>\n\n\n\n<p><strong>Analogy:<\/strong> Like marching in step\u2014everyone completes step 1, then step 2, together.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example:<\/strong><\/h4>\n\n\n\n<p>Suppose you have 3 web servers and the following playbook:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">- name: Install and start nginx on all web servers (linear)\n  hosts: webservers\n  tasks:\n    - name: Install nginx\n      yum:\n        name: nginx\n        state: present\n    - name: Start nginx\n      service:\n        name: nginx\n        state: started\n<\/code><\/span><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Ansible will:\n<ol class=\"wp-block-list\">\n<li>Install nginx on <em>all<\/em> webservers.<\/li>\n\n\n\n<li>Only after step 1 is complete on all, start nginx on <em>all<\/em>.<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>B. The <code>free<\/code> Execution Strategy<\/strong><\/h3>\n\n\n\n<p><strong>How it works:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ansible runs tasks <strong>on each host as soon as possible<\/strong>, without waiting for other hosts to catch up.<\/li>\n\n\n\n<li>Hosts \u201crace ahead\u201d independently if earlier tasks finish sooner.<\/li>\n\n\n\n<li>This can <strong>dramatically speed up playbook runs<\/strong> in environments where some hosts are slower\/faster.<\/li>\n<\/ul>\n\n\n\n<p><strong>Analogy:<\/strong> Like a relay race\u2014each host runs as fast as it can, independently.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>How to Enable <code>free<\/code> Strategy:<\/strong><\/h4>\n\n\n\n<p>You can set it for an entire playbook or per-play:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>For a playbook run:<\/strong> <code>ansible-playbook play.yml -e 'ansible_strategy=free'<\/code><\/li>\n\n\n\n<li><strong>Per play in a playbook:<\/strong> <code>- name: Do things in free mode hosts: all strategy: free tasks: # ...<\/code><\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example:<\/strong><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">- name: <span class=\"hljs-keyword\">Use<\/span> <span class=\"hljs-title\">free<\/span> <span class=\"hljs-title\">strategy<\/span> <span class=\"hljs-title\">for<\/span> <span class=\"hljs-title\">faster<\/span> <span class=\"hljs-title\">parallel<\/span> <span class=\"hljs-title\">execution<\/span>\n  <span class=\"hljs-title\">hosts<\/span>: <span class=\"hljs-title\">webservers<\/span>\n  <span class=\"hljs-title\">strategy<\/span>: <span class=\"hljs-title\">free<\/span>\n  <span class=\"hljs-title\">tasks<\/span>:\n    - <span class=\"hljs-title\">name<\/span>: <span class=\"hljs-title\">Long<\/span>-<span class=\"hljs-title\">running<\/span> <span class=\"hljs-title\">task<\/span>\n      <span class=\"hljs-title\">shell<\/span>: <span class=\"hljs-title\">sleep<\/span> 10 &amp;&amp; <span class=\"hljs-title\">echo<\/span> <span class=\"hljs-title\">done<\/span>\n    - <span class=\"hljs-title\">name<\/span>: <span class=\"hljs-title\">Quick<\/span> <span class=\"hljs-title\">task<\/span>\n      <span class=\"hljs-title\">shell<\/span>: <span class=\"hljs-title\">echo<\/span> <span class=\"hljs-title\">quick<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>Each host will run both tasks as soon as it can, independently of others.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Comparison Table<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>linear (default)<\/th><th>free<\/th><\/tr><\/thead><tbody><tr><td>Sync between hosts<\/td><td>Yes<\/td><td>No<\/td><\/tr><tr><td>Proceeds on error<\/td><td>No (unless ignore_errors)<\/td><td>Yes (for other hosts)<\/td><\/tr><tr><td>Use case<\/td><td>Ordered changes, tight sync<\/td><td>Speed, high parallelism<\/td><\/tr><tr><td>Set via<\/td><td>Default<\/td><td><code>strategy: free<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2. Task Delegation<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is Task Delegation in Ansible?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Delegation<\/strong> allows you to run a task \u201cfor one host, but on another.\u201d<\/li>\n\n\n\n<li>Useful for centralized actions (e.g., updating a load balancer, fetching from a jump host, registering DNS, etc.)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How to Use Task Delegation<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>delegate_to<\/code> keyword is added to a task.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example:<\/strong><\/h4>\n\n\n\n<p>Suppose you want to copy a file from your Ansible control node to <em>all<\/em> webservers, but want to <strong>restart the load balancer<\/strong> only once (from your control node):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">- name: Deploy app and update load balancer\n  <span class=\"hljs-attr\">hosts<\/span>: webservers\n  <span class=\"hljs-attr\">tasks<\/span>:\n    - name: Deploy app\n      <span class=\"hljs-attr\">copy<\/span>:\n        src: app.tar.gz\n        <span class=\"hljs-attr\">dest<\/span>: <span class=\"hljs-regexp\">\/var\/<\/span>www\/app.tar.gz\n\n    - name: Restart load balancer after deploy\n      <span class=\"hljs-attr\">shell<\/span>: systemctl reload haproxy\n      <span class=\"hljs-attr\">delegate_to<\/span>: loadbalancer01\n      <span class=\"hljs-attr\">run_once<\/span>: <span class=\"hljs-literal\">true<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Explanation:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>delegate_to: loadbalancer01<\/code> runs the task on host <code>loadbalancer01<\/code>.<\/li>\n\n\n\n<li><code>run_once: true<\/code> ensures it runs only once (not once per webserver).<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>More Delegation Examples<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Gather facts from a remote server, but run a task on localhost:<\/strong> <code>- name: Save the public IP of each host to a file on the control node lineinfile: path: \"\/tmp\/public_ips.txt\" line: \"{{ inventory_hostname }}: {{ ansible_default_ipv4.address }}\" delegate_to: localhost<\/code><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3. Fact Caching<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What is Fact Caching?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Facts<\/strong> are system info collected by Ansible with the <code>setup<\/code> module (e.g., IP, OS, memory).<\/li>\n\n\n\n<li><strong>Fact caching<\/strong> saves these facts between playbook runs to speed up execution and reuse information, instead of recollecting facts every time.<\/li>\n\n\n\n<li>Useful for large inventories or when using dynamic inventories\/cloud.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How to Enable Fact Caching<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set <code>fact_caching<\/code> in your <code>ansible.cfg<\/code>.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example (YAML file-based caching):<\/strong><\/h4>\n\n\n\n<p>Add to your <code>ansible.cfg<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">&#91;defaults]\nfact_caching = yaml\nfact_caching_connection = <span class=\"hljs-regexp\">\/tmp\/<\/span>ansible_facts\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<ul class=\"wp-block-list\">\n<li>This will cache facts as YAML files in <code>\/tmp\/ansible_facts\/<\/code>.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Other supported backends:<\/strong><\/h4>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>jsonfile<\/code><\/li>\n\n\n\n<li><code>memcached<\/code><\/li>\n\n\n\n<li><code>redis<\/code><\/li>\n\n\n\n<li><code>mongodb<\/code><\/li>\n\n\n\n<li>More: <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_cache.html\" target=\"_blank\" rel=\"noopener\">Ansible fact caching docs<\/a><\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example Usage:<\/strong><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">ansible all -m setup  <span class=\"hljs-comment\"># Gather facts and cache them<\/span>\nansible-playbook play.yml  <span class=\"hljs-comment\"># Next run uses cached facts<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><strong>Tip:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <code>gather_facts: false<\/code> if you want to use cached facts only, or manage fact collection manually.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4. Asynchronous Jobs (async and poll)<\/strong><\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What are Async Jobs in Ansible?<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Async jobs allow you to <strong>run tasks in the background<\/strong> on a host, and optionally check for their completion later.<\/li>\n\n\n\n<li>Useful for long-running commands (package updates, service restarts, big file downloads, etc.).<\/li>\n\n\n\n<li>Avoids timeouts and makes playbooks faster.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>How to Use Async and Poll<\/strong><\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <code>async<\/code> to specify a <strong>timeout<\/strong> (in seconds).<\/li>\n\n\n\n<li>Use <code>poll<\/code> to set how often to check for completion:\n<ul class=\"wp-block-list\">\n<li><code>poll: 0<\/code> means \u201cfire and forget\u201d (don\u2019t wait)<\/li>\n\n\n\n<li><code>poll: n<\/code> means \u201ccheck every n seconds until done or timeout\u201d<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Example 1: Fire and Forget<\/strong><\/h4>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">- name: Start a long task in the background and don't wait\n  shell: \/usr\/local\/bin\/do_something_heavy\n  async: 1200  # 20 minutes allowed\n  poll: 0\n<\/code><\/span><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Example 2: Async with Polling<\/strong><\/h4>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">- name: Run a task <span class=\"hljs-keyword\">for<\/span> up to <span class=\"hljs-number\">5<\/span> minutes, polling every <span class=\"hljs-number\">30<\/span> seconds\n  <span class=\"hljs-attr\">shell<\/span>: <span class=\"hljs-regexp\">\/usr\/<\/span>local\/bin\/slow_task\n  <span class=\"hljs-attr\">async<\/span>: <span class=\"hljs-number\">300<\/span>\n  <span class=\"hljs-attr\">poll<\/span>: <span class=\"hljs-number\">30<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Example 3: Start Async, Then Wait Later<\/strong><\/h4>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Start task async\/poll: 0, register the job.<\/li>\n\n\n\n<li>Use the <code>async_status<\/code> module to wait for the result.<\/li>\n<\/ol>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">- name: Start a long task <span class=\"hljs-keyword\">in<\/span> the background\n  <span class=\"hljs-attr\">shell<\/span>: <span class=\"hljs-regexp\">\/usr\/<\/span>local\/bin\/do_heavy_work\n  <span class=\"hljs-attr\">async<\/span>: <span class=\"hljs-number\">600<\/span>\n  <span class=\"hljs-attr\">poll<\/span>: <span class=\"hljs-number\">0<\/span>\n  <span class=\"hljs-attr\">register<\/span>: async_job\n\n- name: Wait <span class=\"hljs-keyword\">for<\/span> <span class=\"hljs-keyword\">async<\/span> job to complete\n  <span class=\"hljs-attr\">async_status<\/span>:\n    jid: <span class=\"hljs-string\">\"{{ async_job.ansible_job_id }}\"<\/span>\n  <span class=\"hljs-attr\">register<\/span>: job_result\n  <span class=\"hljs-attr\">until<\/span>: job_result.finished\n  <span class=\"hljs-attr\">retries<\/span>: <span class=\"hljs-number\">30<\/span>\n  <span class=\"hljs-attr\">delay<\/span>: <span class=\"hljs-number\">10<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Summary Table<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Usage<\/th><th>Example Keyword<\/th><th>Example Code\/Config<\/th><\/tr><\/thead><tbody><tr><td><strong>Execution Strategy<\/strong><\/td><td>Ordered\/sync or free\/async<\/td><td><code>strategy: linear\/free<\/code><\/td><td><code>strategy: free<\/code><\/td><\/tr><tr><td><strong>Delegation<\/strong><\/td><td>Run task on other host<\/td><td><code>delegate_to<\/code><\/td><td><code>delegate_to: localhost<\/code><\/td><\/tr><tr><td><strong>Fact Caching<\/strong><\/td><td>Speed up fact gathering<\/td><td><code>fact_caching<\/code> in config<\/td><td><code>fact_caching: yaml<\/code><\/td><\/tr><tr><td><strong>Async Jobs<\/strong><\/td><td>Background\/parallel work<\/td><td><code>async<\/code>\/<code>poll<\/code><\/td><td><code>async: 600<\/code> <code>poll: 0<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Best Practices<\/strong><\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use <code>linear<\/code> for most playbooks, <code>free<\/code> for maximum parallelism when order doesn\u2019t matter.<\/li>\n\n\n\n<li>Delegate tasks when you need actions to occur on \u201ccontroller\u201d or special nodes (DNS, LB, etc.).<\/li>\n\n\n\n<li>Enable fact caching in large or cloud environments to save time and API calls.<\/li>\n\n\n\n<li>Use async for long-running tasks, especially when scaling out!<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>References &amp; Further Reading<\/strong><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_strategies.html\" target=\"_blank\" rel=\"noopener\">Ansible Strategies Documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_delegation.html\" target=\"_blank\" rel=\"noopener\">Delegation, Rolling Updates, and Local Actions<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_cache.html\" target=\"_blank\" rel=\"noopener\">Fact Caching Guide<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/user_guide\/playbooks_async.html\" target=\"_blank\" rel=\"noopener\">Async Actions and Polling<\/a><\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Below is a detailed Ansible tutorial covering execution strategies (linear vs free), task delegation, fact caching, and async jobs\u2014with clear code examples, explanations, and a professional tutorial structure. 1. Understanding&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[2],"tags":[],"class_list":["post-51395","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51395","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=51395"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51395\/revisions"}],"predecessor-version":[{"id":51397,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/51395\/revisions\/51397"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=51395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=51395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=51395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}