<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thomas P. Fuller</title>
    <description>The latest articles on DEV Community by Thomas P. Fuller (@thospfuller).</description>
    <link>https://dev.to/thospfuller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F306411%2F354f66a8-6604-4fdd-8fee-f3de305ddc70.jpeg</url>
      <title>DEV Community: Thomas P. Fuller</title>
      <link>https://dev.to/thospfuller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thospfuller"/>
    <language>en</language>
    <item>
      <title>Tutorial: Learn how to use the H2 Database with Spring Boot! 🤔</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Tue, 25 Jun 2024 11:59:22 +0000</pubDate>
      <link>https://dev.to/thospfuller/tutorial-learn-how-to-use-the-h2-database-with-spring-boot-2e1b</link>
      <guid>https://dev.to/thospfuller/tutorial-learn-how-to-use-the-h2-database-with-spring-boot-2e1b</guid>
      <description>&lt;p&gt;&lt;strong&gt;In this &lt;a href="https://thospfuller.com/categories/tutorials/" rel="noopener noreferrer"&gt;instructional&lt;/a&gt; we’ll review an example application which is written in the &lt;a href="https://www.groovy-lang.org/" rel="noopener noreferrer"&gt;Groovy Programming Language&lt;/a&gt; and which demonstrates how to use the &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2 relational database&lt;/a&gt; (&lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2 DB&lt;/a&gt; / &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2&lt;/a&gt;) with &lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The benefit from using the &lt;a href="https://thospfuller.com/categories/software-engineering/groovy-programming-language/" rel="noopener noreferrer"&gt;Groovy Programming Language&lt;/a&gt;, in this case, is that it allows an &lt;a href="https://thospfuller.com/categories/examples/" rel="noopener noreferrer"&gt;example&lt;/a&gt; to ship exactly one file which contains everything we need in order to run the application.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2 Database Engine&lt;/a&gt; is a powerful &lt;a href="https://thospfuller.com/2023/12/28/database-change-notifications-in-the-h2-database/#what-is-the-h2-database-license-accordion-tab" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; &lt;a href="https://thospfuller.com/categories/software-engineering/relational-databases/" rel="noopener noreferrer"&gt;relational database&lt;/a&gt; which is written in the &lt;a href="https://www.java.com/" rel="noopener noreferrer"&gt;Java Programming Language&lt;/a&gt; and which is used with some frequency in &lt;a href="https://thospfuller.com/categories/software-engineering/" rel="noopener noreferrer"&gt;software development&lt;/a&gt; projects — especially when it comes to testing applications.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2&lt;/a&gt; with the &lt;a href="https://spring.io/projects/spring-framework" rel="noopener noreferrer"&gt;Spring Framework&lt;/a&gt; and with &lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt;, in particular, is a common use case, one which we’ll demonstrate here.&lt;/p&gt;

&lt;p&gt;In the next section we’ll take a look at the &lt;a href="https://thospfuller.com/categories/examples/" rel="noopener noreferrer"&gt;example&lt;/a&gt; and dissect, in detail, what happens in each step.&lt;/p&gt;

&lt;p&gt;Note that in a few places I’ve added code which should not be required if we were to write this same solution using the &lt;a href="https://thospfuller.com/categories/software-engineering/java-programming-language/" rel="noopener noreferrer"&gt;Java Programming Language&lt;/a&gt; and a properly structured &lt;a href="https://maven.apache.org/" rel="noopener noreferrer"&gt;Maven&lt;/a&gt; project — I attempt to point this out, where appropriate.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://gist.github.com/thospfuller/c0ac73cf450592ac262c2b098e65b4f6" rel="noopener noreferrer"&gt;H2 with Spring Boot Example on GitHub&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Included here is a link to the &lt;a href="https://gist.github.com/thospfuller/c0ac73cf450592ac262c2b098e65b4f6" rel="noopener noreferrer"&gt;GitHub gist&lt;/a&gt; pertaining to the example used to demonstrate connecting the &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2 Relational Database&lt;/a&gt; with &lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt; -- you should be able to paste this script into the &lt;a href="https://groovy-lang.org/groovyconsole.html" rel="noopener noreferrer"&gt;groovyConsole&lt;/a&gt; and run as-is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spring Boot With H2 DB Example Maven Dependencies
&lt;/h2&gt;

&lt;p&gt;The following dependencies are used in this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure" rel="noopener noreferrer"&gt;Spring Boot AutoConfigure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/org.springframework/spring-jdbc" rel="noopener noreferrer"&gt;Spring JDBC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/com.h2database/h2" rel="noopener noreferrer"&gt;H2 Database Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api" rel="noopener noreferrer"&gt;Javax Annotation API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mvnrepository.com/artifact/org.slf4j/slf4j-simple" rel="noopener noreferrer"&gt;SLF4J Simple Provider&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;a href="https://docs.groovy-lang.org/latest/html/documentation/grape.html" rel="noopener noreferrer"&gt;Groovy Grape&lt;/a&gt; dependency management system should find these dependencies automatically when the script is executed however for reference purposes I’ve included these here.&lt;/p&gt;

&lt;h2&gt;
  
  
  An example pertaining to using the H2 Database Engine with Spring Boot
&lt;/h2&gt;

&lt;p&gt;In this section we’ll take a look at the script in closer detail and go over what’s happening in each step.&lt;/p&gt;

