<?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: Timothy McCallum</title>
    <description>The latest articles on DEV Community by Timothy McCallum (@tpmccallum).</description>
    <link>https://dev.to/tpmccallum</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%2F1202770%2F42db7a8d-6a5b-464b-8f3e-80b9aa604ea7.jpeg</url>
      <title>DEV Community: Timothy McCallum</title>
      <link>https://dev.to/tpmccallum</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tpmccallum"/>
    <language>en</language>
    <item>
      <title>SpinKube: Orchestrating light, fast and efficient WebAssembly (Wasm) workloads in Kubernetes (k8s)</title>
      <dc:creator>Timothy McCallum</dc:creator>
      <pubDate>Wed, 13 Mar 2024 23:16:35 +0000</pubDate>
      <link>https://dev.to/fermyon/spinkube-orchestrating-light-fast-and-efficient-webassembly-wasm-workloads-in-kubernetes-k8s-1iap</link>
      <guid>https://dev.to/fermyon/spinkube-orchestrating-light-fast-and-efficient-webassembly-wasm-workloads-in-kubernetes-k8s-1iap</guid>
      <description>&lt;p&gt;In this article, we touch on technologies that have had a profound impact over the last decade or so and then reveal how &lt;a href="https://www.spinkube.dev/" rel="noopener noreferrer"&gt;SpinKube&lt;/a&gt; has cherry-picked the best parts to provide a way of orchestrating light, fast and efficient Wasm workloads in k8s.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual Machines (VMs)
&lt;/h2&gt;

&lt;p&gt;Using VMs solves several problems compared to running servers directly. By running multiple VMs on a single physical server, we can maximize the use of our hardware infrastructure and reduce costs. Aside from the advantage of better utilisation of hardware resources, VMs also provide us with a level of isolation between different applications sharing the host's hardware. VMs allow us to scale up and down. However, scaling is typically done at the VM level, provisioning more or fewer VMs based on demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Containers
&lt;/h2&gt;

&lt;p&gt;Unlike VMs, containers can run multiple instances on a single host without requiring a separate Operating System (OS) environment for each instance. &lt;/p&gt;

&lt;p&gt;This translates to faster start-up and deployment times compared to VMs. Containers offer horizontal scaling, allowing each application to be distributed across many containers.&lt;/p&gt;

&lt;h2&gt;
  
  
  K8s
&lt;/h2&gt;

&lt;p&gt;K8s is a powerful container orchestration platform. It facilitates horizontal application scaling by automatically distributing containers across multiple nodes and ensures high availability by restarting failed containers or rescheduling them on healthy nodes.&lt;/p&gt;

&lt;p&gt;K8s also offers built-in service discovery and load-balancing mechanisms, allowing applications to discover and communicate with other services within the cluster, making it easier to build complex microservice architectures.&lt;/p&gt;

&lt;p&gt;With continuous monitoring of the health of its containers and nodes, k8s' self-healing capability helps ensure application availability and reliability, making it a popular choice for managing containerized applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overprovisioning
&lt;/h2&gt;

&lt;p&gt;Allocating more resources (CPU, memory, and/or storage) than an application requires goes against the idea of using containers in the first place. Yet overprovisioning is still a common challenge in the container ecosystem; leading to unnecessary costs and resource wastage.&lt;/p&gt;

&lt;p&gt;Efficient orchestration of containers is crucial for optimizing application performance. In today's fast-paced world, ensuring optimal performance and quick application response times is of the utmost importance. &lt;/p&gt;

&lt;p&gt;By minimizing wastage and controlling costs, you can enhance the overall user experience and meet modern users' expectations.&lt;/p&gt;

&lt;p&gt;This is a great segue for discussing cold start times, specifically Spin and Wasm's lightweight and efficient execution model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spin and Wasm
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.fermyon.com/spin" rel="noopener noreferrer"&gt;The Spin framework&lt;/a&gt; leverages the latest developments in the Wasm component model and Wasmtime runtime; designed for fast startup times. Spin is an open-source framework for building and running fast, secure, composable cloud microservices with Wasm. Importantly, in the context of performance, Spin offers several advantages regarding startup times for cloud microservices.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wasm's Lightweight Execution
&lt;/h3&gt;

&lt;p&gt;Wasm is a binary instruction format designed to be compact and efficient. Its lightweight nature allows efficient resource utilization during startup. Spin and Wasm's fast startup times make them well-suited for scalable cloud microservices architectures. Applications can be quickly spun up or down based on demand, allowing for efficient resource allocation and improved scalability. Spin and Wasm perfectly match a container orchestration platform like k8s.&lt;/p&gt;

