<?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: Valentin Knabel</title>
    <description>The latest articles on DEV Community by Valentin Knabel (@vknabel).</description>
    <link>https://dev.to/vknabel</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%2F493241%2F6c20798b-de1e-4735-b958-7ac62b467e3c.jpg</url>
      <title>DEV Community: Valentin Knabel</title>
      <link>https://dev.to/vknabel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vknabel"/>
    <language>en</language>
    <item>
      <title>Switching From Let's Encrypt to Actalis</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Mon, 02 Mar 2026 15:41:56 +0000</pubDate>
      <link>https://dev.to/vknabel/switching-from-lets-encrypt-to-actalis-2j6e</link>
      <guid>https://dev.to/vknabel/switching-from-lets-encrypt-to-actalis-2j6e</guid>
      <description>&lt;p&gt;In my ongoing efforts to reduce the reliance on US companies and services, I decided from Let’s Encrypt to the Italian Actalis. Sure, Let’s Encrypt works fine, is non-profit and had a huge impact on today’s internet security, but nonetheless it is still US based and required to comply with US law and government requests. This could also include breaking the chain of trust for certificates while prohibiting to share this information with the public.&lt;/p&gt;

&lt;p&gt;Actalis, on the other hand, complies to European laws, regulations and standards.&lt;/p&gt;

&lt;p&gt;I operate a Kubernetes cluster with &lt;a href="https://cert-manager.io/" rel="noopener noreferrer"&gt;cert-manager&lt;/a&gt; and DNS01 challenges. Actalis provides these too, making the switch fairly easy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an Actalis account.&lt;/li&gt;
&lt;li&gt;Copy your ACME Key ID and the HMAC.&lt;/li&gt;
&lt;li&gt;Create a new secret in Kubernetes with these values.&lt;/li&gt;
&lt;li&gt;Create a new &lt;code&gt;Issuer&lt;/code&gt; or &lt;code&gt;ClusterIssuer&lt;/code&gt; in Kubernetes, referencing the secret created in step 3.&lt;/li&gt;
&lt;li&gt;Reference the new issuer in your &lt;code&gt;Certificate&lt;/code&gt; resources.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
apiVersion: v1
kind: Secret
metadata:
 name: actalis-eab
 namespace: cert-manager
stringData:
 # no trailing `=` in the HMAC
 hmac: "$YOUR_HMAC"

---
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
 name: actalis-prod
spec:
 acme:
 email: "$YOUR_EMAIL"
 server: https://acme-api.actalis.com/acme/directory
 privateKeySecretRef:
 name: actalis-dns01-account-key
 externalAccountBinding:
 keyID: "$YOUR_KEY_ID"
 keySecretRef:
 name: actalis-eab
 key: hmac
 solvers: # if you are switching, just keep it as is
 - dns01: # due to my setup only DNS01 challenges make sense
 cloudflare:
 apiTokenSecretRef:
 name: cloudflare-credentials
 key: api-token

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect, now we’ve got Actalis set up and we can start issuing certificates.&lt;/p&gt;

&lt;p&gt;But there is one downside: Actalis does not support multiple domains per certificate in the free plan. Splitting these into multiple certs and secrets does solve this fairly easily though.&lt;/p&gt;

&lt;p&gt;I understand if this is a deal breaker for some, but in the end, these are just a few lines that are simple and easy to maintain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
 name: first-domain
spec:
 secretName: first-domain-tls
 issuerRef:
 name: actalis-prod
 kind: ClusterIssuer
 dnsNames:
 - first.domain # only one dns name supported
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
 name: second-domain
spec:
 secretName: second-domain-tls
 issuerRef:
 name: actalis-prod
 kind: ClusterIssuer
 dnsNames:
 - second.domain # and here is the second one
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
 name: both-domains
spec:
 # here we need to supply both certs
 tls:
 - secretName: first-domain-tls
 hosts:
 - first.domain
 - secretName: second-domain-tls
 hosts:
 - second.domain
 # the rules stay untouched
 rules:
 - host: first.domain
 http:
 paths:
 - path: /
 pathType: Prefix
 backend:
 service:
 name: service-http
 port:
 name: http
 - host: second.domain
 http:
 paths:
 - path: /
 pathType: Prefix
 backend:
 service:
 name: service-http
 port:
 name: http

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that’s it! For more services and ideas you could get rid of big tech and the US, check out &lt;a href="https://vknabel.com/sovereignity" rel="noopener noreferrer"&gt;Sovereignity&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>privacy</category>
      <category>security</category>
    </item>
    <item>
      <title>The Grand Redesign</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Thu, 26 Feb 2026 21:13:55 +0000</pubDate>
      <link>https://dev.to/vknabel/the-grand-redesign-1mjm</link>
      <guid>https://dev.to/vknabel/the-grand-redesign-1mjm</guid>
      <description>&lt;p&gt;Nine years ago I launched this blog to share some thoughts about software development. Most of the time I have been very strict about content that I posted. If it wasn’t tech, I didn’t post it.&lt;/p&gt;

&lt;p&gt;Over the years my priorities shifted. I even started a new blog to open up a new niche. But in the end I decided to not restrict myself in terms of topics. Let’s see where this leads me to.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it started
&lt;/h2&gt;

&lt;p&gt;Back in February 2017, that’s &lt;em&gt;nine freaking years&lt;/em&gt; ago, I launched this blog. I just picked some template and some static site generator to get started. The blog was built using &lt;a href="https://www.gatsbyjs.com/docs/glossary/static-site-generator/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt; with some simple theme.&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%2Fd020dfajd7c5zhpfz725.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%2Fd020dfajd7c5zhpfz725.png" alt="screenshot of the design in 2017, dark, mostly grey" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with Gatsby
&lt;/h2&gt;

&lt;p&gt;With the years I was increasingly frustrated with Gatsby. I wanted a simple blog, nothing too crazy client side stuff. But essentially that was the focus of Gatsby: web workers and lots of JavaScript.&lt;/p&gt;

&lt;p&gt;When I left day to day web development, I also switched to &lt;a href="https://gohugo.io" rel="noopener noreferrer"&gt;Hugo&lt;/a&gt;. After all the hassle this was a breeze! I picked a new theme that was simple, but less basic and had a touch of color.&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%2Fiva2hsugfeok7xg0cbsb.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%2Fiva2hsugfeok7xg0cbsb.png" alt="screenshot of the new markdown like design in 2022" width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essentially I was pretty happy with my site. But as teased above not with the topics I was writing about. I started a new website &lt;a href="https://vknabel.com/tags/plants" rel="noopener noreferrer"&gt;Aroid Garden&lt;/a&gt; about houseplants, but also lost focus there due to personal reasons. Eventually I sunsetted it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the redesign?
&lt;/h2&gt;

&lt;p&gt;Now I decided to transform my former tech blog to a personal one. If I want to write something down, I don’t want to think about wether the topic fits or not. Writing is a habit that must be built and maintained, but I regularly focus on other stuff than tech.&lt;/p&gt;

&lt;p&gt;Though the markdown-style design just doesn’t fit the new content I want to share. That’s why I decided to go with the redesign. As it’s been a great choice I sticked to Hugo, but couldn’t find a theme that fit my needs, so I rolled my own. For technical details about this site see &lt;a href="https://vknabel.com/colophon" rel="noopener noreferrer"&gt;Colophon&lt;/a&gt;, which will be updated in the future.&lt;/p&gt;

&lt;p&gt;I know there are still some rough edges around the design, but better ship, than procrastinate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the content?
&lt;/h2&gt;