&lt;p&gt;Preconditions&lt;br&gt;
In order to run this example, you will need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java version 22.0.1 (required)&lt;/li&gt;
&lt;li&gt;Groovy 4.0.17 (required)&lt;/li&gt;
&lt;li&gt;groovyConsole (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This script can be executed using Groovy alone hence the groovyConsole is optional.&lt;/p&gt;

&lt;p&gt;The script uses the &lt;a href="https://dev.tourl"&gt;Groovy Adaptable Packaging Engine&lt;/a&gt; (&lt;a href="https://docs.groovy-lang.org/latest/html/documentation/grape.html" rel="noopener noreferrer"&gt;Groovy Grape&lt;/a&gt;) to pull in dependencies from &lt;a href="https://central.sonatype.com/" rel="noopener noreferrer"&gt;Maven Central&lt;/a&gt; hence a connection to the Internet is required as well.&lt;/p&gt;

&lt;p&gt;I’ve included an example of what the output should look like when running this script from the command line here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftib3isdl0k3a9tooab2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftib3isdl0k3a9tooab2k.png" alt="H2 DB with Spring Boot Successful CRUD Example Output" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;red arrow&lt;/strong&gt; points to the command used to run the script, and &lt;strong&gt;orange arrow&lt;/strong&gt; points to the log statement that indicates the script is starting, and the &lt;strong&gt;blue arrow&lt;/strong&gt; points to the log statement that indicates that the script has finished running.&lt;/p&gt;

&lt;p&gt;In this example, the script runs a Spring Boot application that creates a table in the H2 DB, executes several CRUD (create, read, update, delete) operations on that table, and then drops the table.&lt;/p&gt;

&lt;p&gt;The Groovy script runs to completion successfully and then exits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step One: Declare a package.
&lt;/h3&gt;

&lt;p&gt;When we define the Spring Boot Application, we’ll include the scanBasePackages setting, which requires a package name so we set that here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-one-spring-boot-with-h2-db-package-declaration.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-one-spring-boot-with-h2-db-package-declaration.png" alt="[Step One](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-one): Define a package for this script." width="800" height="20"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Two: Add the Groovy Grape GrabConfig annotation.
&lt;/h3&gt;

&lt;p&gt;In step two we need to add the Groovy Grape GrabConfig annotation and also set the systemClassLoader property to true — if we do not have this an exception will be thrown when the script is executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-two-spring-boot-with-h2-database-systemclassloader-setting.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-two-spring-boot-with-h2-database-systemclassloader-setting.png" alt="[Step Two](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-two): Set the systemClassLoader to true for the GrabConfig for Groovy." width="800" height="19"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Three: Grab dependencies and import required classes.
&lt;/h3&gt;

&lt;p&gt;In step three we need to grab the dependencies necessary to run this example as well as import required classes — this includes the Spring Boot, H2 Database, and other supporting classes.&lt;/p&gt;

&lt;p&gt;Note that we’re using the Hikari database driver in this example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-three-spring-boot-with-h2-example-imports.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-three-spring-boot-with-h2-example-imports.png" alt="[Step Three](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-three): Grab dependencies and import classes." width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See the &lt;a href="https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#maven-dependencies" rel="noopener noreferrer"&gt;Maven Dependencies&lt;/a&gt; section in this article for complete details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Four: Obtain a reference to an SLF4J logger.
&lt;/h3&gt;

&lt;p&gt;We’re using the SLF4J log delegation framework in this example and we’ll send messages to console output so we can watch what’s happening as the script executes.&lt;/p&gt;

&lt;p&gt;The HikariCP dependency is one other framework that we’re using that also uses SLF4J and we’ve included this high performance connection pooling implementation in this example.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-four-spring-boot-h2-db-get-slf4j-logger.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-four-spring-boot-h2-db-get-slf4j-logger.png" alt="[Step Four](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-four): Get an instance of the SLF4J logger." width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Five: Configure H2 database datasource and JdbcTemplate beans.
&lt;/h3&gt;

&lt;p&gt;In the fifth step we’ll configure the H2 Database datasource which utilizes the HikariCP high performance connection pool dependency as the datasource type.&lt;/p&gt;

&lt;p&gt;Since this example demonstrates some simple CRUD operations executed against the H2 Database from a Spring Boot application, we’ll also configure an instance of JdbcTemplate here which uses this data source.&lt;/p&gt;

&lt;p&gt;Note that we’re assigning the HikariDataSource class as the datasource type.&lt;/p&gt;

&lt;p&gt;The H2 DB instance configured in this example will reside in-memory only — if we want to persist this information to disk then we need to change the URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-five-declare-h2-db-datasource-and-jdbctemplate-bean-configurations.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-five-declare-h2-db-datasource-and-jdbctemplate-bean-configurations.png" alt="[Step Five](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-five): Review the configuration class for setting up the H2 in-memory database with HikariCP and JdbcTemplate in this example Spring Boot application." width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Six: Create a repository class.
&lt;/h3&gt;

&lt;p&gt;In this step we implement a repository that contains the CRUD operations that we can execute on the H2 Database instance via the JdbcTemplate, which is autowired in this example by Spring Boot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-six-h2-db-spring-boot-example-repository.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-six-h2-db-spring-boot-example-repository.png" alt="[Step Six](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-six): The ExampleRepository class is a Spring Repository that manages a database table named " width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Seven: Implement a service bean.
&lt;/h3&gt;

&lt;p&gt;In this step we implement a transactional service bean which has stop and start lifecycle methods along with convenience methods that delegate to the repository bean.&lt;/p&gt;

&lt;p&gt;The start method creates the example table in H2 when Spring Boot initializes the beans that the container is managing, and the stop method drops the example table before the container stops.&lt;/p&gt;

&lt;p&gt;Other methods defined in the ExampleService deliver convenience and hide implementation details.&lt;/p&gt;

&lt;p&gt;Using a service aids in reuse and is also helpful when testing our code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-seven-h2-db-spring-boot-example-service.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-seven-h2-db-spring-boot-example-service.png" alt="[Step Seven](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-seven): The ExampleService class handles database operations with transaction management using the ExampleRepository in this Example Spring Boot application." width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the image has been truncated, refer to the &lt;a href="https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#complete-example" rel="noopener noreferrer"&gt;full example&lt;/a&gt; below or on the &lt;a href="https://gist.github.com/thospfuller/c0ac73cf450592ac262c2b098e65b4f6#file-h2-database-spring-boot-groovy-L137" rel="noopener noreferrer"&gt;GitHub Gist&lt;/a&gt; for the complete implementation details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Eight: Implement the Spring Boot CommandLineRunner interface.
&lt;/h3&gt;

&lt;p&gt;In this step we implement the Spring Boot CommandLineRunner specification.&lt;/p&gt;

&lt;p&gt;Our implementation includes executing CRUD operations via the service created in &lt;a href="https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-seven" rel="noopener noreferrer"&gt;step seven&lt;/a&gt; against the H2 Database.&lt;/p&gt;

&lt;p&gt;We log some information along the way so we can see what happens as each CRUD operation completes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-eight-h2-db-spring-boot-example-commandlinerunner.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-eight-h2-db-spring-boot-example-commandlinerunner.png" alt="[Step Eight](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-eight): Spring Boot CommandLineRunner implementation that demonstrates example H2 database operations." width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Nine: Configure Spring Boot Application for Component Scanning
&lt;/h3&gt;

&lt;p&gt;The code in the snippet defines a Spring Boot application and specifies the base package for component scanning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-nine-h2-db-spring-boot-example-springbootapplication.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-nine-h2-db-spring-boot-example-springbootapplication.png" alt="[Step Nine](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-nine): Spring Boot and H2 DB Example Application with Custom Component Scanning." width="800" height="29"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Ten: Configure and then run the Spring Boot application.
&lt;/h3&gt;

&lt;p&gt;The code in this snippet configures and then runs the Spring Boot application with the following configuration:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Initialize SpringApplicationBuilder&lt;/strong&gt;: Creates a builder for the Spring Boot application using H2SpringBootExampleApplication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Profiles and Web Application Type&lt;/strong&gt;: Configures the application to use the default profile and disables the web environment (this is not a web application so we don’t need this).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Parent Context&lt;/strong&gt;: Specifies the BeanConfiguration, ExampleRepository, ExampleService, and ExampleCommandLineRunner classes as components in the parent context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the Application&lt;/strong&gt;: Execute the application with the provided arguments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close the Context&lt;/strong&gt;: Closes the application context — this step ensures that the stop lifecycle method in the service (see step six) is called before the Spring Boot example application has exited resulting in the names table in the H2 DB being dropped.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, the script logs a completion message and then exits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-ten-h2-db-spring-boot-example-run-application.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2024%2F06%2Fstep-ten-h2-db-spring-boot-example-run-application.png" alt="[Step Ten](https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#step-ten): Set up and run the Example Spring Boot application with specified components, profiles, and configurations, then close the application context and log completion." width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next section includes the complete Spring Boot with H2 Database example script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spring Boot With The H2 Database Engine Complete Example
&lt;/h2&gt;

&lt;p&gt;Please refer to the &lt;a href="https://thospfuller.com/2024/06/14/h2-database-with-spring-boot/#complete-example" rel="noopener noreferrer"&gt;original article&lt;/a&gt; or the &lt;a href="https://gist.github.com/thospfuller/c0ac73cf450592ac262c2b098e65b4f6" rel="noopener noreferrer"&gt;GitHub gist&lt;/a&gt; for the complete example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope that this instructional has provided adequate guidance as well as a useful &lt;a href="https://thospfuller.com/categories/software-engineering/" rel="noopener noreferrer"&gt;software engineering solution&lt;/a&gt; regarding how to use the &lt;a href="https://h2database.com/" rel="noopener noreferrer"&gt;H2 Database&lt;/a&gt; with &lt;a href="https://spring.io/projects/spring-boot" rel="noopener noreferrer"&gt;Spring Boot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have another guide that details &lt;a href="https://thospfuller.com/2023/12/28/database-change-notifications-in-the-h2-database/" rel="noopener noreferrer"&gt;how to receive database event notifications from the H2 Database using triggers&lt;/a&gt; which may be of interest as well.&lt;/p&gt;

</description>
      <category>java</category>
      <category>groovy</category>
      <category>database</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>How To Write Awesome Article Titles For SEO 💎</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Mon, 16 Oct 2023 16:11:53 +0000</pubDate>
      <link>https://dev.to/thospfuller/how-to-write-awesome-article-titles-for-seo-3d5j</link>
      <guid>https://dev.to/thospfuller/how-to-write-awesome-article-titles-for-seo-3d5j</guid>
      <description>&lt;p&gt;If you’re wondering how to write awesome article titles for SEO then this tutorial should help to address this question.&lt;/p&gt;

&lt;p&gt;I use the same strategy for other articles that appear on this website and for posts I’ve published elsewhere.&lt;/p&gt;

&lt;p&gt;My goal is to not just write something that a human would appreciate but also to conduct some basic research in an effort to find a long-tail keyword (LTK) that will also appeal to search engines, the Google Search Engine being my primary concern, and to include that target keyword combination in the title.&lt;/p&gt;

&lt;p&gt;I use various ChatGPT prompts when engineering the post title and we’ll cover this too.&lt;/p&gt;

&lt;p&gt;This article started as &lt;a href="https://www.linkedin.com/posts/thomasfuller_website-seo-semrush-activity-6996145583451234307-jS2o"&gt;an update on LinkedIn&lt;/a&gt; where I put together a few ideas regarding how we can engineer the best SEO titles for the purposes of appealing to both the human reader as well as to search engines.&lt;/p&gt;

&lt;p&gt;There are seven steps we need to follow and the first involves doing a bit of research about article titles.&lt;/p&gt;

&lt;p&gt;There's extra information included in &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/"&gt;the original article&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepOne"&gt;Step One: Review Several Articles On The Best SEO Headlines&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Below I’ve included several articles that can help develop a better understanding of strategies and tactics you can use to develop an awesome blog post title.&lt;/p&gt;

&lt;p&gt;Quoting from the article entitled &lt;a href="https://blog.hubspot.com/marketing/types-of-blog-headlines"&gt;13 Types of Blog Headlines That’ll Get You More Traffic [+ Examples]&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You might not realize it, but your headline could be the reason you’re losing traffic. In fact, on average, only 20% of those who read your headline &lt;a href="http://www.copyblogger.com/magnetic-headlines/"&gt;will click through to read your article&lt;/a&gt;. That means good headlines lose 80% of your audience.&lt;/p&gt;

&lt;p&gt;Great headlines, though, can make a dramatic impact in the opposite direction. You can increase the traffic to your articles by as much as 500%, based solely on the headline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Below I’ve included several of the best SEO headlines by type:&lt;/p&gt;

&lt;h3&gt;
  
  
  How-to titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;How to Make the Perfect Cup of Coffee&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;How-to titles are actually quite important and can be helpful as &lt;a href="https://thospfuller.com/2021/04/19/question-based-keywords/#which-question-optimized-queries-perform-well"&gt;backlink magnets&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  List-based titles (list posts / listicles)
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;10 Reasons Why Yoga is Good for Your Health&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;List-based articles, also known as list posts or listicles, can perform very well because they’re generally easy to scan and read.&lt;/p&gt;

&lt;p&gt;List posts are also easy to post on social media platforms so when reusing content, the title in this case can have an importance that extends well beyond the article.&lt;/p&gt;

&lt;h3&gt;
  
  
  Question-based titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;What are the Benefits of Meditation?&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;According to the article entitled &lt;a href="https://financesonline.com/google-search-statistics/"&gt;Google Search Statistics&lt;/a&gt; (dated 2020):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;…14.6% of all Google searches come in the form of a question.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;so when developing a question-based title, it will likely benefit the writer to use the exact question people are searching for as their article title.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opinion-based titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;Why I Think Veganism is the Future of Food&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefit-driven titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;The Benefits of Going for a Morning Run&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Power words
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;Discover the Secrets to a Better Life&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Time-sensitive titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;Why Now is the Time to Start Investing in Real Estate&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Controversial titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;Why I Disagree with Popular Parenting Techniques&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal experience titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;My Journey to Becoming a Better Writer&lt;/em&gt;"&lt;/p&gt;

&lt;h3&gt;
  
  
  Numbers-based titles
&lt;/h3&gt;

&lt;p&gt;"&lt;em&gt;5 Simple Ways to Improve Your Productivity.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;See also the &lt;a href="https://backlinko.com/hub/seo/linkbait"&gt;Backlinko link bait article&lt;/a&gt; and any other articles on this specific subject. I’ve included some tweets to threads about this subject &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/"&gt;in the original article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The article entitled &lt;a href="https://www.searchenginejournal.com/title-capitalization-in-the-english-language/"&gt;How To Write Great SEO Titles&lt;/a&gt; suggests that we should prefer to use title or sentence case and that, while this doesn’t matter to SEO, per se, how we choose to capitalize can impact the reader (See the sections entitled "Capitalize Properly" and "Does Capitalization Affect SEO Rankings?").&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepTwo"&gt;Step Two: Determine The Search Intent&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Search intent, or user intent / audience intent, refers to the reason behind a user’s search query.&lt;/p&gt;

&lt;p&gt;When it comes to Search Engine Optimization (SEO), understanding search intent is important because it helps to optimize content in order to meet the user’s needs and provide relevant search results. &lt;/p&gt;

&lt;p&gt;There are four main types of search intent: informational, navigational, transactional, and commercial investigation. &lt;/p&gt;

&lt;p&gt;We’ll briefly cover each of these below — for more information see the Yoast article entitled “&lt;a href="https://yoast.com/search-intent/"&gt;What is search intent and why is it important for SEO?&lt;/a&gt;“.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Informational Search Intent&lt;/strong&gt;: People looking for specific information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigational Search Intent&lt;/strong&gt;: People looking to visit a specific website.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transactional Search Intent&lt;/strong&gt;: People looking to buy something now.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commercial Search Intent&lt;/strong&gt;: People looking to buy something in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When it comes to optimizing content, this includes the title too.&lt;/p&gt;

&lt;p&gt;In step three we’ll perform some basic target keyword research and knowing what the search intent is should help to narrow down an appropriate long-tail keyword with a search intent that matches what the user is looking for.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepThree"&gt;Step Three: Locate a Long-Tail Keyword for SEO Purposes&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;For step three I’ll use the &lt;a href="https://www.semrush.com/analytics/keywordmagic/"&gt;SEMrush Keyword Magic Tool&lt;/a&gt; to find a long-tail keyword (LTK) combination.&lt;/p&gt;

&lt;p&gt;Ideally, the long tail keyword should be &lt;a href="https://www.searchenginejournal.com/keyword-competition/313815/"&gt;both high volume and low competition&lt;/a&gt; — if we end up ranking for this target keyword combination we may end up getting a decent amount of traffic to the post — especially if we end up in the top three positions in the search engine results page (SERP).&lt;/p&gt;

&lt;p&gt;If you have a long-tail keyword already in mind, then make sure this is included in the headline.&lt;/p&gt;

&lt;p&gt;Designing a compelling headline which incorporates a long-tail keyword may require some creativity especially if the target keyword requires many characters.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Common Benefit to Long-Tail Keywords?
&lt;/h3&gt;

&lt;p&gt;Targeting long-tail keywords is an important search engine optimization (SEO) strategy and involves finding target keyword combinations that are focused, less competitive, and which should help to drive traffic to a website.&lt;/p&gt;

&lt;p&gt;The following quote is from the Search Engine Land article entitled &lt;a href="https://searchengineland.com/back-to-basics-what-does-long-tail-keyword-really-mean-311910"&gt;Back to basics: What does 'long-tail' keyword really mean?&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a particular niche has a total search volume of 100,000 and is accompanied by 1,000 keyword opportunities, then by this logic, an estimated 20 to 30 percent of them will be short-tail keywords, while long-tail keywords will account for the remaining 70 to 80 percent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and the quote below is from the AIOSEO article entitled &lt;a href="https://aioseo.com/how-to-find-long-tail-keywords-and-increase-organic-traffic/"&gt;How to Find Long Tail Keywords and Increase Organic Traffic&lt;/a&gt; drives this point home:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...long tail keywords make up for 70% of search traffic. So if you want to get more organic traffic and improve your SEO rankings, you should definitely use long tail keywords in your content.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Why you should also target zero search volume keywords
&lt;/h3&gt;

&lt;p&gt;It’s important to keep in mind that tools like the SEMrush Keyword Magic Tool are often &lt;em&gt;estimating search volume&lt;/em&gt; and, from time to time, we may find a target keyword that looks attractive and yet have &lt;em&gt;zero search volume&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Below I've quoted &lt;a href="https://twitter.com/NicheCampus/status/1528042692218871809"&gt;this tweet&lt;/a&gt; by &lt;a href="https://twitter.com/NicheCampus/"&gt;@NicheCampus&lt;/a&gt; about zero-volume keywords:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Some of my BEST and BIGGEST volume keywords came from digging around for “zero competitive keywords” which had “zero search volume” (from tools etc)&lt;/p&gt;

&lt;p&gt;Not only are these free and easy to win Google’s #1 spot, they often have much more traffic than people expect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I can speak with experience regarding this suggestion as I’ve used zero search volume keywords for various posts and was pleasantly surprised when the actual search volume was higher than I anticipated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepFour"&gt;Step Four: Use ChatGPT To Research and Write the Title&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;In step four, we use a ChatGPT prompt to help us write the title.&lt;/p&gt;

&lt;p&gt;ChatGPT can be incredibly useful for research purposes and that includes developing a title for a blog post.&lt;/p&gt;

&lt;p&gt;In this example, we ask ChatGPT to create a blog post title that is no longer than 55 characters and also uses the long-tail keyword we discovered in the previous step. &lt;/p&gt;

&lt;p&gt;We can ask ChatGPT to give us several variations and in a few seconds we can review many choices and either use one, take ideas from the results, or use one and improve it such that it works with our post.&lt;/p&gt;

&lt;p&gt;Using ChatGPT in this manner can be a significant time-saver and is a strategy that I’m using with some frequency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb17vrfi680wsqm8l6bc5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb17vrfi680wsqm8l6bc5.png" alt="ChatGPT Post Title Research: Discover The Ultimate List Of Top 100 Best Headlines." width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaz224o6bkz57na3u9vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsaz224o6bkz57na3u9vo.png" alt="Write ten blog post title variations that include the quote " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that if we can generate one blog post title, we can just as easily generate ten, 50, or 100.&lt;/p&gt;

&lt;p&gt;The result can be useful in that we can use the blog post title exactly as generated if it’s appropriate, or we can take something which is close to what we need and improve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepFive"&gt;Step Five: Use The MonsterInsights Headline Analyzer Tool To Develop An Award-Winning Headline&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Step five requires that we use a tool such as the MonsterInsights Headline Analyzer (MIHA) to engineer a solid headline that incorporates the long-tail keyword combination found previously.&lt;/p&gt;

&lt;p&gt;ChatGPT may also give us a great title that requires no adjustment however if the score is not satisfactory we may want to rewrite the title in an effort to improve the score.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is The MonsterInsights Headline Analyzer?
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://www.monsterinsights.com/headline-analyzer/"&gt;MonsterInsights Headline Analyzer&lt;/a&gt; tool is a web application designed to assist users craft compelling and engaging headlines for their content.&lt;/p&gt;

&lt;p&gt;By analyzing the quality and effectiveness of headlines, the &lt;a href="https://www.monsterinsights.com/headline-analyzer/"&gt;MonsterInsights Headline Analyzer&lt;/a&gt; provides insights that can improve the overall impact of articles, blog posts, or marketing materials.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.monsterinsights.com/headline-analyzer/"&gt;MonsterInsights Headline Analyzer&lt;/a&gt; tool evaluates factors such as word choice, length, emotional appeal, and headline type to gauge the headline’s potential effectiveness.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.monsterinsights.com/headline-analyzer/"&gt;MonsterInsights Headline Analyzer&lt;/a&gt; users can write SEO headlines that are both optimized for search performance and captivate readers, increase click-through rates, and ultimately &lt;em&gt;enhance their content visibility&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxrho15z9y6ki50q4wew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxrho15z9y6ki50q4wew.png" alt="" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The MonsterInsights Headline Analyzer suggests that you should strive for a score of 70% and above — we can set this bar higher and aim for 75% as the minimum score.&lt;/p&gt;

&lt;p&gt;It may not be easy or even possible to achieve all of this given the parameters I’ve outlined and we may need to sacrifice something to make it work — in this case, I’m thinking the first to go will be the MonsterInsights Headline Analyzer score goal of 75% or better.&lt;/p&gt;

&lt;p&gt;In this SEO headline example, we have text which is 46 characters long and the Monster Insights Headline Analyzer score is 90%, which is very good.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is The Best Length Of A Title In SEO?
&lt;/h3&gt;

&lt;p&gt;We should endeavor to keep the length of the headline to no more than 60 characters however note that a character count of 55 appears to be the ideal length according to the article entitled &lt;a href="https://buffer.com/library/the-ideal-length-of-everything-online-according-to-science/"&gt;The Ideal Length of Everything Online, Backed by Research&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Do we benefit from placing the long-tail keyword at the beginning of the blog post title?&lt;/p&gt;

&lt;p&gt;ChatGPT suggests that the answer to this question is "no"; other supporting evidence is unavailable at the moment, and even if it did matter, it would be only one of many ranking factors and likely a negligible one at that.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepSix"&gt;Step Six: Add a Relevant Emoji To The Title&lt;/a&gt; ⛳️
&lt;/h2&gt;

&lt;p&gt;In this step we can, if we choose to, and assuming we have enough space to do so, add an emoji to the title.&lt;/p&gt;

&lt;p&gt;We need to be careful with this one and just because we can add an emoji to the title it doesn’t mean we should.&lt;/p&gt;

&lt;p&gt;Also, note that where we place an emoji may be important too — we’ll get to this in a moment.&lt;/p&gt;

&lt;p&gt;This exact subject has been studied already and below is a quote from the findings in the SEMrush article entitled "&lt;a href="https://www.semrush.com/blog/seo-split-testing-case-study-t-adding-an-emoji-to-the-title-on-recipe-pages-/"&gt;SEO Split-Testing Case Study: Should You Add an Emoji to the Title on Recipe Pages?&lt;/a&gt;" (August 2021) and to be clear, the variant group, in this case, is the title that contains the emoji:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The lines start to diverge right away in the first week. This means that the traffic to the variant group is performing better than predicted and shows that the test is a success. Ultimately, based on organic sessions, we see an increase in organic traffic of no less than 11.3%.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Where we place the emoji may be important as well.&lt;/p&gt;

&lt;p&gt;In posts and pages on this site where emojis are included in the title these usually appear at the end of the text.&lt;/p&gt;

&lt;p&gt;Google can rewrite titles and according to the SearchPilot article entitled “Can emojis in title tags be beneficial for SEO?” (April 2022):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Google was choosing not to include the emoji, and everything before it, leaving us with a shorter title than before the test, while also removing the primary keyword for the page from what was displayed in search results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;— and this is not good, of course.&lt;/p&gt;

&lt;p&gt;This site has several pages which utilize emojis in the title however they appear at the end of the text and in several cases Google has decided to remove the emoji however the remainder of the title appears as it’s been written and without any negative consequences.&lt;/p&gt;

&lt;p&gt;So my advice, given what’s been experienced above, is simply to make sure that an article title that contains an emoji is appearing correctly in search results once Google has indexed the page — if it does not appear correctly then you may need to move or remove the emoji and resubmit the URL for indexing in the &lt;a href="https://search.google.com/search-console/about"&gt;Google Search Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I personally do not like this approach as we end up being forced to wait for the update to happen and, in my experience, that could take &lt;em&gt;several weeks&lt;/em&gt; for the change to appear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5h3eg1uymw28jwpdgk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5h3eg1uymw28jwpdgk6.png" alt="Image description" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When developing the best SEO headlines, &lt;a href="https://unicode.org/emoji/charts/full-emoji-list.html"&gt;the emojis we have available are specified as a unicode standard&lt;/a&gt; and tools such as the All In One SEO Pack for WordPress include these emojis as one of the many product features.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/#stepSeven"&gt;Step Seven: Check that the title doesn’t already exist&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;If the exact title developed is already in use by another website, we should consider rewording the title as we don’t want to fall into direct competition with a page which has been ranked using verbatim the text we’ve developed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use ChatGPT To Generate Variations Of Your Best SEO Headlines With Emojis
&lt;/h3&gt;

&lt;p&gt;If we’re not sure which emojis are appropriate for the title, we can use ChatGPT to quickly generate a few variations and then we can pick one.&lt;/p&gt;

&lt;p&gt;In this example I use the ChatGPT prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Provide me with ten example titles with appropriate emojis added to the end for the WordPress post entitled “Does your blog post have one of the Top 100 Best Headlines” and do not change the post title.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and we can examine the results in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0s5590si1kh9jyswo9cr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0s5590si1kh9jyswo9cr.png" alt="" title="" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that there’s likely a more concise way to word this ChatGPT prompt however in this case I needed to demonstrate how this works and intend to revisit this in time.&lt;/p&gt;

&lt;p&gt;We could also prompt ChatGPT to create title variations (see step #4) with the emoji included and possibly kill two birds with one stone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Emojis In The Title Do Not Help Or Hurt SEO
&lt;/h3&gt;

&lt;p&gt;According to the Search Engine Journal article entitled "&lt;a href="https://www.searchenginejournal.com/google-says-emojis-wont-hurt-or-help-seo/436079/"&gt;Google Says Emojis Won’t Hurt Or Help SEO&lt;/a&gt;" the presence of an emoji won’t hurt or help SEO.&lt;/p&gt;

&lt;p&gt;But, as we’ve already discussed, there can be a positive return regardless and the presence of one or more emojis in the title can have the potential to improve traffic from search engines as well as social media platforms because people may still see the graphic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Article Conclusion
&lt;/h2&gt;

&lt;p&gt;This article was initially published &lt;a href="https://thospfuller.com/2022/11/10/title-tags-seo/"&gt;on my blog&lt;/a&gt; on the 10th of November 2022 and has since then undergone many revisions including new content and adjustments for clarity as well as for SEO.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>writing</category>
      <category>contentwriting</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Tutorial: Learn How To Mount A Local Directory Into A Pod In minikube</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Thu, 10 Dec 2020 03:36:55 +0000</pubDate>
      <link>https://dev.to/thospfuller/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2020-3j48</link>
      <guid>https://dev.to/thospfuller/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2020-3j48</guid>
      <description>&lt;p&gt;&lt;strong&gt;The use case for this guide is as follows: A software developer needs to mount a local directory into a pod in minikube since pod storage is ephemeral and will be deleted when the pod is deleted.&lt;br&gt;
In the following article, we're using Minikube (v1.14.2) with Kubectl (1.19) running on Ubuntu 20.04.1 LTS.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we want the storage to survive a pod deletion or to be shared between pods, then we can mount a directory from the local file system — this could be a requirement, for example, when you have a database running in the pod but the storage is located on the local filesystem.&lt;/p&gt;

&lt;p&gt;In this article, we’ll cover several examples that demonstrate how to mount a local directory in a pod running in minikube.&lt;/p&gt;

&lt;p&gt;We rely on minikube (v1.15.1) with kubectl (1.19.4) on Ubuntu (20.04.1 LTS) as well as on Mac OSX (10.13.6 High Sierra).&lt;/p&gt;

&lt;p&gt;The k command, which appears below, is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;alias k='kubectl'&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;In the next section we’ll take a look at several use cases regarding why a software developer would want to mount a local directory in a pod in Kubernetes and/or minikube and following that we’ll take a look at a few solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Cases for mounting a local directory in a pod in Kubernetes
&lt;/h2&gt;

&lt;p&gt;When setting up a local Kubernetes cluster using minikube, you can utilize hostPath volumes to mount specific files or directories from the host machine into your pods, and define volumeMounts with mountPath in your pod specification to efficiently manage file and directory access within your containers.&lt;/p&gt;

&lt;p&gt;For detailed management and troubleshooting of these volumes, use ‘minikube ssh‘ to access the cluster’s command line.&lt;/p&gt;

&lt;p&gt;Mounting a local directory into a pod in Kubernetes can be useful for several reasons and I’ve included five use cases below.&lt;/p&gt;

&lt;p&gt;At a high level, these benefits include data sharing and accelerating the development and testing of software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration Injection
&lt;/h3&gt;

&lt;p&gt;You can mount a local directory containing configuration files or environment variables into a pod.&lt;/p&gt;

&lt;p&gt;This allows you to dynamically adjust the behavior of your application without modifying the container image.&lt;/p&gt;

&lt;p&gt;As you update the configuration on the host machine, the changes are immediately reflected in the pod thereby facilitating easy configuration management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Sharing and Backup
&lt;/h3&gt;

&lt;p&gt;Mounting a shared local directory allows you to share data between containers within the same pod.&lt;/p&gt;

&lt;p&gt;Mounting a shared local directory enables seamless communication and data exchange, such as sharing log files or database backups between containers.&lt;/p&gt;

&lt;p&gt;Additionally, you can use local directories as temporary storage for data backups and then mount the local directories into pods for further processing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Persistent Data Storage
&lt;/h3&gt;

&lt;p&gt;You can mount a local directory into a pod when one or more applications require persistent storage.&lt;/p&gt;

&lt;p&gt;This approach can be particularly useful during development and testing, and allows you to use your local machine’s file system as a data storage solution.&lt;/p&gt;

&lt;p&gt;Local storage is not recommended for production scenarios due to its limitations and lack of scalability however it is perfectly suitable for development and testing purposes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debugging and Troubleshooting
&lt;/h3&gt;

&lt;p&gt;When debugging an application within a pod, mounting a local directory with debugging tools, scripts, or diagnostic utilities can help you quickly investigate issues.&lt;/p&gt;

&lt;p&gt;Mounting a local directory allows the developer access to debugging tools and logs directly from the local machine and streamlines the troubleshooting process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development and Testing
&lt;/h3&gt;

&lt;p&gt;Mounting a local directory can accelerate the iteration process when it comes to developing and testing software.&lt;/p&gt;

&lt;p&gt;Instead of building and pushing container images for every code change, you can mount the directory containing the source code into the pod and enable real-time testing and observation of the changes as development progresses.&lt;/p&gt;

&lt;p&gt;Keep in mind that while mounting a local directory can be helpful for specific use cases, it’s essential to consider the security and portability implications as it pertains to production software.&lt;/p&gt;

&lt;p&gt;Using &lt;a href="https://kubernetes.io/docs/concepts/configuration/configmap/" rel="noopener noreferrer"&gt;ConfigMaps&lt;/a&gt;, &lt;a href="https://kubernetes.io/docs/concepts/configuration/secret/" rel="noopener noreferrer"&gt;Configuration Secrets&lt;/a&gt;, or network-attached storage solutions such as &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" rel="noopener noreferrer"&gt;Persistent Volumes&lt;/a&gt; (see also &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-persistent-volume-storage/" rel="noopener noreferrer"&gt;Configure a Pod to Use a PersistentVolume for Storage&lt;/a&gt;) and &lt;a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/" rel="noopener noreferrer"&gt;Persistent Volume Claims&lt;/a&gt; (PVCs)) might be more appropriate for production environments, where data needs to be managed securely and scaled effectively.&lt;/p&gt;

&lt;p&gt;In the next section we’ll take a look at what the minikube mount command does and then we’ll take a look at three solutions that we can use to mount a host directory in a pod in minikube.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is minikube mount?
&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;&lt;a href="https://minikube.sigs.k8s.io/docs/commands/mount/" rel="noopener noreferrer"&gt;minikube mount&lt;/a&gt;&lt;/em&gt; command allows the developer to mount a local directory on the host machine into a running Minikube cluster, thereby making it accessible to containers running in the cluster.&lt;/p&gt;

&lt;p&gt;In the following examples we do not use the minikube mount command directly — instead we apply a configuration yaml file which has the mount specification details included.&lt;/p&gt;

&lt;p&gt;See also the page on &lt;a href="https://minikube.sigs.k8s.io/docs/handbook/mount/" rel="noopener noreferrer"&gt;mounting filesystems regarding how to mount a host directory into the virtual machine (VM) on k8s.io&lt;/a&gt; for more details regarding how minikube mount is used.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#solution-one" rel="noopener noreferrer"&gt;Solution #1&lt;/a&gt;: Mount a subdirectory within user's home into a pod in minikube)
&lt;/h2&gt;

&lt;p&gt;In the first solution, which is also the easiest solution in this article, we mount a subdirectory within the user’s home directory into a pod in minikube.&lt;/p&gt;

&lt;p&gt;This solution was inspired by &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#tutorial-references" rel="noopener noreferrer"&gt;#1&lt;/a&gt; (Akshay Sood, specifically) and facilitates the same result as Solution #2 however without the requirement to pass the –mount and –mount-string args.&lt;/p&gt;

&lt;p&gt;The pod configuration file looks very close to the one used in Solution #2 as well — direct your attention to lines 14 (volumeMounts) and 17 (volumes).&lt;/p&gt;

&lt;p&gt;This works because minikube mounts the /Users directory &lt;em&gt;by default&lt;/em&gt; on Mac OSX, which is what we’re using for this specific solution.&lt;/p&gt;

&lt;p&gt;Refer to the homedir package documentation as well as the for more information regarding the directory paths per specific supported operating systems (Apple OSX, Linux, and Microsoft Windows) [12 &amp;amp; 13].&lt;/p&gt;

&lt;p&gt;I also have a simple script, which is written in Go, in GitHub, which displays the value of the user’s home directory.&lt;/p&gt;

&lt;p&gt;In the image below we can see which directory has been mounted in minikube by invoking the df command with the h option, for displaying human-readable output, and the l option, which reveals information about locally-mounted filesystems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Nr7we81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2020/12/kubernetes-k8s-minikube-ssh-with-users-directory-mounted.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Nr7we81--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2020/12/kubernetes-k8s-minikube-ssh-with-users-directory-mounted.png" alt="The " width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step One: Modify the hostPath in the pod configuration below to point to the user home directory.
&lt;/h3&gt;

&lt;p&gt;Here’s the pod configuration:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In &lt;a href="https://gist.github.com/thospfuller/f8a8d747906365becc18b811888bdc30#file-nginx-hp-minimounted-yaml" rel="noopener noreferrer"&gt;this example&lt;/a&gt;, we start minikube absent any of the mount-related args.&lt;/p&gt;

&lt;p&gt;When the pod is created the &lt;em&gt;/etc/minimounted/&lt;/em&gt; directory will exist and it will be correctly mapped to the local directory.&lt;/p&gt;

&lt;p&gt;We can see the output of this example in the following image (todo: double-check this image as it may not be the correct one to use here):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TD-WmbN_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2020/12/minikube-etc-minimounted-hello-txt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TD-WmbN_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2020/12/minikube-etc-minimounted-hello-txt.png" alt="Example bash shell output for a container running in minikube with the /etc/minimounted/ directory which now contains the hello.txt file." width="800" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step Two: Start minikube
&lt;/h2&gt;

&lt;p&gt;The second step requires us to start minikube using the hyperv-virtual-switch option as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;minikube start --hyperv-virtual-switch "My Virtual Switch" --v=4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this example the –hyperv-virtual-switch parameter is described on k8s.io as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Name of the virtual switch the minikube VM should use. Defaults to first found&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and we’re using “My Virtual Switch” as the name. The –v option sets the &lt;a href="https://dev.tourl"&gt;log level verbosity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--epEPpLFp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-start-cluster-with-hyperkit-driver-example.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--epEPpLFp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-start-cluster-with-hyperkit-driver-example.png" alt="minikube start cluster using the hyperkit driver." width="800" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Three: Apply the configuration.
&lt;/h3&gt;

&lt;p&gt;In the script below we apply the configuration file.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl apply -f ./nginx-hp-minimounted.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We can see the output when the kubectl apply command is executed below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--16Sy03vE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-mount-local-directory-to-a-pod-kubectl-apply-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--16Sy03vE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-mount-local-directory-to-a-pod-kubectl-apply-output.png" alt="Output when mounting a local directory to a pod." width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step Four (optional): Test that the path is available in the pod in minikube
&lt;/h3&gt;

&lt;p&gt;We can test that the path is available by getting command line access to the pod in the myns namespace and checking that the path exists as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl exec nginx-minimounted -n myns -it -- /bin/sh&lt;br&gt;
ls -la /etc/minimounted&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below I’ve included the complete script for running and testing this solution.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;minikube start --hyperv-virtual-switch "My Virtual Switch" --v=4&lt;br&gt;
kubectl apply -f ./nginx-hp-minimounted.yaml&lt;br&gt;
kubectl exec nginx-minimounted -n myns -it -- /bin/sh&lt;br&gt;
ls -la /etc/minimounted&lt;br&gt;
exit&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If everything worked as we expect it to we should see something that looks like what appears below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--16Sy03vE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-mount-local-directory-to-a-pod-kubectl-apply-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--16Sy03vE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thospfuller.com/wp-content/uploads/2023/10/minikube-mount-local-directory-to-a-pod-kubectl-apply-output.png" alt="Example output for mounting a directory in a pod in Minikube within user's home directory" width="800" height="162"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that’s it for this example.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#solution-two" rel="noopener noreferrer"&gt;Solution #2&lt;/a&gt;: Mount a directory outside of user home into a pod in minikube
&lt;/h2&gt;

&lt;p&gt;Refer to &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#solution-two" rel="noopener noreferrer"&gt;solution #2 in the original article&lt;/a&gt; for the complete example.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#solution-three" rel="noopener noreferrer"&gt;Solution #3&lt;/a&gt;: Mount a directory other than user home, without restart, into a pod in minikube
&lt;/h2&gt;

&lt;p&gt;Refer to &lt;a href="https://thospfuller.com/2020/12/09/learn-how-to-mount-a-local-drive-in-a-pod-in-minikube-2021/#solution-three" rel="noopener noreferrer"&gt;solution #3 in the original article&lt;/a&gt; for the complete example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tutorial Conclusion
&lt;/h2&gt;

&lt;p&gt;If you liked this &lt;a href="https://thospfuller.com/categories/tutorials/" rel="noopener noreferrer"&gt;instructional&lt;/a&gt; then you may also like the following articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thospfuller.com/2020/11/29/easy-kubernetes-metrics-server-install-in-minikube-in-five-steps/" rel="noopener noreferrer"&gt;Easily Install the Metrics Server on Minikube in 5 Steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://thospfuller.com/2020/11/09/answers_to_five_kubernetes_ckad_practice_questions_2020/" rel="noopener noreferrer"&gt;Answers to Five Kubernetes CKAD Practice Questions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See the &lt;a href="https://thospfuller.com/categories/kubernetes/" rel="noopener noreferrer"&gt;Kubernetes category&lt;/a&gt; and the &lt;a href="https://thospfuller.com/categories/containerization/" rel="noopener noreferrer"&gt;containerization category&lt;/a&gt; for other articles that may be of interest.&lt;/p&gt;

&lt;p&gt;Questions and comments are welcomed.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>kubernetes</category>
      <category>docker</category>
      <category>containerization</category>
    </item>
    <item>
      <title>Answers to Five Kubernetes CKAD Practice Questions (2021)</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Tue, 17 Nov 2020 21:13:45 +0000</pubDate>
      <link>https://dev.to/coherentlogic/answers-to-five-kubernetes-ckad-practice-questions-2020-3h0p</link>
      <guid>https://dev.to/coherentlogic/answers-to-five-kubernetes-ckad-practice-questions-2020-3h0p</guid>
      <description>&lt;p&gt;While doing some work with &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; (K8s) and studying for the CKAD exam, I came across a page on Matthew Palmer's website entitled "&lt;a href="https://matthewpalmer.net/kubernetes-app-developer/articles/ckad-practice-exam.html" rel="noopener noreferrer"&gt;Practice Exam for Certified Kubernetes Application Developer (CKAD) Certification&lt;/a&gt;" and which contains five practice questions, which I'll go over here. If you see a problem with anything I've done below, including inefficient solutions, please let me know in the comments.&lt;/p&gt;

&lt;p&gt;We will focus on not just showing a possible solution to each problem but also &lt;em&gt;verifying our work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Since we're limited to the &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;kubernetes.io&lt;/a&gt; website when taking this test, this site is referenced where appropriate -- in particular the &lt;a href="https://kubernetes.io/docs/reference/kubectl/cheatsheet/" rel="noopener noreferrer"&gt;kubectl cheat sheet page&lt;/a&gt; is not a bad place to start and we can search for what we need here as well.&lt;/p&gt;

&lt;p&gt;Lastly, with each of these questions, we need to pay particular attention to the &lt;em&gt;namespace&lt;/em&gt; requirement.&lt;/p&gt;

&lt;p&gt;This article relies on &lt;a href="https://minikube.sigs.k8s.io/" rel="noopener noreferrer"&gt;minikube&lt;/a&gt; running on &lt;a href="https://ubuntu.com/" rel="noopener noreferrer"&gt;Ubuntu&lt;/a&gt; along with the &lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh My Zsh shell&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;k command&lt;/em&gt; is defined as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias k='kubectl'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's take a look at the first question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Question #1
&lt;/h2&gt;

&lt;p&gt;The first question from [1] is as follows:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;Create a namespace called &lt;strong&gt;ggckad-s0&lt;/strong&gt; in your cluster.&lt;br&gt;&lt;br&gt;
Run the following pods in this namespace.&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;1. A pod called pod-a with a single container running the kubegoldenguide/simple-http-server image&lt;/em&gt;  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;2. A pod called pod-b that has one container running the kubegoldenguide/alpine-spin:1.0.0 image, and one container running nginx:1.7.9&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Write down the output of kubectl get pods for the ggckad-s0 namespace.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;We can hack together a pod by hand or we can autogenerate it, which should be the preferred option as we don't want to waste time with this if we can avoid it. The following commands can be used to autogenerate each yaml file: one for the kubegoldenguide/simple-http-server container, one for the kubegoldenguide/alpine-spin:1.0.0 container, and one for the nginx:1.7.9 container.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl run nginx --image=kubegoldenguide/simple-http-server --dry-run=client -o yaml &amp;gt; simple-http-server.yaml

kubectl run nginx --image=kubegoldenguide/alpine-spin:1.0.0 --dry-run=client -o yaml &amp;gt; alpine-spin.yaml

kubectl run nginx --image=nginx:1.7.9 --dry-run=client -o yaml &amp;gt; nginx.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We can use these files to create the pod-a and pod-b yaml files, which are required for this question.&lt;/p&gt;

&lt;p&gt;The configuration file for pod-a appears as follows:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;And the configuration file for pod-b appears below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We need to first create the namespace as per the instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k create namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, we can apply this configuration:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f pod-[a or b].yaml --namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The final instruction for this question indicates that we need to "[w]rite down the output of kubectl get pods for the ggckad-s0 namespace." -- this is accomplished as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k get pods --namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;which yields the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.3_k_get_pods_namespace_ggckad-s0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.3_k_get_pods_namespace_ggckad-s0.png" alt="The result from running 'k get pods --namespace ggckad-s0'." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Verifying Our Solution
&lt;/h3&gt;

&lt;p&gt;Below we have the entire script that we use in this example. We check the logs for all containers in order to see that they're running correctly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k create namespace ggckad-s0
k apply -f pod-a.yaml --namespace ggckad-s0
k logs pod-a --namespace ggckad-s0
k apply -f pod-b.yaml --namespace ggckad-s0
k logs pod-b alpine-spin-container --namespace ggckad-s0
k logs pod-b nginx-container --namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running this script should yield the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_complete_output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_complete_output.png" alt="In this example k is defined as " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can use the &lt;em&gt;get events&lt;/em&gt; command to see the events that were collected.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k get events --namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running this command should yield the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_get_events_namespace_ggckad-s0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_get_events_namespace_ggckad-s0.png" alt="The output for events collected in namespace ggckad-s0 when setting up pod-a and pod-b." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that the &lt;em&gt;nginx-container&lt;/em&gt; has started however there are no messages in the log that indicate that it's actually running so we'll check this by mapping port 19999 on the local machine to port 80 in the &lt;em&gt;pod-b&lt;/em&gt; pod, which should point to the &lt;em&gt;nginx-container&lt;/em&gt; which has the Nginx web server running on port 80.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl port-forward pods/pod-b 19999:80 --namespace ggckad-s0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;When we execute the line above, the output should look like what we have below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_port_forward_from_19999_to_80_for_pod-b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_port_forward_from_19999_to_80_for_pod-b.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we can now test that Nginx is running by browsing &lt;a href="http://localhost:19999/" rel="noopener noreferrer"&gt;localhost:19999&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_exec-nginx_is_running_in_chrome.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_1.1_exec-nginx_is_running_in_chrome.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it for this question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Question #2
&lt;/h2&gt;

&lt;p&gt;The second question from [1] is as follows:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;All operations in this question should be performed in the ggckad-s2 namespace.&lt;br&gt;&lt;br&gt;
Create a ConfigMap called app-config that contains the following two entries:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;'connection_string' set to 'localhost:4096'&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;'external_url' set to 'google.com'&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Run a pod called question-two-pod with a single container running the kubegoldenguide/alpine-spin:1.0.0 image, and expose these configuration settings as environment variables inside the container.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;We need to first create the namespace as per the instructions:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k create namespace ggckad-s2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We need a &lt;a href="https://kubernetes.io/docs/concepts/configuration/configmap/" rel="noopener noreferrer"&gt;ConfigMap&lt;/a&gt;, which can be created via the CLI as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create configmap app-config --from-literal connection_string=localhost:4096 --from-literal external_url=google.com --dry-run -oyaml --namespace ggckad-s2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and which is defined in the following gist:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Next, we can apply this configuration making sure to include the specified namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k apply -f ./app-config.yaml --namespace ggckad-s2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the configuration file for the &lt;em&gt;question-two-pod&lt;/em&gt; appears below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We need to apply the pod configuration file, and we do so via the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k apply -f ./question-two-pod.yaml --namespace ggckad-s2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, we need to verify our work.&lt;/p&gt;
&lt;h3&gt;
  
  
  Verifying Our Solution
&lt;/h3&gt;

&lt;p&gt;Verifying this solution is simple: In step one we'll get CLI access to the container and in step two we'll check the environment, if the environment variables have been set then we're finished.&lt;/p&gt;

&lt;p&gt;Step one appears as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k exec -it question-two-pod -c web --namespace ggckad-s2 -- /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and step two can be accomplished using the &lt;em&gt;env&lt;/em&gt; command and visually inspecting the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_2_answer_verification_with_arrows.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_2_answer_verification_with_arrows.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it for this question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Question #3
&lt;/h2&gt;

&lt;p&gt;The third question from [1] is as follows:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;All operations in this question should be performed in the ggckad-s2 namespace. Create a pod that has two containers. Both containers should run the kubegoldenguide/alpine-spin:1.0.0 image. The first container should run as user ID 1000, and the second container with user ID 2000. Both containers should use file system group ID 3000.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;We need to first create the namespace as per the instructions:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k create namespace ggckad-s2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the configuration file for the &lt;em&gt;question-three-pod&lt;/em&gt; appears below -- review the namespace declaration -- this allows us to apply the configuration file and not include the namespace via the command line (CLI); also, and more importantly, pay particular attention to the &lt;em&gt;fsGroup&lt;/em&gt; and &lt;em&gt;runAsUser&lt;/em&gt; key/value pairs:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We can apply this configuration as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k apply -f ./question-three-pod.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Finally, we need to verify our work.&lt;/p&gt;
&lt;h3&gt;
  
  
  Verifying Our Solution
&lt;/h3&gt;

&lt;p&gt;We need to get CLI access to our container and then verify that the settings are correct and the following command can be used to do exactly that:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k exec -it question-three-pod -c alpine-spin-[a or b] --namespace ggckad-s2 -- /bin/sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once we have access we can check that the &lt;em&gt;fsGroup&lt;/em&gt; and &lt;em&gt;runAsUser&lt;/em&gt; key/value pairs have been set correctly -- we'll get this information by using the &lt;a href="https://man7.org/linux/man-pages/man1/id.1.html" rel="noopener noreferrer"&gt;&lt;em&gt;id&lt;/em&gt; command&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_3_answer_verification-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_3_answer_verification-1.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it for this question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Question #4
&lt;/h2&gt;

&lt;p&gt;The fourth question from [1] is as follows:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;All operations in this question should be performed in the ggckad-s4 namespace. This question will require you to create a pod that runs the image kubegoldenguide/question-thirteen. This image is in the main Docker repository at hub.docker.com.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This image is a web server that has a health endpoint served at '/health'. The web server listens on port 8000. (It runs Python’s SimpleHTTPServer.) It returns a 200 status code response when the application is healthy. The application typically takes sixty seconds to start.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Create a pod called question-13-pod to run this application, making sure to define liveness and readiness probes that use this health endpoint.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Unlike previous questions, this one specifically tells us that the &lt;em&gt;kubegoldenguide/question-thirteen image&lt;/em&gt; is in the main Docker repository at &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;hub.docker.com&lt;/a&gt;. According to the Kubernetes &lt;a href="https://kubernetes.io/docs/concepts/containers/images/" rel="noopener noreferrer"&gt;Images:Image Names&lt;/a&gt; documentation, "&lt;em&gt;[i]f you don't specify a registry hostname, Kubernetes assumes that you mean the Docker public registry&lt;/em&gt;" so no further action is necessary with respect to this detail.&lt;/p&gt;

&lt;p&gt;This question specifically requires &lt;em&gt;liveness&lt;/em&gt; and &lt;em&gt;readiness&lt;/em&gt; probes and we include the definitions of each below for convenience.  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Readiness&lt;/em&gt; -- "the application is ready to receive traffic" [4]. As per [6]: "[i]f the readiness probe fails, the endpoints controller &lt;em&gt;removes the Pod's IP address from the endpoints of all Services that match the Pod&lt;/em&gt;."&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Liveness&lt;/em&gt; -- "the application is no longer serving requests and K8s will restart the offending pod" [4].&lt;/p&gt;

&lt;p&gt;According to the section entitled &lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request" rel="noopener noreferrer"&gt;Define a liveness HTTP request&lt;/a&gt;, "[a]ny code greater than or equal to 200 and less than 400 indicates success." -- so no action is required in our solution as the server running in the &lt;em&gt;question-thirteen&lt;/em&gt; container will return an HTTP status response code of 200 when the application is healthy.&lt;/p&gt;

&lt;p&gt;In our proposed solution, we'll add a buffer and start the &lt;em&gt;livenessProbe&lt;/em&gt; at 75 seconds, which is 15 seconds after the typical expected startup time, as indicated in the &lt;em&gt;question four&lt;/em&gt; details. The 15 second buffer is an arbitrarily chosen number and the assumption is that, realistically, the server should have been started by this time; a similar example appears in [5] and refer also to [7] and [8].&lt;/p&gt;

&lt;p&gt;Note that as of Kubernetes 1.16 it is possible to define a &lt;em&gt;startupProbe&lt;/em&gt; such that the &lt;em&gt;livenessProbe&lt;/em&gt; will not be started until an initial OK is returned.&lt;/p&gt;

&lt;p&gt;Our pod configuration can be seen here.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Finally, we need to verify our work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying Our Solution
&lt;/h3&gt;

&lt;p&gt;In this example, we should expect to see log messages for the &lt;em&gt;readinessProbe&lt;/em&gt; up until ~ 75 seconds after the pod was started, at which point we should see log &lt;em&gt;messages&lt;/em&gt; appear for &lt;em&gt;both&lt;/em&gt; the &lt;em&gt;readinessProbe&lt;/em&gt; as well as the &lt;em&gt;livenessProbe&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl logs question-13-pod -c question-thirteen --v 4 --namespace ggckad-s4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Unfortunately, the output from this command does not tell us which probe is calling the endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_4_verification.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_4_verification.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As an exercise for the reader, can we determine exactly which probe is calling the health endpoint? The Kubernetes documentation seems to indicate that this is possible however at this time I do not have an example which demonstrates this.&lt;/p&gt;

&lt;p&gt;And that's it for this question.&lt;/p&gt;
&lt;h2&gt;
  
  
  Question #5
&lt;/h2&gt;

&lt;p&gt;The fifth question from [1] is as follows:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;All operations in this question should be performed in the ggckad-s5 namespace. Create a file called question-5.yaml that declares a deployment in the ggckad-s5 namespace, with six replicas running the nginx:1.7.9 image.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Each pod should have the label app=revproxy. The deployment should have the label client=user. Configure the deployment so that when the deployment is updated, the existing pods are killed off before new pods are created to replace them.&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;We need to check the labels for both the deployment and pods and then we need to, as per [1] "[c]onfigure the deployment so that when the deployment is updated, the existing pods are killed off before new pods are created to replace them".&lt;/p&gt;

&lt;p&gt;We have two deployment strategies available: &lt;em&gt;RollingUpdate&lt;/em&gt; (the default), and &lt;em&gt;Recreate&lt;/em&gt; [14]. Given the definitions for &lt;em&gt;RollingUpdate&lt;/em&gt; and &lt;em&gt;Recreate&lt;/em&gt; in this case we do not want to use the default and instead need to assign &lt;em&gt;Recreate&lt;/em&gt; to the &lt;em&gt;.spec.strategy.type&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Our deployment configuration can be seen here:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;We can apply the file the same as we did in the previous question:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k apply -f ./question-5.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to verify our work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying Our Solution
&lt;/h3&gt;

&lt;p&gt;We need to check the labels for both the deployment and pods and we also need to ensure that the requirement is met that when the deployment is updated existing pods are killed off before new pods are created to replace them.&lt;/p&gt;

&lt;p&gt;We can use the following command to view the deployment labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k get deployments --show-labels --namespace ggckad-s5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can use the following command to view the various pod labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k get pods --show-labels --namespace ggckad-s5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below we can see the output of applying the question-5.yaml file and then executing these two commands; the yellow arrows show that the labels have been set as per the specification:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_and_pod_labels_only.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_and_pod_labels_only.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that our deployment relies on the nginx:1.7.9 image. This image is old so if we update this to &lt;em&gt;nginx:latest&lt;/em&gt; and apply the question-5.yaml file again then we see that new containers are deployed while the old containers are gradually terminated. The following image demonstrates this behavior:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_strategy_recreate_deployment_reconfigured.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_strategy_recreate_deployment_reconfigured.png" alt="Applying a deployment with a recreate strategy." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we repeat the same exercise only here we check the &lt;em&gt;rollout status&lt;/em&gt; using the following command [11]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout status deployment.v1.apps/question-5 --namespace ggckad-s5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we can see from a different angle that the old replicas are being terminated while the new ones are starting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_strategy_recreate_reconfigured.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_strategy_recreate_reconfigured.png" alt="Checking the rollout status of a deployment which has been updated." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly we can reproduce the same behavior by executing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout restart deployment question-5 --namespace ggckad-s5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in this case we don't even need to update the nginx version in the question-5.yaml file.&lt;/p&gt;

&lt;p&gt;Let's take a look at an update when the deployment strategy type is set to &lt;em&gt;RollingUpdate&lt;/em&gt; -- this is the default and it is also the incorrect choice given the specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  An Incorrect Solution
&lt;/h3&gt;

&lt;p&gt;The same example but with a &lt;em&gt;RollingUpdate&lt;/em&gt; deployment strategy would be incorrect. We include the output of this example below for comparison purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_reconfigured.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_reconfigured.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we repeat the same exercise only here we check the &lt;em&gt;rollout status&lt;/em&gt; using the following command [11]:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl rollout status deployment.v1.apps/question-5 --namespace ggckad-s5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and we can see from a different angle that the old replicas are being terminated while the new ones are starting.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_rollout_status.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthospfuller.com%2Fwp-content%2Fuploads%2F2020%2F11%2Fpractice_exam_for_certified_kubernetes_application_developer_ckad_certification_question_5_deployment_rollout_status.png" alt="The rollout status when updating Nginx from 1.7.9 to latest." width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's it for this question, and for this article for that matter -- on to the conclusion!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article took several hours to write and was done in part as an investigation into how these problems could be solved as an introduction into studying for the CKAD exam for me, specifically.&lt;/p&gt;

&lt;p&gt;There are several good articles available if you're beginning the process of preparing for this certification which provide guidance about the test structure and how to study for the exam and I include several links below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cncf.io/blog/2020/07/20/which-kubernetes-certification-is-right-for-you/" rel="noopener noreferrer"&gt;Which Kubernetes certification is right for you?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://callistaenterprise.se/blogg/teknik/2020/04/30/CKAD-exam-preparation-tips/" rel="noopener noreferrer"&gt;Certified Kubernetes Application Developer (CKAD) exam preparation tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@nikhilagrawal577/how-to-pass-ckad-exam-in-1st-attempt-tips-tricks-in-k8s-9e14477699ca" rel="noopener noreferrer"&gt;How to pass CKAD exam in first attempt ? Tips &amp;amp; Tricks in Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ravikirans.com/ckad-kubernetes-exam-preparation-guide/" rel="noopener noreferrer"&gt;CKAD Exam Preparation Study Guide (Certified Kubernetes Application Developer)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://matthewpalmer.net/kubernetes-app-developer/articles/ckad-exam-guide.html" rel="noopener noreferrer"&gt;CKAD Exam Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/faun/be-fast-with-kubectl-1-18-ckad-cka-31be00acc443" rel="noopener noreferrer"&gt;Be fast with Kubectl 1.19 CKAD/CKA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552" rel="noopener noreferrer"&gt;Practice Enough With These 150 Questions for the CKAD Exam&lt;/a&gt; (noted in the comments, apparently these are not questions that would appear on the exam however this is still a good list)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have other resources or references that you've found helpful in preparing to sit for this exam, please include them in the comments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quiz
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Refer to Question 1: Why don't we need to include the specific container in the port-forward command, copied below for convenience, when &lt;em&gt;both&lt;/em&gt; the alpine-spin-container as well as the nginx-container &lt;em&gt;both&lt;/em&gt; rely on containerPort 80?  &lt;/p&gt;

&lt;p&gt;kubectl port-forward pods/pod-b 19999:80 --namespace ggckad-s0  &lt;/p&gt;

&lt;p&gt;Note: port-forward only allows us to specify the pod and not the pod + container.  &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Refer to Question 1: What would happen if we tried to start pod-b but instead of the alpine-spin-container we had two nginx-container s?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is the difference between a deployment strategy of "Recreate" juxtaposed with "RollingUpdate"?&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Hat Tip
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/rishilmalik/" rel="noopener noreferrer"&gt;Rishi Malik&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/ed-macdonald-7037006/" rel="noopener noreferrer"&gt;Ed McDonald&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/aaronfriel/" rel="noopener noreferrer"&gt;Aaron Friel&lt;/a&gt;, &lt;a href="https://www.linkedin.com/in/scottslowe/" rel="noopener noreferrer"&gt;Scott Lowe&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/in/sudermanjr/" rel="noopener noreferrer"&gt;Andy Suderman&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://matthewpalmer.net/kubernetes-app-developer/articles/ckad-practice-exam.html" rel="noopener noreferrer"&gt;Practice Exam for Certified Kubernetes Application Developer (CKAD) Certification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way" rel="noopener noreferrer"&gt;kelseyhightower / kubernetes-the-hard-way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/" rel="noopener noreferrer"&gt;Connecting Applications with Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/" rel="noopener noreferrer"&gt;Configure Liveness, Readiness and Startup Probes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.colinbreck.com/kubernetes-liveness-and-readiness-probes-how-to-avoid-shooting-yourself-in-the-foot/" rel="noopener noreferrer"&gt;Kubernetes Liveness and Readiness Probes: How to Avoid Shooting Yourself in the Foot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/" rel="noopener noreferrer"&gt;Pod Lifecycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-setting-up-health-checks-with-readiness-and-liveness-probes" rel="noopener noreferrer"&gt;Kubernetes best practices: Setting up health checks with readiness and liveness probes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-startup-probes" rel="noopener noreferrer"&gt;Protect slow starting containers with startup probes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/#define-a-liveness-http-request" rel="noopener noreferrer"&gt;Define a liveness HTTP request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/" rel="noopener noreferrer"&gt;Configure a Pod to Use a ConfigMap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#rollover-aka-multiple-updates-in-flight" rel="noopener noreferrer"&gt;Rollover (aka multiple updates in-flight)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.container-solutions.com/kubernetes-deployment-strategies" rel="noopener noreferrer"&gt;Kubernetes deployment strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/" rel="noopener noreferrer"&gt;Proportional scaling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy" rel="noopener noreferrer"&gt;Deployments : Strategy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way" rel="noopener noreferrer"&gt;Kubernetes The Hard Way&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://phoenixnap.com/kb/how-to-restart-kubernetes-pods" rel="noopener noreferrer"&gt;How To Restart Kubernetes Pods&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>kubernetes</category>
      <category>cloudnative</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hidden Gems: Event-Driven Change Notifications in Relational Databases</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Sun, 09 Aug 2020 15:46:11 +0000</pubDate>
      <link>https://dev.to/coherentlogic/hidden-gems-event-driven-change-notifications-in-relational-databases-23gn</link>
      <guid>https://dev.to/coherentlogic/hidden-gems-event-driven-change-notifications-in-relational-databases-23gn</guid>
      <description>&lt;h2&gt;
  
  
  &lt;em&gt;A powerful non-standard feature that developers should know about&lt;/em&gt;
&lt;/h2&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Wouldn’t it be great if we could receive event-driven change notifications (EDCN) when data changes directly from the database without having to poll for updates?&lt;/p&gt;

&lt;p&gt;This feature is, in fact, available in some relational databases, but &lt;em&gt;not all,&lt;/em&gt; as it’s non-standard functionality and not part of any SQL specification.&lt;/p&gt;

&lt;p&gt;In the three examples covered in this article, this functionality is expressed via the implementation of an interface that is then registered with the JDBC driver directly. This opens the door to a myriad of potential use cases that can be expressed without the need to poll and which do not require the developer to write infrastructure code to deal with changes in data and notifying interested parties. Instead, we can interface with the driver directly and listen for changes and, when they occur, execute whatever workflow we have in an event-driven fashion. A few examples where this could be helpful include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Caching (more on this when we cover PostgreSQL, see also &lt;a href="https://docs.oracle.com/database/121/ADFNS/adfns_cqn.htm#ADFNS1015" rel="noopener noreferrer"&gt;Good Candidates for CQN&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://hackernoon.com/poison-records-acra-eli5-d78250ef94f" rel="noopener noreferrer"&gt;Honeypots&lt;/a&gt; for database tables — also see &lt;a href="https://hackernoon.com/poison-records-acra-eli5-d78250ef94f" rel="noopener noreferrer"&gt;poison records&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Debugging problems&lt;/li&gt;
&lt;li&gt;Logging changes&lt;/li&gt;
&lt;li&gt;Analytics and reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are, of course, some consequences when relying on this functionality. The most obvious implication is that it’s a non-standard feature that ties the application directly to the database.&lt;/p&gt;

&lt;p&gt;I was speaking with &lt;a href="https://www.linkedin.com/in/duergner/" rel="noopener noreferrer"&gt;Michael Dürgner&lt;/a&gt; on &lt;a href="https://www.linkedin.com/posts/thomasfuller_code-postgres-database-activity-6689162224210075648-N4Ah" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; about an example implementation as it pertains to PostgreSQL, and &lt;a href="https://www.linkedin.com/feed/update/urn:li:activity:6689162224210075648/?commentUrn=urn%3Ali%3Acomment%3A%28activity%3A6689162224210075648%2C6692526639311527936%29" rel="noopener noreferrer"&gt;he commented that&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“[W]hile it’s definitely a great way to do this, one of the big drawbacks is that you move application logic into the RDBMS. Not saying you shouldn’t do it but make sure that you have people with deep understanding of the RDBMS you use on board since it’ll be rather unlikely your average software will be able to trouble shoot. Another huge challenge with this approach is continuous delivery since your RDBMS needs to be deeply integrated with your delivery pipeline.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I agree with Michael’s position, and keeping business logic out of the database tends to be a good practice.&lt;/p&gt;

&lt;p&gt;Projects that rely on object-relational mapping (ORM) tools such as the &lt;a href="https://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html" rel="noopener noreferrer"&gt;Java Persistence API&lt;/a&gt; (JPA) to generate the database schema directly from one or more object models immediately lose portability and simplicity when developers are required to add logic in the database tier which probably belongs in the application itself. If developers are not careful, they’ll end up having to use the same database for testing as used in production and this could easily lead to pain and regret.&lt;/p&gt;

&lt;p&gt;I proffer the following question to any engineer considering using EDCNs via the JDBC driver: can the application still function as intended without the inclusion of whatever it is that you’re building that relies on this functionality? If the answer is “yes” then what you’re doing is likely fine; on the contrary, if the answer is “no”, then this is a strike against using EDCNs and alternatives may need to be considered.&lt;/p&gt;

&lt;p&gt;Finally, this feature on its own is not a substitute for well-engineered &lt;a href="https://en.wikipedia.org/wiki/Message-oriented_middleware" rel="noopener noreferrer"&gt;message-oriented middleware&lt;/a&gt; (MOM), which typically provides out-of-the-box solutions for guaranteed delivery, message persistence, &lt;a href="https://doc.akka.io/docs/akka/current/general/message-delivery-reliability.html?language=scala" rel="noopener noreferrer"&gt;at-least-once/exactly-once delivery&lt;/a&gt;, delivery via queues and topics, strategies for flow control (see also: &lt;a href="https://medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7" rel="noopener noreferrer"&gt;backpressure&lt;/a&gt;), and addresses fault tolerance and scalability concerns. The presence of these requirements could be a strong indicator that an approach relying on EDCNs needs to be reconsidered.&lt;/p&gt;

&lt;p&gt;Below we explore this functionality as it exists in the &lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;, &lt;a href="https://docs.oracle.com/en/database/oracle/oracle-database/index.html" rel="noopener noreferrer"&gt;Oracle&lt;/a&gt;, and &lt;a href="http://www.h2database.com/" rel="noopener noreferrer"&gt;H2&lt;/a&gt; databases; we also include some general comments on &lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt; and its fork, &lt;a href="https://mariadb.org/" rel="noopener noreferrer"&gt;MariaDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Throughout this article, we rely on Java 13.0.2 and Groovy. 3.0.4 and include links to the various scripts on GitHub which contain extra notes pertaining to how to set up the required dependencies and any other preconditions necessary to run the examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  PostgreSQL
&lt;/h2&gt;

&lt;p&gt;The PostgreSQL (Postgres) database is the first example we’ll examine.&lt;/p&gt;

&lt;p&gt;The Postgres API includes the &lt;a href="https://impossibl.github.io/pgjdbc-ng/apidocs/0.7/com/impossibl/postgres/api/jdbc/PGNotificationListener.html" rel="noopener noreferrer"&gt;PGNotificationListener&lt;/a&gt; interface which must be implemented and then registered with the database connection. Note that there are two implementations of this available: the &lt;a href="https://jdbc.postgresql.org/" rel="noopener noreferrer"&gt;Postgres [default] JDBC driver&lt;/a&gt; and the &lt;a href="https://github.com/impossibl/pgjdbc-ng" rel="noopener noreferrer"&gt;Impossibl JDBC driver&lt;/a&gt; implementation. We do not want to use the Postgres driver, as that implementation will poll the database for changes. Instead, we will rely on the Impossibl implementation, which delivers true event-driven notifications.&lt;/p&gt;

&lt;p&gt;I had the opportunity to speak with &lt;a href="https://www.linkedin.com/in/erikbrandsberg/" rel="noopener noreferrer"&gt;Erik Brandsberg&lt;/a&gt;, CTO of &lt;a href="https://www.heimdalldata.com/" rel="noopener noreferrer"&gt;Heimdall Data&lt;/a&gt; about this, and Erik remarked that:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The PG notify interface is one of the hidden gems in PG vs. other databases. We can use it to provide cache invalidation messages between proxies instead of using a distinct pub/sub interface such as on Redis.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Heimdall Data delivers a sophisticated caching solution for applications that use &lt;a href="https://aws.amazon.com/rds/" rel="noopener noreferrer"&gt;Amazon Relational Database Service&lt;/a&gt; (Amazon RDS) and other databases and this is one real-world use case that demonstrates how important this functionality can be.&lt;/p&gt;

&lt;p&gt;In the following example, the &lt;a href="https://www.postgresql.org/docs/9.6/plpgsql-trigger.html" rel="noopener noreferrer"&gt;trigger&lt;/a&gt; and &lt;a href="https://www.postgresql.org/docs/9.6/sql-createfunction.html" rel="noopener noreferrer"&gt;function&lt;/a&gt; script must be executed inside Postgres as a precondition to running the Groovy script. The &lt;em&gt;notify_change&lt;/em&gt; function will send events to any registered &lt;a href="https://en.wikipedia.org/wiki/Event_(computing)" rel="noopener noreferrer"&gt;listeners&lt;/a&gt; that are listening on the &lt;em&gt;examplechannel&lt;/em&gt; &lt;a href="https://en.wikipedia.org/wiki/Channel_(programming)" rel="noopener noreferrer"&gt;channel&lt;/a&gt; — pay particular attention to the warning below, as channel names are case sensitive.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;A &lt;a href="https://github.com/thospfuller/GroovyExamples/blob/master/event-driven-jdbc/PGNotificationListenerInPostGreSQLDatabaseExample.groovy" rel="noopener noreferrer"&gt;working example&lt;/a&gt; implementation of the &lt;a href="https://impossibl.github.io/pgjdbc-ng/apidocs/0.7/com/impossibl/postgres/api/jdbc/PGNotificationListener.html" rel="noopener noreferrer"&gt;com.impossibl.postgres.api.jdbc. PGNotificationListener&lt;/a&gt; using the PostgreSQL database is included next. The &lt;em&gt;PGNotificationListener&lt;/em&gt; interface requires that the developer implement just one method:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;void notification(int processId, String channelName, String payload)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;We can see this on line #18 below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We can see an example of this script being executed along with an explanation and the output which appears in the &lt;a href="http://www.groovy-lang.org/groovyconsole.html" rel="noopener noreferrer"&gt;GroovyConsole&lt;/a&gt; in the following image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3237xm3242cutzn7riz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy3237xm3242cutzn7riz.png" alt="An explanation of the PostgreSQL example running in the Groovy Console." width="800" height="485"&gt;&lt;/a&gt;&lt;em&gt;An explanation of the PostgreSQL example running in the Groovy Console.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The next example we’ll cover includes event-driven change notification functionality as it applies to the &lt;a href="https://en.wikipedia.org/wiki/Oracle_Database" rel="noopener noreferrer"&gt;Oracle Database&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oracle
&lt;/h2&gt;

&lt;p&gt;The next example we’ll cover in this article will focus on the &lt;a href="https://en.wikipedia.org/wiki/Oracle_Database" rel="noopener noreferrer"&gt;Oracle Database&lt;/a&gt; (Oracle). Below we detail the steps required to configure event-driven change notifications via the JDBC driver along with preconditions required to run the example.&lt;/p&gt;

&lt;p&gt;The following two gists are required preconditions for this example. It is instructive to note that Docker was running on another machine which, in this case, uses the Ubuntu operating system. See the warning regarding running Oracle in Docker locally in the &lt;a href="https://github.com/thospfuller/GroovyExamples/blob/master/event-driven-jdbc/DatabaseChangeListenerInOracleDatabaseExample.groovy" rel="noopener noreferrer"&gt;DatabaseChangeListenerInOracleDatabaseExample.groovy&lt;/a&gt; script for complete details.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In SQL*Plus, we can now run the following configuration script. Keep in mind that once the example table has been created, see line #8, the Groovy script in the next section can be started and any insert, update, or delete operations on the target table will result in an event being sent to the Groovy script and then printed to the console output.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here we have an example of the complete &lt;a href="https://github.com/thospfuller/GroovyExamples/blob/master/event-driven-jdbc/DatabaseChangeListenerInOracleDatabaseExample.groovy" rel="noopener noreferrer"&gt;DatabaseChangeListenerInOracleDatabaseExample.groovy&lt;/a&gt; script. Note that the developer must implement one method:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;void onDatabaseChangeNotification(DatabaseChangeEvent databaseChangeEvent)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;We can see this implementation on line #55 below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The following image goes into deeper detail regarding what each step is doing, along with some notes explaining the output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwaouno3iyg2atbk70h2m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwaouno3iyg2atbk70h2m.png" alt="A deeper explanation regarding what the example script, as it pertains to the Oracle database, is doing, including notes explaining the output." width="800" height="509"&gt;&lt;/a&gt;&lt;em&gt;A deeper explanation regarding what the example script, as it pertains to the Oracle database, is doing, including notes explaining the output.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lastly, the following image demonstrates that when we perform five inserts in a row and then commit the changes, only a single event is emitted, which includes these five inserts. Events are only ever emitted whenever commit has returned successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp22u64n0ohrl4sr7u8mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp22u64n0ohrl4sr7u8mz.png" alt="Five inserts are executed in SQL*Plus followed by a single commit and we can see that this event includes these five insert operations." width="800" height="183"&gt;&lt;/a&gt;&lt;em&gt;Five inserts are executed in SQL*Plus followed by a single commit and we can see that this event includes these five insert operations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The final example we’ll cover in this article includes the &lt;a href="https://www.h2database.com/html/main.html" rel="noopener noreferrer"&gt;H2 database&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  H2 Database
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.h2database.com/html/main.html" rel="noopener noreferrer"&gt;H2 database&lt;/a&gt; is an open-source, lightweight, and very powerful relational database written entirely in Java. It supports a long list of features and &lt;a href="https://mvnrepository.com/artifact/com.h2database/h2" rel="noopener noreferrer"&gt;ships as a single 2.2mb jar file&lt;/a&gt;. H2 is frequently used when testing Java applications and works well as an embedded database and can be used with &lt;a href="https://docs.oracle.com/javaee/6/tutorial/doc/bnbpz.html" rel="noopener noreferrer"&gt;object-relational mapping tools such as the Java Persistence API (JPA)&lt;/a&gt;. H2 is also embedded in the &lt;a href="https://wildfly.org/" rel="noopener noreferrer"&gt;JBoss Wildfly application server&lt;/a&gt; (JBoss) and has been in use in JBoss as an embedded database for a very long time.&lt;/p&gt;

&lt;p&gt;H2 delivers event notifications via the &lt;a href="http://www.h2database.com/javadoc/org/h2/api/DatabaseEventListener.html" rel="noopener noreferrer"&gt;org.h2.api.DatabaseEventListener&lt;/a&gt; interface. The DatabaseEventListener interface offers limited functionality when compared with the Postgres and Oracle listener specifications covered earlier. The methods required to implement the interface are:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;void closingDatabase ()&lt;br&gt;
void exceptionThrown(SQLException sqlException, String sql)&lt;br&gt;
void init (String url)&lt;br&gt;
void opened ()&lt;br&gt;
void setProgress (String state, String name, int x, int max)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;A working example implementation of the &lt;a href="http://www.h2database.com/javadoc/org/h2/api/DatabaseEventListener.html" rel="noopener noreferrer"&gt;org.h2.api.DatabaseEventListener&lt;/a&gt; using the H2 database &lt;a href="https://github.com/thospfuller/GroovyExamples/blob/master/event-driven-jdbc/H2EventListenerExample.groovy" rel="noopener noreferrer"&gt;can be found on GitHub&lt;/a&gt; and is also included in the gist below followed by an image with pointers explaining how this works.&lt;/p&gt;

&lt;p&gt;In this example, H2 is running in embedded mode — that is, H2 is running entirely in memory in the same virtual machine that the Groovy script is running in.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the following image, we can see an example of this script being executed, along with the output in the GroovyConsole.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F200rtx7ld99zsm5exn2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F200rtx7ld99zsm5exn2h.png" alt="An example of the H2 DatabaseEventListener running in the Groovy Console including output." width="800" height="500"&gt;&lt;/a&gt;&lt;em&gt;An example of the H2 DatabaseEventListener running in the Groovy Console including output.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s somewhat disappointing that the H2 DatabaseEventListener doesn’t offer similar functionality to that found in the PostgreSQL interface. As a result, I submitted &lt;a href="https://github.com/h2database/h2database/issues/2761" rel="noopener noreferrer"&gt;a new feature request on the H2 Database repository on GitHub&lt;/a&gt; and may try to implement this myself, time permitting.&lt;/p&gt;

&lt;h2&gt;
  
  
  MySQL/MariaDB
&lt;/h2&gt;

&lt;p&gt;Event-driven change notifications via the JDBC driver do not appear to be supported by either MySQL or MariaDB databases and so engineers will have to consider alternative solutions if this functionality is required.&lt;/p&gt;

&lt;p&gt;We will not cover triggers and user-defined functions (UDF) as they pertain to MySQL and MariaDB to call a web service endpoint, which is one such alternative. Brief research on this subject suggests that triggers and UDFs can be used to accomplish this; however, they come with potentially significant security and performance implications that must be considered when taking this approach.&lt;/p&gt;

&lt;p&gt;If you’ve used triggers and UDFs or some other solution to accomplish this within MySQL and/or MariaDB please feel free to elaborate on what you needed to do, the approach you took, and how well it worked out in the comments. Finally, If there’s a better solution available in MySQL and MariaDB, please explain further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Have you used event-driven change notifications in relational databases in a project you were on? If so, I encourage you to discuss any of the following in the comments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What was it needed for?&lt;/li&gt;
&lt;li&gt;What database was used?&lt;/li&gt;
&lt;li&gt;What language was the solution written in?&lt;/li&gt;
&lt;li&gt;Can you do it with &lt;a href="https://www.microsoft.com/en-us/sql-server" rel="noopener noreferrer"&gt;Microsoft SQL Server&lt;/a&gt; or another database not covered here?&lt;/li&gt;
&lt;li&gt;Were any problems encountered, and how were they addressed?&lt;/li&gt;
&lt;li&gt;Was this option explored and determined to &lt;em&gt;not&lt;/em&gt; be an appropriate solution for the problem at hand?&lt;/li&gt;
&lt;li&gt;Were you forced to use an alternative and, if so, what did the implementation look like and why?&lt;/li&gt;
&lt;li&gt;Any other thoughts you might have, including any questions I might have left out here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While EDCNs offer powerful functionality in supported relational databases, we hope that, in addition to providing some working examples, it has also been made clear that there’s a cost associated with relying on this feature and that you must give due consideration before using it.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;h1&gt;
  
  
  Before You Go
&lt;/h1&gt;

&lt;p&gt;If you found this document to be useful, you may also find the &lt;a href="https://www.meetup.com/Washington-DC-CTO-Meetup-Group/" rel="noopener noreferrer"&gt;Washington, DC Chief Technical Officer Meetup Group&lt;/a&gt; to be helpful too. We run events frequently and as these are available over Zoom being local to the DC area is not a requirement.&lt;/p&gt;

&lt;p&gt;See also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://slofile.com/slack/dcctos" rel="noopener noreferrer"&gt;DC Metro Area Chief Technology Officer &lt;em&gt;Slack&lt;/em&gt; Community&lt;/a&gt; (&lt;a href="https://coherentlogic.com/for-ctos/dc-cto-slack-group-signup-form/" rel="noopener noreferrer"&gt;alternate link here&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/groups/12301178/" rel="noopener noreferrer"&gt;DC Metro Area Chief Technology Officer (CTO) &lt;em&gt;LinkedIn&lt;/em&gt; Group&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Cover image compliments of &lt;a href="https://unsplash.com/@justchris87" rel="noopener noreferrer"&gt;Chris Coe&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>java</category>
      <category>tutorial</category>
      <category>sql</category>
    </item>
    <item>
      <title>Demo Friday: Erik Brandsberg reviewed the Heimdall Distributed Database Proxy</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Thu, 04 Jun 2020 20:37:06 +0000</pubDate>
      <link>https://dev.to/coherentlogic/demo-friday-erik-brandsberg-will-review-the-heimdall-distributed-database-proxy-2he5</link>
      <guid>https://dev.to/coherentlogic/demo-friday-erik-brandsberg-will-review-the-heimdall-distributed-database-proxy-2he5</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=w5xDpAtJMvc" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pskg9pig75bzgwur5gb.jpg" alt="Demo Friday: Erik Brandsberg will review the Heimdall Distributed Database Proxy" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Click the image above to watch the video on YouTube&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On Friday, May 22nd, &lt;a href="https://www.linkedin.com/in/erikbrandsberg/" rel="noopener noreferrer"&gt;Erik Brandsberg&lt;/a&gt;, Chief Technical Officer at &lt;a href="https://www.heimdalldata.com/" rel="noopener noreferrer"&gt;Heimdall Data&lt;/a&gt;, reviewed the Heimdall Distributed Database Proxy (HD).&lt;/p&gt;

&lt;p&gt;The Heimdall Distributed Database Proxy is a SQL platform for application developers, database administrators, and infrastructure owners.&lt;/p&gt;

&lt;p&gt;Whether on-premise or cloud, Heimdall helps organizations deliver faster, more reliable, and secure content generation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Use Cases:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Find Performance Bottlenecks&lt;/strong&gt;: Heimdall’s analytics provides complete SQL performance visibility (e.g. slow, redundant queries) and offers recommendations to remediate them. It diagnoses and cures. For deployment there are no application modifications or integration work required for installation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increase Scale&lt;/strong&gt;: Heimdall’s read/write splitting allows customers to make better use of read replicas with ZERO application changes. Heimdall Data is a 5-minute drop-in replacement. Moreover, we guarantee query reads will always have fresh data with our lag detection logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maximize Uptime&lt;/strong&gt;: Heimdall is application-aware ensuring connection uptime upon a database failover. Why spend resources developing and re-architecting a solution, when you can use Heimdall and install it a matter of minutes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Strengthen Security&lt;/strong&gt;: Heimdall provides an added layer of defense, protecting the database from malicious ZERO day attacks. Unlike other solutions, Heimdall’s database firewall does not rely on pattern or signature matching. It is contextual; alerting and filtering SQL queries that are deemed “abnormal”.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Heimdall Architecture
&lt;/h1&gt;

&lt;p&gt;Heimdall Data is a distributed Database Proxy that optimizes from an application perspective. It gives users visibility and control over their SQL environment. Our proxy can be installed anywhere: 1) On each application instance, 2) Separate proxy tier, or 3) On the database. We are transparent to the application and database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;: Today’s SQL solutions incur data latency from application-database round trips. Caching on the database improves scale, but does not remove the latency. The Heimdall proxy can be deployed as a sidecar process across application instances. This distributed model results in optimal performance and predictive scale.&lt;/p&gt;