&lt;h2&gt;
  
  
  SpinKube
&lt;/h2&gt;

&lt;p&gt;SpinKube is a new open-source project that streamlines the experience of developing, deploying, and operating Wasm workloads on K8s. It provides hyper-efficient serverless on K8s powered by Wasm. With SpinKube, you can leverage the advantages of using Wasm for your workloads. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Artifacts are significantly smaller in size compared to container images.&lt;/li&gt;
&lt;li&gt;Artifacts can be quickly fetched over the network and started much faster.&lt;/li&gt;
&lt;li&gt;Substantially fewer resources are required during idle times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to Spin Operator, we can integrate with k8s primitives (DNS, probes, autoscaling, metrics, and many more cloud native and CNCF projects).&lt;/p&gt;

&lt;p&gt;K8s has a large and vibrant ecosystem with many extensions and plugins. It can be easily extended to integrate with other tools and services. Let's look at the open-source projects that comprise the overarching SpinKube GitHub organization.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/spinkube" rel="noopener noreferrer"&gt;SpinKube GitHub organisation&lt;/a&gt; consists of the following individual open-source project repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/spinkube/spin-operator" rel="noopener noreferrer"&gt;Spin Operator&lt;/a&gt; - facilitating the orchestration of Wasm workloads in k8s&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/spinkube/containerd-shim-spin" rel="noopener noreferrer"&gt;Containerd Shim Spin&lt;/a&gt; - the containerd shim implementation for Spin&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/spinkube/spin-plugin-kube" rel="noopener noreferrer"&gt;Spin Kube Plugin&lt;/a&gt; - a Spin plugin for interacting with k8s&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/spinkube/runtime-class-manager" rel="noopener noreferrer"&gt;Runtime Class Manager&lt;/a&gt; - the spiritual successor to the kwasm-operator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Spin operator uses the &lt;a href="https://github.com/kubernetes-sigs/kubebuilder" rel="noopener noreferrer"&gt;Kubebuilder&lt;/a&gt; framework and contains a Spin App Custom Resource Definition (CRD) and controller. It watches Spin App Custom Resources and realizes the desired state in the K8s cluster. Aside from the immediate benefits gained by running Wasm workloads in k8s, additional optimizations such as &lt;a href="https://spinkube.dev/docs/spin-operator/tutorials/scaling-with-hpa" rel="noopener noreferrer"&gt;Horizontal Pod Scaling (HPA)&lt;/a&gt; and &lt;a href="http://spinkube.dev/docs/spin-operator/tutorials/scaling-with-keda" rel="noopener noreferrer"&gt;k8s Event-driven Autoscaling (KEDA) can be achieved&lt;/a&gt; in a pinch. &lt;/p&gt;

&lt;p&gt;SpinKube throws a host of useful functionality into the mix, allowing you to &lt;a href="https://spinkube.dev/docs/spin-operator/tutorials/deploy-on-azure-kubernetes-service" rel="noopener noreferrer"&gt;install Spin Operator on an Azure k8s Service (AKS) cluster to deploy your Spin application&lt;/a&gt; and much more. You can build and push Spin Operator images. Whether &lt;a href="https://spinkube.dev/docs/spin-operator/tutorials/running-locally" rel="noopener noreferrer"&gt;running locally&lt;/a&gt; or &lt;a href="https://spinkube.dev/docs/spin-operator/tutorials/running-on-a-cluster" rel="noopener noreferrer"&gt;on a cluster&lt;/a&gt;, you can be assured that your orchestration of light, fast and efficient Wasm workloads in k8s is optimal.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://spinkube.dev/docs/spin-plugin-kube/installation/" rel="noopener noreferrer"&gt;Spin plugin for k8s&lt;/a&gt; is crafted to augment Spin's capabilities, facilitating the direct execution of Wasm modules within a k8s cluster. It is a specialized tool for integrating k8s with the Spin command-line interface. By collaborating with containerd shims, this plugin enables k8s to oversee and execute Wasm workloads in a manner akin to conventional container tasks.&lt;/p&gt;

&lt;p&gt;The diagram below illustrates application development (using the &lt;code&gt;spin&lt;/code&gt; CLI), workload lifecycle, and runtime management.&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%2F7avaleq98yvb1gsj8cjr.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%2F7avaleq98yvb1gsj8cjr.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more information and documentation, please visit the &lt;a href="https://spinkube.dev/" rel="noopener noreferrer"&gt;SpinKube website&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Pickling Python in the Cloud via WebAssembly</title>
      <dc:creator>Timothy McCallum</dc:creator>
      <pubDate>Thu, 11 Jan 2024 05:24:19 +0000</pubDate>
      <link>https://dev.to/fermyon/pickling-python-in-the-cloud-via-webassembly-115n</link>
      <guid>https://dev.to/fermyon/pickling-python-in-the-cloud-via-webassembly-115n</guid>
      <description>&lt;p&gt;I have just finished publishing an article, "&lt;a href="https://www.fermyon.com/blog/leveraging-python-standard-library-via-webassembly" rel="noopener noreferrer"&gt;Leveraging Python Standard Library via WebAssembly&lt;/a&gt;" and no sooner am I struck with the immediate urge of Pickling Python in the Cloud via WebAssembly (Wasm).&lt;/p&gt;