&lt;p&gt;When mixing many topics, it makes sense to provide ways to navigate and filter it more easily.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;refactored the tags that grew over the years (I had &lt;code&gt;go&lt;/code&gt; and &lt;code&gt;golang&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;separate &lt;a href="https://vknabel.com/rss" rel="noopener noreferrer"&gt;RSS feeds&lt;/a&gt; for the blog, library and one for all content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also provide additional content like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a book &lt;a href="https://vknabel.com/library" rel="noopener noreferrer"&gt;library&lt;/a&gt; to share book recommendatations&lt;/li&gt;
&lt;li&gt;a &lt;a href="https://vknabel.com/now" rel="noopener noreferrer"&gt;now&lt;/a&gt; page to share what I’m currently doing&lt;/li&gt;
&lt;li&gt;the &lt;a href="https://vknabel.com/colophon" rel="noopener noreferrer"&gt;colophon&lt;/a&gt; to share technical details about the site&lt;/li&gt;
&lt;li&gt;my list of &lt;a href="https://vknabel.com/projects" rel="noopener noreferrer"&gt;projects&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;and &lt;a href="https://vknabel.com/sovereignity" rel="noopener noreferrer"&gt;sovereignity&lt;/a&gt; to share my efforts to regain control over my data and online presence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also some updated content:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;a href="https://vknabel.com/about" rel="noopener noreferrer"&gt;about&lt;/a&gt; page was just outdated&lt;/li&gt;
&lt;li&gt;I imported the Aroid Garden posts to the &lt;a href="https://vknabel.com/tags/plants" rel="noopener noreferrer"&gt;plants tag&lt;/a&gt;, though the layout isn’t optimized for it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, when you have a look at &lt;a href="https://vknabel.com/" rel="noopener noreferrer"&gt;Home&lt;/a&gt;, you cannot come around to see that my content has changed. And that this is just the beginning.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>webdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>Discontinuing of Projects</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Fri, 02 Jan 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/discontinuing-of-projects-kcb</link>
      <guid>https://dev.to/vknabel/discontinuing-of-projects-kcb</guid>
      <description>&lt;p&gt;Starting with this year, I have decided to discontinue all of my open source projects.&lt;/p&gt;

&lt;p&gt;Most notably this affects my VS Code extensions for Swift. I archieved the reposiroties and requested to deprecate the extensions in the Visual Studio Marketplace.&lt;/p&gt;

&lt;p&gt;Also I decided to stop my work on my toy programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reasoning
&lt;/h2&gt;

&lt;p&gt;Since a few years I shifted my focus from Swift development to Go and Kubernetes and switched my main editor from VS Code to Helix.&lt;/p&gt;

&lt;p&gt;And I found joy in so many different things that can be done without computers. Doing some side projects just isn’t worth the hassle for me anymore.&lt;/p&gt;

&lt;p&gt;Occasionally I will still write some blog posts and update my non-archived repositories.&lt;/p&gt;

</description>
      <category>career</category>
      <category>opensource</category>
      <category>programming</category>
    </item>
    <item>
      <title>Blushlog: Going Virtual</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Sun, 28 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/blushlog-going-virtual-2fho</link>
      <guid>https://dev.to/vknabel/blushlog-going-virtual-2fho</guid>
      <description>&lt;p&gt;A few years ago while I started working on &lt;a href="https://github.com/vknabel/Lithia" rel="noopener noreferrer"&gt;Lithia&lt;/a&gt;, I decided to use whatever takes me to my goal. Getting finished was the primary focus. And I did.&lt;/p&gt;

&lt;p&gt;With &lt;a href="https://github.com/vknabel/blush" rel="noopener noreferrer"&gt;Blush&lt;/a&gt; I want to take less compromise and build a better language. Performance and portability aren’t completely irrelevant anymore.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post is part of a &lt;a href="https://vknabel.com/posts/journey-about-creating-a-new-programming-language/" rel="noopener noreferrer"&gt;Journey about creating a new programming language&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tree Walker
&lt;/h2&gt;

&lt;p&gt;For Lithia I chose to implement a tree walker interpreter. It is simple to implement and easy to understand. The downside is that it’s slow.&lt;/p&gt;

&lt;p&gt;Here the interpreter walks the abstract syntax tree (AST) and executes the program directly. This means that every time a function is called, the AST nodes for that function have to be traversed again.&lt;/p&gt;

&lt;p&gt;In this approach every node in the AST has an &lt;code&gt;evaluate&lt;/code&gt; method that takes the current context as a parameter. The context holds variable bindings and other state information.&lt;/p&gt;

&lt;p&gt;Variables and constants were stored in a map. During every variable access, a lookup with the string name of the variable had to be performed. In case of a miss, a parent context had to be checked as well until the variable was found or the global context was reached.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let a = "global"

func do { =&amp;gt;
 let b = "local"

 print a // lookup "a" in current context -&amp;gt; miss -&amp;gt; lookup "a" in parent context -&amp;gt; hit
 print b // lookup "b" in current context -&amp;gt; hit
}

do // looks up the function "do" and calls it

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally checking the type of a value wasn’t trivial as well as the types had to be looked up by name as well.&lt;/p&gt;

&lt;p&gt;Furthermore Lithia leverages lazy evaluation, which means that expressions are not evaluated until their value is needed. This adds additional overhead as every expression has to be wrapped in a thunk (a parameterless function).&lt;/p&gt;

&lt;p&gt;And this makes the second problem of this clear: everything is hidden behind pointers and in general everything is kind of costly. Not necessarily in terms of complexity, its just slow like hashing strings multiple times per variable access, checking if everything has been evaluated and last but not least it can’t be cached efficiently by the CPU.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bytecode Interpreter
&lt;/h2&gt;

&lt;p&gt;Blush takes a different approach to this. It defines a virtual machine (VM) that executes bytecode instructions. Blush’s VM is stack based, which is comparable for a simple calculator or a deck of cards: each operation works on the topmost elements of the stack.&lt;/p&gt;

&lt;p&gt;The bytecode itself is separated of all constants. Instead these are in a separate array or slice while the bytecode references them by index. In case of the expression &lt;code&gt;40 + 2&lt;/code&gt;, the constant &lt;code&gt;40&lt;/code&gt; is at index &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;2&lt;/code&gt; is at index &lt;code&gt;1&lt;/code&gt;. The human readable bytecode to add these two numbers is then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1 + 2
Cons 0 # Pushes the constant at index 0 (40) onto the stack
Cons 1 # Pushes the constant at index 1 (2) onto the stack
Add
# Result: 42

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The actual bytecode currently looks like this: &lt;code&gt;01 00 00 01 00 01 10&lt;/code&gt;. Neat, huh?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The VM iterates over the bytecode instructions and executes them one by one. Here &lt;code&gt;Cons&lt;/code&gt; loads the constant with the fitting index onto the stack. &lt;code&gt;Add&lt;/code&gt; pops the top two elements from the stack, adds them and pushes the result back onto the stack. That way the stack of the VM grows and shrinks as needed.&lt;/p&gt;

&lt;p&gt;When it comes to variables, the VM uses a different approach as well: each variable gets an index assigned at compile time. That way variable access is just a matter of looking up an index of a single array.&lt;/p&gt;

&lt;p&gt;Now let’s get back to our example from above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let a = "global" // globals[0] = constants[0]

func do() { // functions are constants: constants[1]
 let b = "local" // locals[0] = constants[2]

 print(a) // globals[0]
 print(b) // locals[0]
}

do() // constants[1]()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more string lookups. No more parent contexts. Just direct index access. And the best part of this: the CPU can cache this data much more efficiently.&lt;/p&gt;

&lt;p&gt;What about laziness? Almost everything is now eagerly evaluated. Expressions are evaluated as soon as they are encountered. Though there are a few exceptions like logical operators (&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;) which skip their right hand side if the result is already determined by the left hand side. This is common and does not add much overhead.&lt;/p&gt;

&lt;p&gt;But in Blush globals are still initialized lazily. More on this in a future blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why that hassle?
&lt;/h2&gt;

&lt;p&gt;Interpreters are much easier to implement and to understand. Is this actually worth it?&lt;/p&gt;

&lt;p&gt;Glad you asked! I made some micro benchmarks for Lithia and Blush. In this case I wrote a simple recursive Fibonacci function in both languages and measured the time it takes to compute for several numbers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Microbenchmarks can be misleading and do not reflect real world performance. But as long as we keep all tests as similar as possible, we can get a rough idea of the performance difference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the Lithia version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func fib { n =&amp;gt;
 if (n &amp;lt; 2), n, (fib n - 1) + (fib n - 2)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the Blush version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func fib(n) {
    return if n &amp;lt; 2 {
        n
    } else {
        fib(n-1) + fib(n-2)             
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As both languages are implemented in Go, I used the builtin Go benchmarking for both to keep it as similar as possible.&lt;/p&gt;

&lt;p&gt;And these are the results on my machine:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Repetitions&lt;/th&gt;
&lt;th&gt;Lithia&lt;/th&gt;
&lt;th&gt;Repetitions&lt;/th&gt;
&lt;th&gt;Blush&lt;/th&gt;
&lt;th&gt;Factor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5,338 sec&lt;/td&gt;
&lt;td&gt;1,000,000,000&lt;/td&gt;
&lt;td&gt;0.1101 ns&lt;/td&gt;
&lt;td&gt;4,848,486&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;13,990 sec&lt;/td&gt;
&lt;td&gt;1,000,000,000&lt;/td&gt;
&lt;td&gt;0.2860 ns&lt;/td&gt;
&lt;td&gt;4,891,832&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;36,805 sec&lt;/td&gt;
&lt;td&gt;1,000,000,000&lt;/td&gt;
&lt;td&gt;0.7305 ns&lt;/td&gt;
&lt;td&gt;5,038,386&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;(too long)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;34,238 sec&lt;/td&gt;
&lt;td&gt;(too long)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;When I first saw these results, I had to check if I messed something up. We are comparing seconds with nanoseconds here. That’s why I added another run with &lt;code&gt;fib(40)&lt;/code&gt; for Blush to validate the tests. And they were right. Blush is nearly &lt;em&gt;five million&lt;/em&gt; times faster than Lithia in this case.&lt;/p&gt;

&lt;p&gt;To get some more context, I also measured the Python and Ruby &lt;code&gt;fib(40)&lt;/code&gt; and got around 10 to 17 seconds here. Although these numbers are not accurate and probably estimated too high, they give a rough idea of the performance difference. Blush is multiple times slower than these languages, but still in the same ballpark, while Lithia is outclassed by magnitudes.&lt;/p&gt;

&lt;p&gt;Blush is still in early development. Through optimization, new language features but also additional safe guards the performance profile will change over time. And probably not always for the better. Also this is just a microbenchmark that is not in favor of Lithia. Real world performance might be different. Take these numbers with a grain of salt.&lt;/p&gt;

&lt;p&gt;But yes, this was worth the hassle. In case you are curios about what’s up next or want a nerd talk, feel free to reach out to me &lt;a href="https://mastodon.social/@vknabel" rel="noopener noreferrer"&gt;@mastodon.social@vknabel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devjournal</category>
      <category>programming</category>
      <category>performance</category>
      <category>computerscience</category>
    </item>
    <item>
      <title>Blushlog: A new Beginning</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Tue, 16 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/blushlog-a-new-beginning-ma</link>
      <guid>https://dev.to/vknabel/blushlog-a-new-beginning-ma</guid>
      <description>&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%2Fhwczea86ufgr1tcga243.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%2Fhwczea86ufgr1tcga243.png" alt="The blush logo with an old computer" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a long time of procrastination I finally resumed my work on my new programming language. &lt;a href="https://vknabel.com/posts/the-current-state-of-lithia-after-2-years/" rel="noopener noreferrer"&gt;Back then&lt;/a&gt; I wrote about the current state of &lt;a href="https://github.com/vknabel/lithia" rel="noopener noreferrer"&gt;Lithia&lt;/a&gt; and how I arrived in a dead end regarding the language design. Sure I proposed some large changes, but if a lazy evaluated programming language with a parensless call syntax becomes a strict evaluated programming language with a regular call syntax and multiple additional features, is it still the same &lt;del&gt;boat&lt;/del&gt; … language?&lt;/p&gt;

&lt;p&gt;Literally every line of code would break. That’s why I decided to create a new, currently private, repository for my new programming language called &lt;strong&gt;Blush&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post is part of a &lt;a href="https://vknabel.com/posts/journey-about-creating-a-new-programming-language/" rel="noopener noreferrer"&gt;Journey about creating a new programming language&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What will Blush be like?
&lt;/h2&gt;

&lt;p&gt;Similarly to Lithia, Blush will still be simple, but it will still be much more feature rich than Lithia.&lt;/p&gt;

&lt;p&gt;First to get the boring stuff out of the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blush will be dynamically but strongly typed as Lithia is.&lt;/li&gt;
&lt;li&gt;Blush will be strict evaluated while Lithia is lazy evaluated.&lt;/li&gt;
&lt;li&gt;The call syntax might now look slightly familiar as &lt;code&gt;f(a, b)&lt;/code&gt; instead of &lt;code&gt;f a, b&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Annotations
&lt;/h3&gt;

&lt;p&gt;Regarding the type system Blush adds the new &lt;code&gt;annotation&lt;/code&gt; types to Lithia’s &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;enum&lt;/code&gt; types. An &lt;code&gt;annotation&lt;/code&gt; is declared like a &lt;code&gt;data&lt;/code&gt; type, but can be instantiated with an &lt;code&gt;@&lt;/code&gt; before declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;annotation Countable {
 @Returns(Int)
 length(@Has(Countable) value)
}

@Countable({ v -&amp;gt; v.length })
data Bag {
 @Array items
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In contrast to decorators in other languages, annotations only store data. They cannot change the behavior of functions or types. To use annotations, a new reflection API will be provided.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import reflect

@Returns(Int)
func count(@Has(Countable) value) {
 return reflect.typeOf(value).annotation(Countable).length(value)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The effectively replaces the old but common &lt;a href="https://github.com/vknabel/lithia?tab=readme-ov-file#why-no-interfaces" rel="noopener noreferrer"&gt;witness pattern in Lithia&lt;/a&gt; with a more flexible and powerful system without introducing other new concepts like interfaces.&lt;/p&gt;

&lt;p&gt;As you might have noticed, the new annotations &lt;em&gt;can&lt;/em&gt; but don’t have to be used to provide type hints. In the long term these should be checked by the compiler and fuel the language server to provide better IDE support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Control Flow
&lt;/h3&gt;

&lt;p&gt;In Lithia there were no control flow constructs like &lt;code&gt;if&lt;/code&gt; statements or &lt;code&gt;for&lt;/code&gt; loops except the &lt;code&gt;type&lt;/code&gt; expression. Instead everything was expressed via functions and recursion. This was slow and cumbersome.&lt;/p&gt;

&lt;p&gt;Blush now comes with classic &lt;code&gt;if&lt;/code&gt; and &lt;code&gt;switch&lt;/code&gt; statements as well as &lt;code&gt;for&lt;/code&gt; loops.&lt;code&gt;if&lt;/code&gt; statements will support multiple branches and &lt;code&gt;else if&lt;/code&gt; as well as inline variable declarations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if condition {
 doSomething()
} else if otherCondition {
 doSomethingElse()
} else {
 defaultCase()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;switch&lt;/code&gt; statements will support type matching as well as value matching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;switch value {
case @SomeType:
 doSomething(value)
case 42:
 doSomethingElse()
case _:
 defaultCase()
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;for&lt;/code&gt; loops will support iterating over ranges, arrays, maps and custom iterators and infinite loops with &lt;code&gt;for { }&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for {
 if condition {
 break
 }
}

for i in Range(0, 10) {
 println(i)
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In contrast to other languages, there will also be &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;switch&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt; expressions that can be used inline to assign values. In there only variable declarations and one expression per branch are allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let filtered = for num -&amp;gt; items {
 if num % 13 == 0 {
 break
 } else if num % 2 == 0 &amp;amp;&amp;amp; num % 3 == 0 {
 "fizzbuzz"
 } else if num % 2 == 0 {
 "fizz"
 } else if num % 3 == 0 {
 "buzz"
 } else {
 continue
 }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A few more things
&lt;/h3&gt;

&lt;p&gt;Blush will come with a working package manager out of the box, it will have a new design and mascot (you might have noticed) and in the long term the language server and tooling will be much better and more accurate than Lithia’s.&lt;/p&gt;

&lt;p&gt;A much better performance is also a goal, but don’t expect miracles here. Lithia was just really slow.&lt;/p&gt;

&lt;p&gt;More on all of that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the current state?
&lt;/h2&gt;

&lt;p&gt;As of now, Blush is still in a very early stage. Blush can parse lots of the syntax although large parts are still missing. Though the execution side is still in its infancy and only supports a few basic mathematical operations, arrays, bools, and &lt;code&gt;if&lt;/code&gt; statements and expressions. Variables and functions will be the next big step.&lt;/p&gt;

&lt;p&gt;At the tooling side, the core of the package manager is already present.&lt;/p&gt;

&lt;p&gt;I guess I have quite a long way to go, but I am excited to finally work on a new programming language again. If you want to follow along or want a quick chat, feel free to reach out to me &lt;a href="https://mastodon.social/@vknabel" rel="noopener noreferrer"&gt;@mastodon.social@vknabel&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>compilers</category>
      <category>go</category>
      <category>devlog</category>
    </item>
    <item>
      <title>metalstack.cloud v0.2.1</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Wed, 14 Feb 2024 13:50:53 +0000</pubDate>
      <link>https://dev.to/metalstackcloud/metalstackcloud-v021-2f8a</link>
      <guid>https://dev.to/metalstackcloud/metalstackcloud-v021-2f8a</guid>
      <description>&lt;p&gt;We are excited to announce the latest release of &lt;a href="https://metalstack.cloud/"&gt;metalstack.cloud&lt;/a&gt;, version 0.2.1! This release includes several enhancements, bug fixes, and new features across various components of the metalstack.cloud ecosystem.&lt;br&gt;
From now on, you will find release notes in this part of our documentation section.&lt;/p&gt;

&lt;p&gt;The first new feature of this release is the creation of &lt;a href="https://metalstack.cloud/en/documentation/UserManual#6-api-access"&gt;Access Tokens&lt;/a&gt;.&lt;br&gt;
These allow a safe and secure programmatic access to our APIs. They may only access specific organizations, projects and endpoints. Access tokens created from the web console are only valid for one specific project.&lt;/p&gt;

&lt;p&gt;And beside the &lt;a href="https://github.com/metal-stack-cloud/terraform-provider-metal"&gt;metal terraform provider&lt;/a&gt; we also introduce a new developer tool: the fully featured &lt;a href="https://github.com/metal-stack-cloud/cli"&gt;metalstack.cloud command line interface&lt;/a&gt; which already uses the new access tokens.&lt;/p&gt;

&lt;p&gt;Besides these new features and projects, new patch releases for all &lt;a href="https://metalstack.cloud/en/documentation/UserManual#32-provisioning"&gt;supported Kubernetes&lt;/a&gt; versions from v1.21.6 to v1.26.2 are now available.&lt;/p&gt;

&lt;p&gt;We encourage users to explore these updates and provide feedback. For more detailed information, refer to the individual GitHub repositories linked above.&lt;br&gt;
Thank you for your continued support, and we look forward to delivering more exciting features in future releases!&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>terraform</category>
    </item>
    <item>
      <title>The current state of Lithia after 2 years</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Thu, 18 Jan 2024 16:45:00 +0000</pubDate>
      <link>https://dev.to/vknabel/the-current-state-of-lithia-after-2-years-hk7</link>
      <guid>https://dev.to/vknabel/the-current-state-of-lithia-after-2-years-hk7</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvknabel.com%2Fimages%2Fshared-posts%2Flithia-strelitzia-lush.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvknabel.com%2Fimages%2Fshared-posts%2Flithia-strelitzia-lush.jpeg" title="The name and logo of the Lithia programming language are derived from the Strelitzia nicolai." alt="A Strelizia nicolai with a tiny Lithia logo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In 2021 I started working on the current Go implementation of my own experimental programming language called &lt;a href="https://github.com/vknabel/lithia" rel="noopener noreferrer"&gt;Lithia&lt;/a&gt;. Now it is available in version v0.0.19. Infrequently I also wrote some words about it on this blog. It has been designed to be an experiment, that is able to teach some lessons and that can be fulfilled.&lt;/p&gt;

&lt;p&gt;For a programming language being able to teach lessons, a Standard Library and of course some programs need to exist. Only the experience of its developers can lead to conclusions. Now it’s time to derive those!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post is part of a &lt;a href="https://vknabel.com/posts/journey-about-creating-a-new-programming-language/" rel="noopener noreferrer"&gt;Journey about creating a new programming language&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The current state
&lt;/h2&gt;

&lt;p&gt;But first let’s have a look on the current state of Lithia.&lt;/p&gt;

&lt;p&gt;Lithia has all planned features implemented. You can define &lt;code&gt;data&lt;/code&gt;-structures, &lt;code&gt;enum&lt;/code&gt;s similar to unions, functions, constants, modules and imports, closures, partial application of parameters and lazy evaluation. The standard library currently consists of 19 modules providing base types, helpers around comparisons, strings, results and more, file system access and a micro-framework to write unit tests in and for Lithia. Every module is fully documented and is generated by a Lithia script.&lt;/p&gt;

&lt;p&gt;To declare packages and to make project-based scripts easily accessible, there is the &lt;code&gt;Potfile&lt;/code&gt; (comparable to &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;Package.swift&lt;/code&gt;, &lt;code&gt;go.mod&lt;/code&gt;, &lt;code&gt;Gemfile&lt;/code&gt; &amp;amp; &lt;code&gt;Taskfile&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Although the performance of the Lithia interpreter has largely improved in the early days but it’s still slow and leaves room for improvements.&lt;/p&gt;

&lt;p&gt;Developing Lithia is fueled by the Visual Studio Code extension which relies on the Language Server within the Lithia binary and does not need to be installed separately. It provides syntax highlighting, diagnostics and autocompletion. Additionally to the LSP there is a tree-sitter grammar which can be used in other modern editors.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Developer Experience
&lt;/h2&gt;

&lt;p&gt;Obviously the development experience in such a young programming language doesn’t reach the ease of use of mature ones. But for a scripting it provides decent autocompletion. Though there are no formatters or linters, yet. And currently there is no debugger support, which is a bummer. In practice this at least encourages the use of unit testing.&lt;/p&gt;

&lt;p&gt;Lithia has a dynamic but strict type system, which may lead to runtime errors, which is okay for scripting. But the mix of lazy evaluation often further delays and hides these runtime errors and make debugging unnecessarily hard. Especially when adding concurrency. This needs to change.&lt;/p&gt;

&lt;p&gt;Another option for improvement is the current parens-less call syntax: instead of &lt;code&gt;f(g(x), y)&lt;/code&gt; you write &lt;code&gt;f g x, y&lt;/code&gt;. With great syntax highlighting this is something you get around, but syntax should be self-explanatory.&lt;/p&gt;

&lt;p&gt;What’s also missing is a real package manager although git submodules at least provide a workaround for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In general Lithia as an experiment was successful and lead to really great results. The simplicity but power of the type system is a breeze. But Lithia needs a change. And at its core lazy evaluation needs to be dropped, while the overall tooling should evolve. But what’s still missing is the perfect use case that perfectly fits Lithia’s language features. The upcoming release v0.1.0 should provide answers and solutions for those pain points.&lt;/p&gt;

&lt;p&gt;If you wish, check out the open source repository of &lt;a href="https://github.com/vknabel/lithia" rel="noopener noreferrer"&gt;Lithia&lt;/a&gt;. If you have any questions don’t hesitate to ask me on &lt;a href="https://mastodon.social/@vknabel" rel="noopener noreferrer"&gt;@mastodon.social@vknabel&lt;/a&gt; or join the &lt;a href="https://github.com/vknabel/lithia/discussions" rel="noopener noreferrer"&gt;Lithia discussions&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>lithia</category>
      <category>compilers</category>
      <category>go</category>
    </item>
    <item>
      <title>24hrs format for html inputs in Firefox</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Thu, 17 Aug 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/24hrs-format-for-html-inputs-in-firefox-2fma</link>
      <guid>https://dev.to/vknabel/24hrs-format-for-html-inputs-in-firefox-2fma</guid>
      <description>&lt;p&gt;My system language on my linux machine is set to English, but as a German raised with 24-hour days, I simply cannot wrap my head around to get the 12-hours &lt;code&gt;am&lt;/code&gt;/&lt;code&gt;pm&lt;/code&gt; format intuitively. By the time I learned that &lt;code&gt;am&lt;/code&gt; is in the morning and &lt;code&gt;pm&lt;/code&gt; is in the evening. But when it comes to &lt;code&gt;12:00&lt;/code&gt; as the mid of the day and &lt;code&gt;0:00&lt;/code&gt; in the night, I'm lost.&lt;/p&gt;

&lt;p&gt;Of course I have already set the time format to 24-hours in my system settings (Ubuntu &lt;code&gt;Date &amp;amp; Time &amp;gt; Time Format&lt;/code&gt; set to &lt;code&gt;24-hour&lt;/code&gt;), but Firefox still uses the 12-hours format for html inputs with &lt;code&gt;type="time"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As a solution you open &lt;a href="https://dev.toabout:config"&gt;about:config&lt;/a&gt; and set &lt;code&gt;intl.regional_prefs.use_os_locales&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
Now simple &lt;code&gt;&amp;lt;input type="time"&amp;gt;&lt;/code&gt; will use the 24h format!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Designing and scoping my programming language Lithia</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/designing-and-scoping-my-programming-language-lithia-39h</link>
      <guid>https://dev.to/vknabel/designing-and-scoping-my-programming-language-lithia-39h</guid>
      <description>&lt;p&gt;Once you have decided you want to create your own programming language, you need to create a broader concept. Every programming language is unique in its own way. Your goal is to find out in which way. And you need to find your reason &lt;em&gt;why&lt;/em&gt; you want to create it in the first place.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you want to solve a particular problem?&lt;/li&gt;
&lt;li&gt;Is it for learning purposes?&lt;/li&gt;
&lt;li&gt;For who do you build the language?&lt;/li&gt;
&lt;li&gt;Who should use it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep the answers in mind during the whole design process: they will guide you into the right direction.&lt;/p&gt;

&lt;p&gt;In my case, I designed &lt;a href="https://github.com/vknabel/lithia"&gt;Lithia&lt;/a&gt; for myself to learn and explore all sorts of tooling around programming and to create them myself. And that's also the focus of the language: tooling around itself. Learning by doing is king here.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This blog post is part of a &lt;a href="https://dev.to/posts/journey-about-creating-a-new-programming-language/"&gt;Journey about creating a new programming language&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My initial take on designing Lithia
&lt;/h2&gt;

&lt;p&gt;I really like functional programming, but I value being able to perform changes imperatively when I need to. I like the idea of lazy evaluation and being able to create infinite data structures, but to only execute needed parts. And the stronger your type system is, the more errors can be caught at compile time. Some downsides like verbosity can be reduced by type inference.&lt;/p&gt;

&lt;p&gt;Writing functional algorithms really work well with enumerations where every case may have attributes or associated values. It should also be possible to add scoped methods to already declared classes or data types.&lt;/p&gt;

&lt;p&gt;And generics are great, let‘s stuff generics in there. Great nice language. How long will I take to implement it? Well…, scrap that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let‘s start all over.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every programming language special on its own way. To define each characteristic of it, you not only need to know the language features, but the intentionally missing ones, naming conventions, typical patterns, the standard library and how everything is tied together.&lt;/p&gt;

&lt;p&gt;That all defines the programming language. Everything is a tradeoff. For example, every piece of syntactic sugar makes your language more expressive, but harder to read. Every new feature needs to be learned and understood correctly. And every feature may be used in the wrong places or not at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  What language is worth to implement?
&lt;/h2&gt;

&lt;p&gt;Let‘s be honest: programming languages tend to be on the bigger side of projects and we all have limited time, energy and motivation. And there are plenty of programming languages out there.&lt;/p&gt;

&lt;p&gt;Where does your language fit between all those other already finished languages? Are you solving niche problems? Are you experimenting with new language concepts or are you mixing seemingly unrelated paradigms? And more importantly: why do &lt;strong&gt;you&lt;/strong&gt; want to implement it yourself? Are you able to even finish it? How do you keep your motivation up in the long term?&lt;/p&gt;

&lt;p&gt;If you decided to start working on a compiler or interpreter, be sure to be able to finish it and expect you will be the only one using it.&lt;/p&gt;

&lt;p&gt;So what‘s my case? Lithia does not solve a particular problem, but it enables me to learn about the inner workings of compilers, interpreters and the tooling around it. I want a green field to build all kinds of tooling. And in case there is a limitation or bug, I can fix or embrace and document it. What can be achieved in a specific field is not limited by external factors, only by my time, energy and motivation.&lt;/p&gt;

&lt;h2&gt;
  
  
  It’s about the scope and milestones
&lt;/h2&gt;

&lt;p&gt;We know, the planned Lithia is not going to be able to compete with whole language ecosystems or programming languages that shine through lots of features. I wouldn’t be able to finish it.&lt;/p&gt;

&lt;p&gt;Instead, the scope must be reduced. Even more as the language should be accompanied by tooling, coming with a huge scope increase!&lt;/p&gt;

&lt;p&gt;But great tooling requires meta data like types to operate on and the compiler needs to support all that.&lt;/p&gt;

&lt;p&gt;There need to be compromises.&lt;/p&gt;

&lt;p&gt;And I need continuous wins to keep my motivation high. Once there is a basic implementation, I want to do some simple stuff, while working on a complex subsystem.&lt;/p&gt;

&lt;p&gt;Lithia needs to shine through the absence of many features. Instead it should focus on few key concepts, that support requirements for tooling. And after all, it should be a language I like to program in.&lt;/p&gt;

&lt;p&gt;To sum up, Lithia…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is a simple language with only a few features&lt;/li&gt;
&lt;li&gt;supports tooling&lt;/li&gt;
&lt;li&gt;allows a few quick wins&lt;/li&gt;
&lt;li&gt;is conceptually attracting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lithia is an experiment
&lt;/h2&gt;

&lt;p&gt;I personally prefer mostly functional programming languages with a shot of imperative programming. In that context I also favour lazy over strict evaluation and love currying.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lazy vs strict evaluation:&lt;/strong&gt; expressions will only be evaluated if their value is actually needed in lazy evaluation. With strict evaluation they will always be evaluated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Currying&lt;/strong&gt;: let’s imagine you have a function with two parameters, but you currently have just the first parameter. With currying you can pass just the first one and you will receive a function that accepts the second parameter. Without currying you‘d need to manually create that function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lithia won’t allow direct mutations of variables. There will only be constants. I didn’t want to explicitly forbid any mutations, but at this stage I didn’t know how they fit into the language, yet.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt; lazy evaluation and directly mutating variables might lead to weird behaviour. And what about types of a variable? May they change at any time?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The type system should be easy to bootstrap, but should enable static analysis in the future.&lt;/p&gt;

&lt;p&gt;That’s my baseline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type System
&lt;/h3&gt;

&lt;p&gt;Variables, parameters and functions won't have an explicit type annotation like Java's &lt;code&gt;String name&lt;/code&gt;, Swift's &lt;code&gt;let name: String&lt;/code&gt; or Go's &lt;code&gt;var name string&lt;/code&gt;. If there would be type annotations, Lithia would need to enforce them right from the beginning.&lt;/p&gt;

&lt;p&gt;Instead Lithia should have an easy to bootstrap dynamic type system, that still enables static analysis. The easiest way is not to allow structural manipulation of types.&lt;/p&gt;

&lt;p&gt;How far can we get with type inference?&lt;/p&gt;

&lt;h3&gt;
  
  
  Base Types
&lt;/h3&gt;

&lt;p&gt;There are two basic kinds of types to support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;types like classes and structs with independent properties.&lt;/li&gt;
&lt;li&gt;types like enums that list all possible values. In some languages enums may have associated properties, thus mixing sum and product types.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another aspect are reference and value types and semantics. How should changes propagate through the different parts of your program?&lt;/p&gt;

&lt;p&gt;In Lithia there will be one type with properties called &lt;em&gt;data&lt;/em&gt; without any inheritance or methods like classes have. They will have a list of untyped properties.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Don't worry if upcoming code snippets look unfamiliar – we will cover the syntax in another article.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;data Example {
  firstProperty
  secondProperty
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here is an optimisation for tooling: if you want to store a function within your &lt;em&gt;data&lt;/em&gt;, you can add all its parameters &lt;code&gt;firstProperty param, and, more&lt;/code&gt;. When the tooling and the compiler mature, they can detect errors and improve autocompletion.&lt;/p&gt;

&lt;p&gt;In Lithia, the &lt;em&gt;enum&lt;/em&gt; type breaks with common interpretations. Here an &lt;em&gt;enum&lt;/em&gt; isn’t a direct list of possible values, but a list of possible types, called a union.&lt;/p&gt;

&lt;p&gt;This change from individual values to more generic types should make the currently rather static language feel more dynamic and like a scripting language for lovers of strong typing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The type switch
&lt;/h3&gt;

&lt;p&gt;Now that we have enums, we need to resolve those types. A type switch maps every type to a function. It requires the enum definition and returns a function that receives the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let increaseOptional = type Optional {
  Some: { some =&amp;gt; some.value + 1 },
  None: { none =&amp;gt; none }
}
increaseOptional (Some 1)
increaseOptional None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is to provide functions to work on the enums within one module, that are reusable and higher level. This should reduce the amount of external type switches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standard Library
&lt;/h3&gt;

&lt;p&gt;The stdlib is a great place to get quick wins from once the most basic implementation of the language has been finished.&lt;/p&gt;

&lt;p&gt;In Lithia the interpreter’s responsibility ends early. It defines Strings, Characters, numeric types, Functions and some more basic types.&lt;/p&gt;

&lt;p&gt;The Standard Library called &lt;em&gt;prelude&lt;/em&gt; starts with famous types like Boolean and List.&lt;/p&gt;

&lt;p&gt;In here there are many possibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Docs generation&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;All kinds of basic data manipulations&lt;/li&gt;
&lt;li&gt;And much, much more!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What didn’t make it to Lithia
&lt;/h3&gt;

&lt;p&gt;The list of all features that did not find any place in Lithia is longer than what did. All have their particular reasons and their absence fit into the concept of Lithia. Here are some honorable mentions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interfaces / protocols&lt;/li&gt;
&lt;li&gt;Extensions / adding new methods to existing types&lt;/li&gt;
&lt;li&gt;Methods&lt;/li&gt;
&lt;li&gt;Type casts and direct type testing&lt;/li&gt;
&lt;li&gt;Custom operators&lt;/li&gt;
&lt;li&gt;Overloading&lt;/li&gt;
&lt;li&gt;Variational arguments&lt;/li&gt;
&lt;li&gt;Exceptions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this post, I summarised my take on creating your own programming language. Don’t do it for glory, do it for yourself and the experience you gain.&lt;/p&gt;

&lt;p&gt;Design your scope and concept. Make sure you stay motivated until the end. Don’t hesitate to reevaluate your decisions. Take tiny steps.&lt;/p&gt;

&lt;p&gt;If you wish, check out the open source repository of &lt;a href="https://github.com/vknabel/lithia"&gt;Lithia&lt;/a&gt;. If you have any questions don't hesitate to ask me on &lt;a href="https://mastodon.social/@vknabel"&gt;@mastodon.social@vknabel&lt;/a&gt; or join the &lt;a href="https://github.com/vknabel/lithia/discussions"&gt;Lithia discussions&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>lithia</category>
      <category>compilers</category>
      <category>interpreters</category>
      <category>languages</category>
    </item>
    <item>
      <title>Starting the journey about creating a new programming language</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Fri, 22 Jul 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/starting-the-journey-about-creating-a-new-programming-language-35n6</link>
      <guid>https://dev.to/vknabel/starting-the-journey-about-creating-a-new-programming-language-35n6</guid>
      <description>&lt;p&gt;This is planned to be a series of blog posts about designing and developing my own programming language, where I want to share some pitfalls, my learnings, design decisions, experience and the development process.&lt;/p&gt;

&lt;p&gt;While this series will not teach you how to write your first own programming language on its own, it might be supplementary.&lt;/p&gt;

&lt;p&gt;After years of playing with the idea of writing my own programming language, I finally started. In the past I read books and blog posts about creating my own compiler, and I actually have written some parsers, but I never implemented the whole language itself. I know some theory, but I do not know how to actually apply it in practice.&lt;/p&gt;

&lt;p&gt;I felt stuck between theory and simple proof of concept implementations like creating another Lisp.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in this series?
&lt;/h2&gt;

&lt;p&gt;These are all finished blog posts so far.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/posts/designing-and-scoping-my-language-lithia/"&gt;Designing and scoping my language Lithia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My motivations and background
&lt;/h2&gt;

&lt;p&gt;As soon as I learned programming, I was inspired by all the tooling like linters, editors and the compiler itself. All developed in order to develop. They were those magical blackboxes, that felt beyond everything I could achieve.&lt;/p&gt;

&lt;p&gt;Later I played around with various language features and writing my own standard library replacement for existing languages. Lots of fun, but not productive.&lt;/p&gt;

&lt;p&gt;With the years, I learned new paradigms like object orientation, logical, constraint and functional programming. And beyond those big paradigms, there are many different concepts that define the languages character like the module system, dependencies, inheritance, generics, operator overloading, interfaces, type classes, strong or weak typing, dynamic or static, side-effects, monads and many more.&lt;/p&gt;

&lt;p&gt;I started experimenting with new programming language concepts, mixing a few and thinking about the consequences. How do these features integrate and what does it mean for a different group of features? And which syntax do you need to support the special characteristics?&lt;/p&gt;

&lt;p&gt;For fun, I worked on small libraries and tooling in existing programming language ecosystems. Nothing special or widespread.&lt;br&gt;
I read about compilers and interpreters and even though I implemented small lisp-like languages and custom parsers, I felt like I couldn’t write a compiler on my own.&lt;/p&gt;

&lt;p&gt;I kept the wish to design and create my own programming language from ground up. With tooling. I want to learn every aspect of it. Run into problems. Solve them and gradually increase the maturity of the language, the tooling and the compiler.&lt;/p&gt;

&lt;p&gt;That being said, I don’t want my language to be used in wild, heck I encourage you to &lt;em&gt;not&lt;/em&gt; use it. The journey and what we learn along the way is the treasure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I decided to create yet another programming language and let’s be honest: nobody will ever use it and I’m fine with it. But anyway I will still provide tooling and documentation for it.&lt;/p&gt;

&lt;p&gt;I will update and link all my compiler and language design blog posts here.&lt;/p&gt;

&lt;p&gt;If you wish, check out the open source repository of &lt;a href="https://github.com/vknabel/lithia"&gt;Lithia&lt;/a&gt;. If you have any questions don't hesitate to ask me on &lt;a href="https://mastodon.social/@vknabel"&gt;@mastodon.social@vknabel&lt;/a&gt; or join the &lt;a href="https://github.com/vknabel/lithia/discussions"&gt;Lithia disussions&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>lithia</category>
      <category>compilers</category>
      <category>interpreters</category>
      <category>languages</category>
    </item>
    <item>
      <title>Debugging Swift in VS Code in 2022</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Tue, 08 Feb 2022 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/debugging-swift-in-vs-code-in-2022-4blk</link>
      <guid>https://dev.to/vknabel/debugging-swift-in-vs-code-in-2022-4blk</guid>
      <description>&lt;p&gt;Back in 2019 I wrote an &lt;a href="https://www.vknabel.com/pages/Debugging-Swift-in-VS-Code" rel="noopener noreferrer"&gt;article about how to debug&lt;/a&gt; your Swift Package Manager projects in Visual Studio Code. In late december 2021, the Swift Server Working group released a brand &lt;a href="https://marketplace.visualstudio.com/items?itemName=sswg.swift-lang" rel="noopener noreferrer"&gt;new extension for vscode&lt;/a&gt;, which dramatically improves debugging your Swift code. Especially for linux! Time for an update!&lt;/p&gt;

&lt;p&gt;Running and debugging your targets in Visual Studio Code is not prepared by default. Especially for us Swift developers this might come unexpected, especially in comparison to Xcode. In VS Code we require extensions and configs for this purpose.&lt;/p&gt;

&lt;p&gt;First we need to install the mentioned extension: &lt;a href="https://marketplace.visualstudio.com/items?itemName=sswg.swift-lang" rel="noopener noreferrer"&gt;Swift for Visual Studio Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now let’s create a new project on open it in VS Code!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ swift package init --type executable
Creating executable package: MyProject
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/MyProject/main.swift
Creating Tests/
Creating Tests/MyProjectTests/
Creating Tests/MyProjectTests/MyProjectTests.swift

$ code . # if not found: open -a "Visual Studio Code" .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Swift extension for VS Code will now generate some launch configurations within a &lt;code&gt;.vscode/launch.json&lt;/code&gt; file. It generates release and debug &lt;a href="https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb" rel="noopener noreferrer"&gt;LLDB&lt;/a&gt;-launch-configurations for each target and one launch configuration for each test target. Previously this step would have been manual.&lt;/p&gt;

&lt;p&gt;As we currently have one target &lt;code&gt;MyProject&lt;/code&gt; and one test target &lt;code&gt;MyProjectTests&lt;/code&gt;, we will have the following launch configurations:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_launch_configs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_launch_configs.png" alt="Launch configs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also note, that the &lt;code&gt;preLaunchTask&lt;/code&gt;s have been created, too!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Debug MyProject",
      "program": "${workspaceFolder:MyProject}/.build/debug/MyProject",
      "args": [],
      "cwd": "${workspaceFolder:MyProject}",
      "preLaunchTask": "swift: Build Debug MyProject"
    },
    {
      "type": "lldb",
      "request": "launch",
      "name": "Release MyProject",
      "program": "${workspaceFolder:MyProject}/.build/release/MyProject",
      "args": [],
      "cwd": "${workspaceFolder:MyProject}",
      "preLaunchTask": "swift: Build Release MyProject"
    },
    {
      "type": "lldb",
      "request": "launch",
      "name": "Test MyProject",
      "program": "/Applications/Xcode.app/Contents/Developer/usr/bin/xctest",
      "args": [".build/debug/MyProjectPackageTests.xctest"],
      "cwd": "${workspaceFolder:MyProject}",
      "preLaunchTask": "swift: Build All"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we are ready to start debugging! Let's open &lt;code&gt;Sources/MyProject/main.swift&lt;/code&gt;, and add a breakpoint before executing &lt;code&gt;print("Hello, world!")&lt;/code&gt; by left-clicking the empty space before the line number.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_breakpoint.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_breakpoint.png" alt="Breakpoint in main.swift"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, switch to the &lt;code&gt;Run and Debug&lt;/code&gt; tab on the left, make sure &lt;code&gt;Debug MyProject&lt;/code&gt; is selected, and click the green run button.&lt;/p&gt;

&lt;p&gt;Now your project will be compiled, run and stops at the breakpoint!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_debugging.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.vknabel.com%2Fimages%2FDebugging-Swift-in-VS-Code-in-2022%2Fexample_debugging.png" alt="Stopped at breakpoint in main.swift"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sadly this approach currently does not work when debugging iOS or macOS apps, but Swift Package Manager projects and CLIs work great! I hope you enjoy your increased productivity!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adopting Swift Async Await in Vapor</title>
      <dc:creator>Valentin Knabel</dc:creator>
      <pubDate>Sun, 14 Nov 2021 00:00:00 +0000</pubDate>
      <link>https://dev.to/vknabel/adopting-swift-async-await-in-vapor-4d4b</link>
      <guid>https://dev.to/vknabel/adopting-swift-async-await-in-vapor-4d4b</guid>
      <description>&lt;p&gt;A few months ago Swift 5.5 has been released and made &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; available. And in &lt;a href="https://github.com/vapor/vapor/releases/tag/4.50.0"&gt;4.50.0&lt;/a&gt; Vapor added support for it, too!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;If you are still on Vapor 3, you first need to &lt;a href="https://www.vknabel.com/pages/Upgrading-a-server-side-Swift-project-to-Vapor-4/"&gt;upgrade your server to Vapor 4&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can migrate most usages of Swift NIO's &lt;code&gt;EventLoopFuture&lt;/code&gt; with &lt;code&gt;async&lt;/code&gt;. But we don't have to! This is not a breaking change. I recently performed this upgrade for the server of my app &lt;a href="https://github.com/vknabel/puffery"&gt;Puffery&lt;/a&gt; and as both, the client and the server are open source I will include links to the respective git commits.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;_ &lt;strong&gt;Puffery&lt;/strong&gt; is an app to send messages into channels using Shortcuts or HTTP. This will trigger a push notification to all clients that have subscribed. Within the app you can view your messages and channels._&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I wouldn't recommend to directly replace all occurrences of &lt;code&gt;EventLoopFuture&lt;/code&gt;. If you aren't going to touch specific code paths in a while, there is no need to migrate those. But we'll come back to that later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upgrading to Swift 5.5
&lt;/h2&gt;

&lt;p&gt;If you haven't already, you need to upgrade your Swift Tools Version within your &lt;code&gt;Package.swift&lt;/code&gt;-manifest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="c1"&gt;// swift-tools-version:5.5&lt;/span&gt;
&lt;span class="kd"&gt;import&lt;/span&gt; &lt;span class="kt"&gt;PackageDescription&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a few lines later we need to upgrade to a newer macOS version, because &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; not only requires Swift 5.5, but also macOS 12 Monterey. Make sure you have upgraded accordingly. Otherwise you'd need to work on a linux machine or within a docker container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;Package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"PufferyServer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nv"&gt;platforms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;macOS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;v12&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// upgrade to .v12&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next up, we need to bump our dependencies. As we want to rely on special features of the new Vapor, we explicitly go &lt;code&gt;from: "4.50.0"&lt;/code&gt;. Repeat this with other dependencies like Fluent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;        &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="nv"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;package&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://github.com/vapor/vapor.git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"4.50.0"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// upgrade to 4.50.0&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, to silence a warning, we need to explicitly declare our &lt;code&gt;Run&lt;/code&gt; target as &lt;code&gt;executableTarget&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;    &lt;span class="nv"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executableTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
        &lt;span class="c1"&gt;// ...&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use a Dockerfile, build &lt;code&gt;FROM swift:5.5 as build&lt;/code&gt;. Also if present don't forget to update your &lt;code&gt;.swift-version&lt;/code&gt;-file and your CI.&lt;/p&gt;

&lt;p&gt;Now update your packages using &lt;code&gt;swift package update&lt;/code&gt;. If you use Xcode, also update your dependencies using &lt;code&gt;File &amp;gt; Packages &amp;gt; Update to Latest Package Versions&lt;/code&gt; to keep them in sync. In theory &lt;code&gt;swift build&lt;/code&gt; and &lt;code&gt;swift test&lt;/code&gt; should run without any errors. If it does, fix those and proceed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/vknabel/puffery/commit/1c41e5ae5c49748c1389b4491e03d595e5b0f406"&gt;&lt;code&gt;git commit -am "Upgraded PufferyServer to Swift 5.5"&lt;/code&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopting Async Await
&lt;/h2&gt;

&lt;p&gt;Now that we upgraded our new Swift version and updated our dependencies, let's get started with our migration.&lt;/p&gt;

&lt;p&gt;We will incrementally do tiny steps and migrate every function after another. But it doesn't make sense to migrate all functions immediately. If you haven't touched specific files in a while, there is no need to do so now. A great example are your database migrations. You won't touch them anyways. Just write new ones with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; and you are fine.&lt;/p&gt;

&lt;p&gt;In my opinion, controllers are the easiest place to get started. Later you can tackle migrate &lt;code&gt;Jobs&lt;/code&gt; or &lt;code&gt;ScheduledJob&lt;/code&gt;s. Then your services and your repositories.&lt;/p&gt;

&lt;p&gt;The easiest places to upgrade will most likely be your Fluent queries: there are overloads for &lt;code&gt;.find()&lt;/code&gt; and &lt;code&gt;.all()&lt;/code&gt; to return &lt;code&gt;EventLoopFuture&lt;/code&gt; and &lt;code&gt;async throws&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate the function signature
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;messagesForAllChannels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;messagesForAllChannels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now fix all issues within the function. Then fix the errors of all callers.&lt;/p&gt;

&lt;p&gt;If you temporarily converted invocations of this method from &lt;code&gt;EventLoopFuture&lt;/code&gt; to an async function using &lt;code&gt;.get()&lt;/code&gt;, it is now time to remove it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate Protocol Methods if directly affected
&lt;/h3&gt;

&lt;p&gt;Most protocols need to be prefixed with &lt;code&gt;Async&lt;/code&gt; like &lt;code&gt;AsyncJob&lt;/code&gt; or &lt;code&gt;AsyncScheduledJob&lt;/code&gt;. Then you can replace all function signatures.&lt;/p&gt;

&lt;h3&gt;
  
  
  I need async, but I have an EventLoopFuture
&lt;/h3&gt;

&lt;p&gt;To convert a not yet converted &lt;code&gt;EventLoopFuture&lt;/code&gt;, we call &lt;code&gt;EventLoopFuture&amp;lt;V&amp;gt;.get() async throws -&amp;gt; V&lt;/code&gt;. You can migrate the function later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;theEventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  I need an EventLoopFuture, but I have an async function
&lt;/h3&gt;

&lt;p&gt;Sometimes I decided to keep some function signatures as they were and I did not migrate them. For those cases I created a small helper function to create an &lt;code&gt;EventLoopFuture&lt;/code&gt; from an async task.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;extension&lt;/span&gt; &lt;span class="kt"&gt;EventLoop&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;@escaping&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makePromise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;T&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;promise&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completeWithTask&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;task&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;promise&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;futureResult&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example executing multiple futures in parallel is easy with &lt;code&gt;eventLoop.flatten&lt;/code&gt;, but it's much harder with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate &lt;code&gt;.flatMap&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Migrate &lt;code&gt;.flatMap({ messages in doSomething(messages) })&lt;/code&gt; to &lt;code&gt;let result = try await doSomething(messages).get()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate &lt;code&gt;.flatMapThrowing&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Migrate &lt;code&gt;.flatMapThrowing({ messages in doSomething(messages) })&lt;/code&gt; to &lt;code&gt;let result = try doSomething(messages)&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate &lt;code&gt;eventLoop.flatten&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Executing multiple futures in parallel is easy with &lt;code&gt;eventLoop.flatten&lt;/code&gt;, but it's much harder with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'd recommend to keep this part as is, and to keep this part as &lt;code&gt;EventLoopFuture&lt;/code&gt;. See I need an EventLoopFuture, but I have async.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate &lt;code&gt;.transform(to:)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This is straight forward: use the value directly. Typically you'd return this.&lt;/p&gt;

&lt;p&gt;Sometimes I used &lt;code&gt;transform&lt;/code&gt; within a &lt;code&gt;flatMap&lt;/code&gt; to keep the same return value. Now, just &lt;code&gt;try await&lt;/code&gt; these side effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt;   &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;   &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;   &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Migrate &lt;code&gt;.always(_:)&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;.always&lt;/code&gt; will be executed when an &lt;code&gt;EventLoopFuture&lt;/code&gt; fails and when it succeeds. This is the same behaviour of &lt;code&gt;defer&lt;/code&gt; with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;computeSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;always&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;computeSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;_ &lt;strong&gt;Attention:&lt;/strong&gt; you probably need to move your defer up. Using &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; will likely introduce more return and throw statements which will exit your functions early._&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Returning constant futures
&lt;/h3&gt;

&lt;p&gt;If you currently throw a failing future, just throw the error directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventLoop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="kt"&gt;Abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To replace a succeeding future, return the value directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventLoop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If thee &lt;code&gt;future(error:)&lt;/code&gt; was embedded within a &lt;code&gt;do&lt;/code&gt;-&lt;code&gt;catch&lt;/code&gt; to lift errors to an &lt;code&gt;EventLoopFuture&lt;/code&gt;, you can probably remove the &lt;code&gt;do&lt;/code&gt;-&lt;code&gt;catch&lt;/code&gt; and mark the function as &lt;code&gt;throws&lt;/code&gt; instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test and Commit
&lt;/h3&gt;

&lt;p&gt;Do not forget to regularly run your tests and to keep your project in a green state. From time to time, do some commits.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://github.com/vknabel/puffery/commit/17825477cb1d2709dc16e0669a9b943e2d978fd4"&gt;&lt;code&gt;git commit -am "Use async/await for Vapor"&lt;/code&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real World Examples
&lt;/h2&gt;

&lt;p&gt;In case you need guidance, here are typical examples for Vapor-endpoints. These examples should look familiar.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All code snippets are actual code from Puffery.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example for a Fluent query
&lt;/h3&gt;

&lt;p&gt;This function is part of the &lt;code&gt;SubscriptionRepository&lt;/code&gt;. It is meant to be used from &lt;code&gt;Controllers&lt;/code&gt; to consistently access, filter and sort the channel subscriptions of a user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requireID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$createdAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;descending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;eventLoop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We start by changing the type signature to &lt;code&gt;async throws&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To fix the type errors, we could drop &lt;code&gt;do&lt;/code&gt;-&lt;code&gt;catch&lt;/code&gt; as the new variant is throwing. Previously it wasn't throwing as there is no overload of &lt;code&gt;EventLoopFuture.flatMap&lt;/code&gt; that accepts throwing &lt;code&gt;EventLoopFuture&lt;/code&gt;s. Therefore &lt;code&gt;all(of:)&lt;/code&gt; was required to lift thrown errors to futures.&lt;/p&gt;

&lt;p&gt;As there is no distinction between directly throwing and a query failure with &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; we can get rid of the &lt;code&gt;do&lt;/code&gt;-&lt;code&gt;catch&lt;/code&gt;. And as Fluent has overloads for both &lt;code&gt;EventLoopFuture&lt;/code&gt; and &lt;code&gt;async throws&lt;/code&gt; we're done here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="kt"&gt;Subscription&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;requireID&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(\&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;$createdAt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;descending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example Migrations for simple read-only endpoints
&lt;/h3&gt;

&lt;p&gt;My &lt;code&gt;MessageController&lt;/code&gt; looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kt"&gt;MessageController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;messagesForAllChannels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latestSubscribed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:))&lt;/span&gt;
      &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatMapThrowing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
          &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// other endpoints ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code should be familiar to any Vapor developer. I started migration with the function signature, replaced &lt;code&gt;flatMap&lt;/code&gt; and &lt;code&gt;flatMapThrowing&lt;/code&gt; and inserted the &lt;code&gt;.get()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;messagesForAllChannels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;subs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscriptions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;latestSubscribed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;MessageResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After I migrated my &lt;code&gt;SubscriptionRepository&lt;/code&gt;, I could even get rid of the trailing &lt;code&gt;.get()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Migration for simple write-endpoints
&lt;/h3&gt;

&lt;p&gt;This function's migration path was more complex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;confirmEmailIfNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;EventLoopFuture&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;eventLoop&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;future&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;confirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Confirmation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;confirmation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatMapThrowing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flatMap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;
            &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SendEmailJob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we could completely remove the empty &lt;code&gt;req.eventLoop.future()&lt;/code&gt;. A simple, blank &lt;code&gt;return&lt;/code&gt; statement is enough. And creating models doesn't force us anymore to nest everything one level deeper. We &lt;code&gt;await&lt;/code&gt; the result, but we discard it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight swift"&gt;&lt;code&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;confirmEmailIfNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;throws&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;guard&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;emailAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;confirmation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Confirmation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;emailAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;confirmation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="kt"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;SendEmailJob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Within this post we upgraded our Swift version, Package manifest, docker / CI Swift versions and our dependencies. Then we incrementally migrated portions of our codebase by following a set of rules. What was your migration like? Did you experience any problems?&lt;/p&gt;

&lt;p&gt;If you wish, check out the open source repository of &lt;a href="https://github.com/vknabel/puffery"&gt;Puffery&lt;/a&gt; or check it out on the &lt;a href="https://apps.apple.com/de/app/puffery/id1508776889"&gt;App Store&lt;/a&gt;. If you have any questions or feedback don't hesitate to ask me on twitter &lt;a href="http://twitter.com/vknabel"&gt;@vknabel&lt;/a&gt; or join the &lt;a href="https://github.com/vknabel/puffery/discussions"&gt;Puffery disussions&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>swift</category>
      <category>vapor</category>
      <category>async</category>
      <category>await</category>
    </item>
  </channel>
</rss>