&lt;p&gt;With Heimdall caching, queries that would have gone to the database are now cached locally on the application tier. You choose the cache of choice (e.g. Amazon Elasticache, Redis) and Heimdall determines which query results to cache and invalidate. Best of all, caching does not require writing a single line of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read/Write Split&lt;/strong&gt;: To scale the database tier horizontally with master and read replicas, applications modifications are required. Heimdall is SQL aware and routes queries to the appropriate database instances (writes or read replicas). As an added benefit, we support replication lag detection to ensure fresh data is always served.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated Failover&lt;/strong&gt;: Health checks each database instance. Upon a failure, Heimdall holds the connection as it transitions to the redundant database instance. This results in failovers that are transparent to the application.&lt;/p&gt;




&lt;center&gt;[Sign up to our email list](http://eepurl.com/b5jPPj)&lt;/center&gt;

</description>
      <category>database</category>
      <category>aws</category>
      <category>architecture</category>
      <category>techtalks</category>
    </item>
    <item>
      <title>Awesome Backlinks &amp; SEO Workshops</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Tue, 05 May 2020 19:07:40 +0000</pubDate>
      <link>https://dev.to/coherentlogic/awesome-backlinks-1lmd</link>
      <guid>https://dev.to/coherentlogic/awesome-backlinks-1lmd</guid>
      <description>&lt;p&gt;I created a page on GitHub called &lt;a href="https://github.com/thospfuller/awesome-backlinks" rel="noopener noreferrer"&gt;Awesome Backlinks&lt;/a&gt; which has a number of ideas for where backlinks can be created. The purpose, in this case, is focused more on releasing a product or project and gaining awareness for a deliverable. These suggestions could be useful elsewhere, of course.&lt;/p&gt;

&lt;p&gt;At this point I have around 16 ideas and intend to expand this list over time.&lt;/p&gt;

&lt;p&gt;With that said, what ideas can you share for opportunities to create backlinks?&lt;/p&gt;

&lt;p&gt;For convenience, I've included the current list below.&lt;/p&gt;

&lt;p&gt;I also host various SEO-related workshops along with discussions on other technical topics online. Register via the &lt;a href="https://www.meetup.com/Washington-DC-CTO-Meetup-Group/" rel="noopener noreferrer"&gt;Washington, DC CTO Meetup Group&lt;/a&gt; if this interests you. As these are held completely via Zoom being local to the DC area is not a requirement.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Add a link on a page from your company website to the project&lt;/li&gt;
&lt;li&gt;Add a link on a page from your blog to the project&lt;/li&gt;
&lt;li&gt;Twitter (social signal)&lt;/li&gt;
&lt;li&gt;LinkedIn Company Updates - Add a URL to the project will be available for indexing (shortened links are considered redirects by Google).&lt;/li&gt;
&lt;li&gt;LinkedIn Group Posts - Do NOT count as backlinks but may help to bring awareness to a project.&lt;/li&gt;
&lt;li&gt;LinkedIn Personal Posts - Do NOT count as backlinks but may help to bring awareness to a project.&lt;/li&gt;
&lt;li&gt;Write an article on _____ and backlink to the project.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com" rel="noopener noreferrer"&gt;Medium.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;[WANTED: Other sites here]&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Answer questions on &lt;a href="https://www.quora.com/" rel="noopener noreferrer"&gt;Quora&lt;/a&gt; and link to the project.&lt;/li&gt;

&lt;li&gt;Send email to group mailing lists (project awareness, may be indexed if the mailing list is is archived and publicly available).&lt;/li&gt;

&lt;li&gt;Create a video and release it on &lt;a href="https://youtube.com" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt; and link to the project in the description.&lt;/li&gt;

&lt;li&gt;Find appropriate awesome-[x] lists and add a link to your project there.

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://java-lang.github.io/awesome-java/" rel="noopener noreferrer"&gt;Awesome Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/qinwf/awesome-R" rel="noopener noreferrer"&gt;Awesome R Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/uhub/awesome-c-sharp" rel="noopener noreferrer"&gt;Awesome C#&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mickaelandrieu/awesome-cobol" rel="noopener noreferrer"&gt;Awesome COBOL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/igorbarinov/awesome-data-engineering" rel="noopener noreferrer"&gt;Awesome Data Engineering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Find complimentary projects and add the backlink to the README in a "See Also" section or where appropriate. Note that reciprocity is likely welcomed.&lt;/li&gt;

&lt;li&gt;Talk about the project in a podcast and request that the project backlink be added in the details.

&lt;ul&gt;
&lt;li&gt;[Podcasts WANTED]&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Talk at a &lt;a href="https://meetup.com" rel="noopener noreferrer"&gt;meetup.com event&lt;/a&gt; and request that the project backlink be added in the details.&lt;/li&gt;

&lt;li&gt;Post on Facebook (for referral traffic, see also &lt;a href="https://monitorbacklinks.com/blog/seo/facebook-backlinks" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://monitorbacklinks.com/blog/seo/facebook-backlinks" rel="noopener noreferrer"&gt;https://monitorbacklinks.com/blog/seo/facebook-backlinks&lt;/a&gt; )&lt;/li&gt;

&lt;li&gt;Showcase the project including the backlink on &lt;a href="https://www.google.com/business/" rel="noopener noreferrer"&gt;Google My Business&lt;/a&gt;
&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  See Also
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.matthewwoodward.co.uk/seo/link-building/social-media-backlinks/" rel="noopener noreferrer"&gt;28 Social Media Backlinks To Increase Your Rankings In 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://neilpatel.com/blog/backlink-opportunities/" rel="noopener noreferrer"&gt;How to Find 50 Backlink Opportunities in Just 20 Minutes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://backlinko.com/hub/seo/backlinks" rel="noopener noreferrer"&gt;What are Backlinks? And How to Build Them in 2020&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://smart.linkresearchtools.com/linkthing/case-studies/link-building-techniques" rel="noopener noreferrer"&gt;20 SEO Link Building Methods for 2020&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>showdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Prepare for the AWS Certified Solutions Architect: Associate Certification Exam</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Fri, 31 Jan 2020 22:29:15 +0000</pubDate>
      <link>https://dev.to/coherentlogic/aws-associate-architect-certification-exam-preparation-notes-1oc4</link>
      <guid>https://dev.to/coherentlogic/aws-associate-architect-certification-exam-preparation-notes-1oc4</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: &lt;em&gt;Take a course online, use flash cards, and take as many practice exams as possible (17 quizzes, exams, and practice tests are included below, see the *'s)&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this article I include several observations based on my experience preparing to take the AWS Certified Solutions Architect: &lt;em&gt;Associate Certification Exam‎&lt;/em&gt; -- if you are planning to sit for this exam hopefully you will find the following pointers to be helpful.&lt;/p&gt;

&lt;p&gt;In my opinion, practice exams and tests are a very important tool to use when studying for this exam and this article includes &lt;em&gt;17 links&lt;/em&gt; to exams, quizzes, and tests to assist you in your effort [see *'s].&lt;/p&gt;

&lt;p&gt;🎓 The test is not hard but it's not easy either, so expect to study. I would recommend first taking a practice exam and seeing how you do and then setting a date to take the actual exam which is not too far in the future. Once you've completed a practice exam you'll be able to see where you're weak and then you can dedicate extra effort on those domains that require attention.&lt;/p&gt;

&lt;p&gt;Then study with the intention of sitting for the exam on that date.&lt;/p&gt;

&lt;p&gt;You could even lock yourself in by scheduling the exam before you begin studying for it in earnest.&lt;/p&gt;

&lt;p&gt;From &lt;a href="https://d1.awsstatic.com/training-and-certification/docs-sa-assoc/AWS_Certified_Solutions_Architect_Associate_Exam_Guide_BETA.PDF" rel="noopener noreferrer"&gt;AWS Certified Solutions Architect –&lt;br&gt;
Associate (SA1-C01) Exam Blueprint&lt;/a&gt;, the test is broken down as follows (note the links below point to subject-specific &lt;em&gt;practice assessments&lt;/em&gt; which may be helpful):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Domain&lt;/th&gt;
&lt;th&gt;% of Scored Items&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain 1: &lt;a href="https://cloudacademy.com/quiz/33572/" rel="noopener noreferrer"&gt;Design Resilient Architectures *&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;34%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain 2: &lt;a href="https://cloudacademy.com/quiz/33573/" rel="noopener noreferrer"&gt;Define Performant Architectures *&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;24%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain 3: &lt;a href="https://cloudacademy.com/quiz/33574/" rel="noopener noreferrer"&gt;Specify Secure Applications and Architectures *&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain 4: &lt;a href="https://cloudacademy.com/quiz/33575/" rel="noopener noreferrer"&gt;Design Cost-Optimized Architectures *&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Domain 5: &lt;a href="https://cloudacademy.com/quiz/33576/" rel="noopener noreferrer"&gt;Define Operationally Excellent Architectures *&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You should also become acquainted with the &lt;a href="https://aws.amazon.com/blogs/apn/the-5-pillars-of-the-aws-well-architected-framework/" rel="noopener noreferrer"&gt;The 5 Pillars of the AWS Well-Architected Framework&lt;/a&gt; which includes operational excellence, security, reliability, performance efficiency, and cost optimization.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://aws.amazon.com/certification/certification-prep/" rel="noopener noreferrer"&gt;Prepare for Your AWS Certification Exam *&lt;/a&gt; page includes more sample questions, another practice exam, and further information.&lt;/p&gt;

&lt;p&gt;🎓 Take courses online, especially courses that have practice exams and I've included two courses for your consideration below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-saa-c01/" rel="noopener noreferrer"&gt;Ultimate AWS Certified Solutions Architect Associate 2020 *&lt;/a&gt; includes one practice exam.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-amazon-practice-exams/" rel="noopener noreferrer"&gt;AWS Certified Solutions Architect Associate Practice Exams *&lt;/a&gt; includes six practice exams.&lt;/p&gt;

&lt;p&gt;Further example tests and questions can be found in [3, 4, 5, and 11 *].&lt;/p&gt;

&lt;p&gt;In my opinion, as long as you're motivated it should not be necessary to take classroom training in order to pass this exam. Keep in mind, however, that I have been developing software for ~ 20 years at the time of this writing and I have experience with AWS as well. People who are new to AWS or who are unfamiliar with the concepts may benefit from classroom-based training.&lt;/p&gt;

&lt;p&gt;🎓 YouTube has many excellent videos on this subject and below I've added three to this article, see [8, 9, 10]. If you find that you're weak on a given topic YouTube will likely have videos that can compliment the other material you're relying on to prepare for this exam.&lt;/p&gt;

&lt;p&gt;🎓 Some questions revolve around corner cases &amp;amp; details which are easy to answer with Google, but you won't have Google available when you take the exam so it's important to know these corner cases because these questions are usually easy to answer once you understand the nuance.&lt;/p&gt;

&lt;p&gt;🎓 You'll need to pace yourself properly otherwise you'll run low on time and end up needing to rush through questions to complete the exam, and that's not a good place to be.&lt;/p&gt;

&lt;p&gt;The test consists of 65 multiple choice questions and 130 minutes to complete the test, this means you have &lt;em&gt;two minutes per question&lt;/em&gt;; a score of 72% or better is passing.&lt;/p&gt;

&lt;p&gt;Some questions will require that the test taker &lt;em&gt;select more than one possible answer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The test software will allow you to mark questions and return to them later so if you find that you're spending too much time on something, do the best you can with it, mark it, and move on -- you can return to it later if you have time remaining.&lt;/p&gt;

&lt;p&gt;🎓 Consider using flash cards and when you get a question wrong on a practice test, for example, add the gist of information that you missed framed as a question to the flash card and review it daily. There's significant ground covered so you may have a stack of these eventually.&lt;/p&gt;

&lt;p&gt;I am not the only person to suggest using flash cards — for example, in the article entitled “How I Passed a Cloud Provider Certification Exam in Less Than 3 Weeks” [14] the author, Joshua Feierman, states that “…good old flashcard[s are] actually way more effective than reviewing your notes and highlights. To that end, one of the ways I studied for the [AWS DevOps Engineer Professional] exam was using the free online tool Quizlet, which allows you to create decks of flashcards and use various ways to review them (hint: the “Learn” mode was probably the best method I found)”. In my preparation I used simple paper flash cards so choose what works for you.&lt;/p&gt;

&lt;p&gt;If you find that you are weak on a specific subject then you should spend time reviewing missed questions, covering subject-specific material such as videos on S3 for example, that will help bridge gaps in knowledge, while reviewing your stack of flash cards so that you're constantly re-testing yourself.&lt;/p&gt;

&lt;p&gt;I found that a notebook is only marginally helpful when studying for this exam mainly because the notebook did not help me drill and when it comes to multiple choice tests reviewing material, for me at least, is not as helpful as drilling with that material.&lt;/p&gt;

&lt;p&gt;🎓 Learn to identify answers which are clearly wrong and make sure to understand why.&lt;/p&gt;

&lt;p&gt;🎓 Identify answers to questions which were answered correctly &lt;em&gt;while not fully understanding why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This is an important point when reviewing the results of a practice exam: it is important to understand why a question was answered incorrectly but that should not be the only focus because there will likely be guesses which are correct and it will behoove you as much to study these questions as well.&lt;/p&gt;

&lt;p&gt;When I took practice exams I would write on paper which questions I had to guess on so I knew which ones to pay particular attention to once the results were available.&lt;/p&gt;

&lt;p&gt;🎓 At some point you'll have to go for it and see how you do so good luck!&lt;/p&gt;

&lt;p&gt;🎯 Once I passed the AWS solutions architect associate exam I received a 50% off voucher for recertification or any other exam.&lt;/p&gt;

&lt;p&gt;If you've passed this exam &amp;amp; have additional suggestions to add, please include them in the comments.&lt;/p&gt;

&lt;p&gt;This article has been &lt;a href="https://www.linkedin.com/posts/thomasfuller_aws-experience-google-activity-6588088095692902400-0d2o" rel="noopener noreferrer"&gt;reposted from LinkedIn&lt;/a&gt; -- feel free to add your thoughts below, or on LinkedIn. And feel free to &lt;a href="https://www.linkedin.com/in/thomasfuller/" rel="noopener noreferrer"&gt;send me an invitation to connect&lt;/a&gt;, if you'd like to network.&lt;/p&gt;

&lt;h1&gt;
  
  
  See Also
&lt;/h1&gt;

&lt;p&gt;1.) &lt;a href="https://dev.to/coherentlogic/five-tips-for-passing-the-aws-machine-learning-specialty-exam-a-data-scientist-perspective-452h"&gt;Five tips for passing the AWS Machine Learning specialty exam - A data scientist perspective&lt;/a&gt;&lt;br&gt;
2.) &lt;a href="https://aws.amazon.com/certification/certified-solutions-architect-associate/" rel="noopener noreferrer"&gt;AWS Certified Solutions Architect – Associate&lt;/a&gt;&lt;br&gt;
3.) &lt;a href="https://aws.amazon.com/certification/certification-prep/" rel="noopener noreferrer"&gt;Prepare for Your AWS Certification Exam&lt;/a&gt;&lt;br&gt;
4.) &lt;a href="https://d1.awsstatic.com/training-and-certification/docs/AWS_Certified_Solutions_Architect_Associate_Sample_Questions.pdf" rel="noopener noreferrer"&gt;AWS Solutions Architect – Associate (SAA-C01)&lt;br&gt;
Sample Exam Questions&lt;/a&gt;&lt;br&gt;
5.) &lt;a href="https://digitalcloud.training/quizzes/aws-certified-solutions-architect-associate-free-practice-questions/" rel="noopener noreferrer"&gt;AWS CERTIFIED SOLUTIONS ARCHITECT ASSOCIATE FREE PRACTICE QUESTIONS&lt;/a&gt;&lt;br&gt;
6.) &lt;a href="https://aws.amazon.com/training/course-descriptions/exam-workshop-solutions-architect-associate/" rel="noopener noreferrer"&gt;Exam Readiness: AWS Certified Solutions Architect - Associate&lt;/a&gt;&lt;br&gt;
7.) &lt;a href="https://dev.to/dietertroy/aws-certified-solutions-architect-associate-study-guide-38c2"&gt;AWS Certified Solutions Architect: Associate study guide&lt;/a&gt;&lt;br&gt;
8.) &lt;a href="http://www.youtube.com/watch?v=76fKNr5YScA" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fimg.youtube.com%2Fvi%2F76fKNr5YScA%2F0.jpg" alt="How I passed the AWS Solutions Architect Associate and Professional Exams on the First Try! Video" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
9.) &lt;a href="http://www.youtube.com/watch?v=yLGTWeC27Gw" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqno3yiivj9xumm4zzqux.jpg" alt="ACloudGuru AWS Exam Tips: Certified Solutions Architect Associate Video" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
10.) &lt;a href="http://www.youtube.com/watch?v=IRacq0cQ64A" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5zlv9dv2impfnet2ur9s.jpg" alt="AWS Certified Solutions Architect Associate - Thoughts, impressions, tips Video" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;
11.) &lt;a href="https://www.udemy.com/course/practice-test-aws-certified-solutions-architect-associate/" rel="noopener noreferrer"&gt;2020 Practice Test AWS Solutions Architect Associate&lt;/a&gt;&lt;br&gt;
12.) &lt;a href="https://www.educationcorner.com/multiple-choice-tests.html" rel="noopener noreferrer"&gt;Multiple-Choice Test Taking Tips and Strategies&lt;/a&gt;&lt;br&gt;
13.) &lt;a href="https://medium.com/avmconsulting-blog/aws-solutions-architect-associate-5f0ab1019b55" rel="noopener noreferrer"&gt;AWS Solutions Architect – Associate: Studying toward your first Amazon Web Services certification&lt;/a&gt;&lt;br&gt;
14.) &lt;a href="https://towardsdatascience.com/how-i-passed-a-cloud-provider-certification-exam-in-less-than-3-weeks-6b0fc65fb3ba" rel="noopener noreferrer"&gt;How I Passed a Cloud Provider Certification Exam in Less Than 3 Weeks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>certification</category>
      <category>amazon</category>
    </item>
    <item>
      <title>The Power of Pair Programming, Pair Rotation, and Mobbing for Extreme Collaboration</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Fri, 17 Jan 2020 20:11:17 +0000</pubDate>
      <link>https://dev.to/coherentlogic/the-power-of-pair-programming-pair-rotation-and-mobbing-for-extreme-collaboration-2c3n</link>
      <guid>https://dev.to/coherentlogic/the-power-of-pair-programming-pair-rotation-and-mobbing-for-extreme-collaboration-2c3n</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Use pair programming, pair rotation, and mobbing to help create a more cohesive team, where information is shared freely amongst the group, and one with a better view of the overall mission of the project.&lt;/p&gt;