&lt;p&gt;Writing Wasm-powered serverless applications in Python is irresistible. I love Python, and I love Wasm, so I guess that makes sense.&lt;/p&gt;

&lt;p&gt;With the &lt;a href="https://developer.fermyon.com/spin/v2/install" rel="noopener noreferrer"&gt;latest version of Spin&lt;/a&gt; I can use the &lt;code&gt;spin new&lt;/code&gt; command to scaffold out a new HTTP Python application in seconds:&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating an Application
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;spin new &lt;span class="nt"&gt;-t&lt;/span&gt; http-py
Enter a name &lt;span class="k"&gt;for &lt;/span&gt;your new application: pickling-python
Description: Pickling Python
HTTP path: /...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From there if I change into the application's folder and open the application manifest file (&lt;code&gt;spin.toml&lt;/code&gt;) for editing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;pickling-python
&lt;span class="nv"&gt;$ &lt;/span&gt;vi spin.toml 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I see the following (a pretty straight forward &lt;code&gt;.toml&lt;/code&gt; file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;spin_manifest_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="nn"&gt;[application]&lt;/span&gt;
&lt;span class="py"&gt;authors&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"tpmccallum &amp;lt;tim.mccallum@fermyon.com&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Pickling Python"&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pickling-python"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;

&lt;span class="nn"&gt;[[trigger.http]]&lt;/span&gt;
&lt;span class="py"&gt;route&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/..."&lt;/span&gt;
&lt;span class="py"&gt;component&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pickling-python"&lt;/span&gt;

&lt;span class="nn"&gt;[component.pickling-python]&lt;/span&gt;
&lt;span class="py"&gt;source&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"app.wasm"&lt;/span&gt;
&lt;span class="nn"&gt;[component.pickling-python.build]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"spin py2wasm app -o app.wasm"&lt;/span&gt;
&lt;span class="py"&gt;watch&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.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Pipfile"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding Redis Storage
&lt;/h2&gt;

&lt;p&gt;I want all this processing and pickling in the cloud (e.g., once built and deployed, no processing or storage will be performed locally). For this to become a reality, I go to my &lt;a href="https://app.redislabs.com/" rel="noopener noreferrer"&gt;Redis Cloud&lt;/a&gt; account and copy the credentials of an existing database, e.g. username, password, URL and port.&lt;/p&gt;

&lt;p&gt;I then add the values in the &lt;code&gt;environment&lt;/code&gt; and &lt;code&gt;allowed_outbound_hosts&lt;/code&gt; configurations at the &lt;code&gt;component.pickling-python&lt;/code&gt; "component" level (as shown below):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[component.pickling-python]&lt;/span&gt;
&lt;span class="py"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;REDIS_ADDRESS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"redis://username:password@my-redis-cloud.redislabs.com:16978"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="py"&gt;allowed_outbound_hosts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"redis://my-redis-cloud.redislabs.com:16978"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is &lt;a href="https://developer.fermyon.com/spin/v2/redis-outbound#granting-network-permissions-to-components" rel="noopener noreferrer"&gt;granting network permissions to components&lt;/a&gt; and &lt;a href="https://developer.fermyon.com/spin/v2/python-components#configuration" rel="noopener noreferrer"&gt;Python component configuration&lt;/a&gt; documentation available if you need it. But you should be ok just mirroring what I am doing here (using your credentials, of course).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Python
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;app.py&lt;/code&gt; file in the application directory holds all the Python source code needed. You can open your &lt;code&gt;app.py&lt;/code&gt; and replace it with the following code (if you are following along):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;spin_http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;spin_redis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis_set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;redis_get&lt;/span&gt;

&lt;span class="c1"&gt;# Define a simple example class
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attribute1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attribute2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribute1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attribute1&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribute2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attribute2&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Obtain the Redis address
&lt;/span&gt;    &lt;span class="n"&gt;redis_address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;REDIS_ADDRESS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Read the body of the request
&lt;/span&gt;        &lt;span class="n"&gt;json_str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attribute1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attribute2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;# Create an instance of our ExampleClass using the values from the incoming request
&lt;/span&gt;        &lt;span class="n"&gt;example_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ExampleClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attribute1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;attribute2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="c1"&gt;# Serialize the instance of our ExampleClass and set the  into Redis as a value
&lt;/span&gt;        &lt;span class="nf"&gt;redis_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redis_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example_instance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example_instance&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="c1"&gt;# Fetch the previously stored value from Redis and deserialize the value so we can work with an instance of our class
&lt;/span&gt;        &lt;span class="n"&gt;fetched_instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pickle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;redis_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;redis_address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example_instance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attribute 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fetched_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribute1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attribute 2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fetched_instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attribute2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content-type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text/plain&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="nf"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I will pause a moment and explain what this Python code is doing...&lt;/p&gt;

&lt;p&gt;The code above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;receives a JSON object as part of an incoming request,&lt;/li&gt;
&lt;li&gt;instantiates our &lt;code&gt;ExampleClass&lt;/code&gt; using the JSON object's data,&lt;/li&gt;
&lt;li&gt;uses &lt;code&gt;pickle.dumps&lt;/code&gt; to serialize the instance of the &lt;code&gt;ExampleClass&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;stores the instance as bytes in Redis (with the &lt;code&gt;attribute1&lt;/code&gt; and &lt;code&gt;attribute2&lt;/code&gt; values intact),&lt;/li&gt;
&lt;li&gt;retrieves the bytes back from Redis and deserializes them into the form of our original &lt;code&gt;ExampleClass&lt;/code&gt; instance (with the &lt;code&gt;attribute1&lt;/code&gt; and &lt;code&gt;attribute2&lt;/code&gt; values intact),&lt;/li&gt;
&lt;li&gt;creates a Response object,&lt;/li&gt;
&lt;li&gt;returns a JSON string that describes the correct state of the &lt;code&gt;ExampleClass&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; part is super easy, we just run the following 2 commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;spin build
&lt;span class="nv"&gt;$ &lt;/span&gt;spin deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once deployed, a secure HTTP request from a client can be made. Here is an example of a client's request using the &lt;code&gt;curl&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://dev-to-example-zwirrxzu.fermyon.app/"&lt;/span&gt; &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"attribute1": 123, "attribute2": 456}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà, we get the correct response (as follows):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Attribute 1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Attribute 2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;456&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How did this go for you? You can contact us &lt;a href="https://www.fermyon.com/discord" rel="noopener noreferrer"&gt;on Discord&lt;/a&gt; if you get stuck or have any questions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;In my experience so far, I can use a vast amount of the &lt;a href="https://docs.python.org/3/library/index.html" rel="noopener noreferrer"&gt;Python Standard Library&lt;/a&gt; to build Wasm-powered serverless applications. The caveat I currently understand is that Python’s implementation of TCP and UDP sockets, as well as Python libraries that use threads, processes, and signal handling behind the scenes, will not compile to Wasm. It is worth noting that a similar caveat exists with libraries that I find on &lt;a href="https://pypi.org/" rel="noopener noreferrer"&gt;The Python Package Index (PyPI)&lt;/a&gt; site. While these caveats might limit what can be compiled to Wasm, there are still a ton of extremely powerful libraries to leverage.&lt;/p&gt;

&lt;p&gt;My takeaway is that it is now so easy and quick to develop very powerful serverless web applications using a combination of Python, Spin and Fermyon Cloud. &lt;/p&gt;

&lt;p&gt;What combinations of Python can you think of to launch applications for the web? Perhaps you can develop in tandem with a front-end web developer and create dynamic functionality using a combination of HTML/CSS/Javascript on the client side.&lt;/p&gt;

&lt;p&gt;I hope this inspires you to create something great!&lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.fermyon.com/blog/leveraging-python-standard-library-via-webassembly" rel="noopener noreferrer"&gt;Leveraging Python Standard Library via WebAssembly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;YouTube - &lt;a href="https://www.youtube.com/watch?v=HDyFjn_V0Hs" rel="noopener noreferrer"&gt;Leveraging Python Standard Library via WebAssembly&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.fermyon.com/" rel="noopener noreferrer"&gt;Fermyon Developer Home&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://commons.wikimedia.org/wiki/File:Python_logo_51.svg" rel="noopener noreferrer"&gt;Python logo image attribution&lt;/a&gt; Dnu72, CC BY-SA 4.0 &lt;a href="https://creativecommons.org/licenses/by-sa/4.0" rel="noopener noreferrer"&gt;https://creativecommons.org/licenses/by-sa/4.0&lt;/a&gt;, via Wikimedia Commons&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