&lt;p&gt;I worked on a ten week contract recently with a group of excellent software engineers and one of the strategies of software development that I had the pleasure of experiencing on this gig was the incorporation of &lt;a href="https://en.wikipedia.org/wiki/Pair_programming" rel="noopener noreferrer"&gt;pair programming&lt;/a&gt;, &lt;a href="https://medium.com/@dhavaldoshi/pair-rotation-techniques-e8a88c632b3e" rel="noopener noreferrer"&gt;pair rotation&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Mob_programming" rel="noopener noreferrer"&gt;mobbing&lt;/a&gt; -- the result of this included an impressive amount of work being delivered in a relatively short period of time. It also led to a more cohesive team, one where information flowed freely amongst the group, and one with a better view of the overall &lt;em&gt;mission&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A brief summary of this project is that it was technically challenging work, where we took an existing Java-based monolithic web application and transformed it into an application following a &lt;a href="https://en.wikipedia.org/wiki/Microservices" rel="noopener noreferrer"&gt;microservices architecture&lt;/a&gt; and running in &lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; on &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have encountered pair programming in the past. In 2001 I worked on a project where we chose to follow this technique for developing software and we had an excellent return on investment. Sadly, this rarely shows up on projects I've worked on since then. While I've seen variations of mobbing or mob programming, pair rotation was new.&lt;/p&gt;

&lt;p&gt;A byproduct of working in this manner includes no code ownership, no problem ownership, and there's no single person left struggling with a problem for long periods of time, nor are there gaps in understanding of what or why something was done a certain way, nor was there a need to perform a knowledge transfer exercise at the end of the project because &lt;em&gt;everyone was working on the same thing at the same time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;This way of working is likely to have its detractors [#5, #6, and #7]. Already I can predict that the rebuttal being that if two people are working on the same problem that means that there are two brains doing one thing when they could be doing two -- sure they could but it'll take longer than if two people focus on one thing and then blow through it and start on the next task. Also there are two people who can explain why something was done a certain way, and that's important because people forget, people leave projects, etc. If a single task has one rotation you'll end up with three people who understand what was done.&lt;/p&gt;

&lt;p&gt;One may also assume that switching developers halfway into a problem would slow the whole operation down as well but in my experience this is not the case at all. Firstly we would only rotate one of a two person team off of a task at any one time, and secondly it only took a few minutes for people to get acclimated with where the task was at that point and then start contributing to the solution. Finally, this strategy kept things interesting, allowing developers to work on areas of the application which they may not have had a chance to do if they were focused only on one area of the application for long periods of time, and this strategy also helped to prevent burnout.&lt;/p&gt;

&lt;p&gt;As an aside, we didn't pair for the entire day -- in some cases we would break off and work on something individually and then bring that finding or subtask back to the task at hand and incorporate the result.&lt;/p&gt;

&lt;p&gt;Finally, mobbing really helped to push through particularly difficult pain points and at one point we had five people working towards getting a task resolved. This was an excellent approach as the problem we had required an understanding of a certain framework and we had an expert available on the team. We had the symptoms already identified, we voiced the observations during our daily standup meeting, and when this happened we were able, as a group which now included yet another engineer, to get this problem resolved in under three hours. Compare this with working on this issue in an insular manner or with only a short burst of assistance here and there and it could have easily taken two weeks to get past this issue alone and the task itself was technically challenging.&lt;/p&gt;

&lt;p&gt;All in all this experience was positive and I often left work at the end of the day feeling exhausted but also consistently productive, and that's very important since one is not far from burning out when they're going home day after day feeling exclusively exhausted.&lt;/p&gt;

&lt;p&gt;So have you tried &lt;a href="https://en.wikipedia.org/wiki/Pair_programming" rel="noopener noreferrer"&gt;pair programming&lt;/a&gt;, &lt;a href="https://medium.com/@dhavaldoshi/pair-rotation-techniques-e8a88c632b3e" rel="noopener noreferrer"&gt;pair rotation&lt;/a&gt;, and &lt;a href="https://en.wikipedia.org/wiki/Mob_programming" rel="noopener noreferrer"&gt;mobbing&lt;/a&gt; on any of the projects you've worked on? If so, I'd be interested to hear if your experience reflects what I've written in this article, so please include some comments below. I'd be especially interested in hearing where this hasn't worked, or any problem encountered when introducing this style of working.&lt;/p&gt;

&lt;h1&gt;
  
  
  Addendum
&lt;/h1&gt;

&lt;p&gt;I had the pleasure of chatting with &lt;a href="https://www.linkedin.com/in/benjaminleesmith/" rel="noopener noreferrer"&gt;Benjamin Smith&lt;/a&gt;, a member of &lt;a href="https://ctolunches.com/" rel="noopener noreferrer"&gt;CTO Lunches&lt;/a&gt;, a few days ago and here's what Ben had to say about pair programming:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I've been pairing full time in most of my gigs for the past 10 years...&lt;/p&gt;

&lt;p&gt;Pairing encourages doing the right thing. Most teams see this come out in higher quality code, but it applies to anything. Are you more likely to write that test first when you're by yourself or when your peer is sitting next to you? If testing is difficult for you, you might skip writing the test first or skip writing tests altogether if you are soloing. How about talking to the stakeholders to get a better understanding of what needs to be built rather than just making assumptions and carrying on? Or spending the time to figure out the performance implications of a SQL query rather than just shipping it as is.&lt;/p&gt;

&lt;p&gt;Full time pairing removes your ego. When I'm soloing I occasionally (maybe often) get stumped by simple problems. They're problems that I know I should be able to solve, and I know the solution is going to be face-palm stupid. I will spin my wheels for 15 minutes, then 30, and feel embarrassed when I have to ask for help after 45 minutes. My Ego is what's making me feel embarrassed, and keeping me from asking for help the second I get stuck. With full time pairing, you cannot have any ego. If you get stuck or don't know something, you cannot hide it. You get used to saying "I don't know". And when your pair replies with "I don't know either", you immediately get up and find someone to help the two of you rather than waiting 45 minutes. (as a side note: I don't believe that teams that pair part time, or pair-when-it-makes-sense are able to get rid of the above ego problem).&lt;/p&gt;

&lt;p&gt;When choosing whom will pair with whom on the team, all different match ups are productive. For example you may think that it is always a good idea to keep a junior team member paired with a senior team member, but that's not actually the case. It is equally good to have two junior people pair up and work their way through hard problems on their own.&lt;/p&gt;

&lt;p&gt;Pairing when neither person knows tech stack can be tough. For example: if the codebase is in React, and neither have ever done any React, then you spend your time going through tutorials, and reading documentation. Reading through large amounts of text while pairing is hard since everyone reads at a different speed.&lt;/p&gt;

&lt;p&gt;Those are a few nuggets that immediately come to mind."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://content.pivotal.io/blog/pair-programming-considered-extremely-beneficial" rel="noopener noreferrer"&gt;Pair Programming Considered Extremely Beneficial&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://builttoadapt.io/a-recipe-for-successful-pair-programming-b5eec6611e7" rel="noopener noreferrer"&gt;A Recipe For Successful Pair Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/red-green-refactor/the-pair-programming-skeptic-f751bae6eb3c" rel="noopener noreferrer"&gt;The Pair Programming Skeptic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/podcasts/neha-batra/" rel="noopener noreferrer"&gt;Neha Batra - Pivotal Labs Pair Programming&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://news.ycombinator.com/item?id=2050552" rel="noopener noreferrer"&gt;Where Pair Programming Fails for Me&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mwilden.blogspot.com/2009/11/why-i-dont-like-pair-programming-and.html" rel="noopener noreferrer"&gt;Why I Don't Like Pair Programming (and Why I Left Pivotal)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://mwilden.blogspot.com/2010/12/why-i-love-solo-programming-and-why-i.html" rel="noopener noreferrer"&gt;Why I love solo programming (and why I hated working for Pivotal)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=TzUNGOVrhWs" rel="noopener noreferrer"&gt;2x4 Pair Programming Rotation&lt;/a&gt; (YouTube video)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/pulse/mob-programming-experiment-don-eitel/?lipi=urn%3Ali%3Apage%3Ad_flagship3_pulse_read%3BvtymUSOeQLS02TDSvNlyXA%3D%3D" rel="noopener noreferrer"&gt;Mob Programming - An Experiment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.mitchellakeconsulting.com/news/2014/1/23/pair-programming-leave-your-ego-at-the-door" rel="noopener noreferrer"&gt;Pair Programming – “Leave Your Ego at the Door”&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/better-programming/does-pair-programming-work-189d9bc3aee5" rel="noopener noreferrer"&gt;Does Pair Programming Work?﻿&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>agile</category>
      <category>productivity</category>
      <category>management</category>
      <category>business</category>
    </item>
    <item>
      <title>COBOL is dead...or is it? 😳</title>
      <dc:creator>Thomas P. Fuller</dc:creator>
      <pubDate>Thu, 02 Jan 2020 19:12:14 +0000</pubDate>
      <link>https://dev.to/coherentlogic/cobol-is-dead-or-is-it-4p44</link>
      <guid>https://dev.to/coherentlogic/cobol-is-dead-or-is-it-4p44</guid>
      <description>&lt;p&gt;An acquaintance was surprised to learn recently that the &lt;a href="https://en.wikipedia.org/wiki/COBOL" rel="noopener noreferrer"&gt;COBOL&lt;/a&gt; business programming language, created ~ 1959, was still in use in 2019.&lt;/p&gt;

&lt;p&gt;In fact COBOL is still prolific and won't be going away any time soon, if ever.&lt;/p&gt;

&lt;p&gt;Below are several observations which demonstrate that COBOL is still alive and well today.&lt;/p&gt;

&lt;p&gt;✔️ Companies are still actively hiring COBOL developers [1]. LinkedIn, for example, has 2075 COBOL jobs open in the US today.&lt;br&gt;
✔️ The national average for a senior COBOL developer is ~ $110k [2].&lt;br&gt;
✔️ COBOL has been object oriented since 2002 [3].&lt;br&gt;
✔️ GitHub has 1558 COBOL repositories [4].&lt;br&gt;
✔️ The &lt;a href="https://www.linkedin.com/groups/55779/" rel="noopener noreferrer"&gt;LinkedIn Mainframe Experts Network&lt;/a&gt; has ~ 32k members [5a].&lt;br&gt;
✔️ The &lt;a href="https://www.linkedin.com/groups/910927/" rel="noopener noreferrer"&gt;LinkedIn Mainframe Experts Group&lt;/a&gt;, which includes COBOL, has ~ 47.6k members [5b].&lt;br&gt;
✔️ There are 173 groups in total on LinkedIn which include COBOL.&lt;br&gt;
✔️ Micro Focus offers JVM COBOL support [6].&lt;br&gt;
✔️ The Oracle GraalVM supports COBOL [7].&lt;br&gt;
✔️ The Microsoft Visual Studio 2015 IDE supports COBOL [8].&lt;br&gt;
✔️ COBOL code can be run on AWS Lambda [9].&lt;br&gt;
✔️ Per [10 &amp;amp; 11] 25k+ companies use COBOL.&lt;br&gt;
✔️ In 2017 Reuters calculated that there was still 220bn lines of COBOL code running in production &amp;amp; COBOL systems handled $3 trillion in commerce every day [12].&lt;/p&gt;

&lt;p&gt;If you have additional points please add your thoughts in the comments section.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;[1] &lt;a href="https://enterprisersproject.com/article/2018/11/3-aging-it-specialties-just-won-t-retire" rel="noopener noreferrer"&gt;https://enterprisersproject.com/article/2018/11/3-aging-it-specialties-just-won-t-retire&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://www.ziprecruiter.com/Salaries/Senior-Cobol-Developer-Salary" rel="noopener noreferrer"&gt;https://www.ziprecruiter.com/Salaries/Senior-Cobol-Developer-Salary&lt;/a&gt;&lt;br&gt;
[3] &lt;a href="https://en.wikipedia.org/wiki/COBOL" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/COBOL&lt;/a&gt;&lt;br&gt;
[4] &lt;a href="https://github.com/search?q=cobol" rel="noopener noreferrer"&gt;https://github.com/search?q=cobol&lt;/a&gt;&lt;br&gt;
[5a] &lt;a href="https://www.linkedin.com/groups/55779/" rel="noopener noreferrer"&gt;https://www.linkedin.com/groups/55779/&lt;/a&gt;&lt;br&gt;
[5b] &lt;a href="https://www.linkedin.com/groups/910927/" rel="noopener noreferrer"&gt;https://www.linkedin.com/groups/910927/&lt;/a&gt;&lt;br&gt;
[6] &lt;a href="https://www.microfocus.com/documentation/visual-cobol/VC40/EclWin/GUID-DEAFFCA6-6D75-4AEA-A3B6-6DF0BDCF3E2F.html" rel="noopener noreferrer"&gt;https://www.microfocus.com/documentation/visual-cobol/VC40/EclWin/GUID-DEAFFCA6-6D75-4AEA-A3B6-6DF0BDCF3E2F.html&lt;/a&gt;&lt;br&gt;
[7] &lt;a href="https://www.graalvm.org/uploads/graalvm-language-level-virtualization-oracle-tech-papers.pdf" rel="noopener noreferrer"&gt;https://www.graalvm.org/uploads/graalvm-language-level-virtualization-oracle-tech-papers.pdf&lt;/a&gt;&lt;br&gt;
[8] &lt;a href="https://blogs.msdn.microsoft.com/cdndevs/2015/09/09/visual-studio-2015-now-supports-cobol-and-you-can-make-desktop-and-web-apps-with-it/" rel="noopener noreferrer"&gt;https://blogs.msdn.microsoft.com/cdndevs/2015/09/09/visual-studio-2015-now-supports-cobol-and-you-can-make-desktop-and-web-apps-with-it/&lt;/a&gt;&lt;br&gt;
[9] &lt;a href="https://searchaws.techtarget.com/news/252454023/COBOL-applications-can-go-serverless-on-AWS-Lambda" rel="noopener noreferrer"&gt;https://searchaws.techtarget.com/news/252454023/COBOL-applications-can-go-serverless-on-AWS-Lambda&lt;/a&gt;&lt;br&gt;
[10] &lt;a href="https://enlyft.com/tech/products/cobol}&amp;lt;br&amp;gt;%0A[11]%20[" rel="noopener noreferrer"&gt;"Companies using COBOL"&lt;/a&gt;&lt;br&gt;
[12] &lt;a href="https://thenewstack.io/cobol-everywhere-will-maintain/" rel="noopener noreferrer"&gt;https://thenewstack.io/cobol-everywhere-will-maintain/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cobol</category>
      <category>mainframe</category>
      <category>business</category>
      <category>legacy</category>
    </item>
  </channel>
</rss>
