<?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>Forem: Josh Campbell</title>
    <description>The latest articles on Forem by Josh Campbell (@thingengineer).</description>
    <link>https://forem.com/thingengineer</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%2F2143208%2F54f43aea-0c2e-4f6e-8171-3934b889e420.png</url>
      <title>Forem: Josh Campbell</title>
      <link>https://forem.com/thingengineer</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/thingengineer"/>
    <language>en</language>
    <item>
      <title>Unlocking User Data: Building a Secure Supabase Edge Function</title>
      <dc:creator>Josh Campbell</dc:creator>
      <pubDate>Tue, 26 Nov 2024 18:15:13 +0000</pubDate>
      <link>https://forem.com/thingengineer/unlocking-user-data-building-a-secure-supabase-edge-function-bn9</link>
      <guid>https://forem.com/thingengineer/unlocking-user-data-building-a-secure-supabase-edge-function-bn9</guid>
      <description>&lt;p&gt;In this tutorial, we'll delve into the world of Supabase Edge Functions. We'll explore how to set up a local development environment and build a simple function to list all users within your Supabase project. This hands-on guide will empower you to leverage the full potential of Supabase Edge Functions for your next project.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Assuming you have your local Supabase CLI setup and linked to your remote project.&lt;/p&gt;

&lt;p&gt;Make sure Supabase is running with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supabase start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a New Edge Function
&lt;/h2&gt;

&lt;p&gt;Run this to create a new edge function named 'admin-list-all-users':&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supabase functions new admin-list-all-users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a new folder under ./supabase named 'admin-list-all-users' and inside that folder is an index.ts file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Functions Locally
&lt;/h2&gt;

&lt;p&gt;To run functions locally using the CLI, execute this command. Note that this ties up a console window until it is stopped with control + c. While it is running, you can see information about the function calls, and even more if you run it with the --debug flag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supabase functions serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you edit the function, it would be a good idea to run the demo "hello world" code to make sure the basics are working. This code should be in your newly created function already but here it is just in case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Setup type definitions for built-in Supabase Runtime APIs&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsr:@supabase/functions-js/edge-runtime.d.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello from Functions!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!`&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;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Running Your Function Locally
&lt;/h2&gt;

&lt;p&gt;There is also a curl command at the bottom of your index.ts file that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/admin-list-all-users' \
    --header 'Authorization: Bearer SUPABASE_ANON_KEY_HERE' \
    --header 'Content-Type: application/json' \
    --data '{"name":"World"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your SUPABASE_ANON_KEY should be automatically populated with the correct key for your local setup. Copy and paste that to your terminal and run it.&lt;/p&gt;

&lt;p&gt;You should see a response like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"message":"Hello World!"}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Fun Part
&lt;/h2&gt;

&lt;p&gt;Now lets replace the demo code with this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Setup type definitions for built-in Supabase Runtime APIs&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsr:@supabase/functions-js/edge-runtime.d.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import necessary modules with full URLs&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;serve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://deno.land/std@0.168.0/http/server.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://esm.sh/@supabase/supabase-js@2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Access environment variables for Supabase URL and Service Role Key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabaseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPABASE_URL&lt;/span&gt;&lt;span class="dl"&gt;'&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;serviceRoleKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Deno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SUPABASE_SERVICE_ROLE_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&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="c1"&gt;// Initialize the Supabase client with the service role key&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;supabaseUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;serviceRoleKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;serve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_req&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Fetch all users&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listUsers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the list of users as JSON&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;status&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="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Handle errors and return a JSON response&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&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;This will automatically pull your Supabase URL and service role key then return a JSON object containing all users. &lt;/p&gt;

&lt;p&gt;Again, run the function locally like this. Notice that we do not need to pass any data to the function this time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/admin-list-all-users' \
    --header 'Authorization: Bearer SUPABASE_ANON_KEY_HERE' \
    --header 'Content-Type: application/json'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;By following these steps, you've successfully created and tested a Supabase Edge Function locally that can securely access and pass user data to the client. This powerful ability enables you to extend your Supabase application's capabilities without the need for complex server setups. &lt;/p&gt;

&lt;p&gt;Take the next steps and deploy your function to run on your linked (live) Supabase project. Explore the vast possibilities of Edge Functions and leverage them to create secure, innovative and efficient applications by reading the Supabase docs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://supabase.com/docs/guides/functions" rel="noopener noreferrer"&gt;Supabase Edge Functions DOCS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Watch for part 2 where we lock the function down using Supabase Auth.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>typescript</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Intro to Svelte 5: The Compiler-Free Frontend Framework</title>
      <dc:creator>Josh Campbell</dc:creator>
      <pubDate>Mon, 21 Oct 2024 16:45:51 +0000</pubDate>
      <link>https://forem.com/thingengineer/intro-to-svelte-5-the-compiler-free-frontend-framework-bom</link>
      <guid>https://forem.com/thingengineer/intro-to-svelte-5-the-compiler-free-frontend-framework-bom</guid>
      <description>&lt;p&gt;Svelte has carved a unique niche in the frontend framework landscape. Known for its blazing-fast performance and developer-friendly approach, Svelte recently released its highly anticipated version 5. This update boasts exciting new features and improvements that solidify Svelte's position as a compelling choice for modern web development.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Svelte?
&lt;/h2&gt;

&lt;p&gt;Unlike React or Vue, Svelte takes a different approach. It's a component-based framework, but it compiles your code at build time. This means Svelte removes unnecessary parts of your application, resulting in smaller bundle sizes and lightning-fast performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's New in Svelte 5?
&lt;/h2&gt;

&lt;p&gt;Svelte 5 introduces some major improvements, including:&lt;/p&gt;

&lt;p&gt;Runes: This new feature simplifies state management and data manipulation within your components. Runes like $derived and $state make reactivity more intuitive and easier to work with.&lt;br&gt;
Snippets: Svelte 5 allows you to define reusable chunks of markup within your components. This promotes code organization and reduces redundancy.&lt;br&gt;
Improved Reactivity: Svelte 5 streamlines reactivity handling, leading to a more robust and reliable experience for developers.&lt;br&gt;
New Built-in Functions: Gain access to functions like mount and unmount for more granular control over your components' lifecycle.&lt;br&gt;
Benefits of Using Svelte 5:&lt;/p&gt;

&lt;p&gt;Performance: Enjoy the benefits of smaller bundle sizes and incredibly fast runtime performance.&lt;br&gt;
Developer Experience: Svelte is known for its clean syntax and intuitive approach, making it easy to learn and use.&lt;br&gt;
Component-Based Architecture: Structure your application into reusable components for better maintainability and scalability.&lt;br&gt;
Getting Started with Svelte 5:&lt;/p&gt;

&lt;p&gt;Head over to the official Svelte website (svelte.dev) to get started with the framework. You'll find comprehensive documentation, tutorials, and a vibrant community ready to help you on your Svelte journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Svelte 5 Right for You?
&lt;/h2&gt;

&lt;p&gt;If you're looking for a performant, modern, and developer-friendly framework, Svelte 5 is definitely worth considering. Its unique approach and recent improvements offer a compelling alternative to traditional options.&lt;/p&gt;

&lt;p&gt;Dive into Svelte 5 and experience the joy of building lightning-fast web applications!&lt;/p&gt;

&lt;p&gt;The docs are currently a work in progress and you can check out the preview &lt;a href="https://svelte-omnisite.vercel.app" rel="noopener noreferrer"&gt;here&lt;/a&gt;. There are also many great YouTube content creators that can get you started. Here are a few of my personal favorites are.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@JoyofCodeDev" rel="noopener noreferrer"&gt;JoyofCode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/@syntaxfm" rel="noopener noreferrer"&gt;Syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/@Huntabyte" rel="noopener noreferrer"&gt;Huntabyte&lt;/a&gt; - He hasn't had any new content on Svelte 5 in a while, but when he does it will be worth the watch.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How VOLATILE, IMMUTABLE, and STABLE Attributes Affect Functions in Supabase</title>
      <dc:creator>Josh Campbell</dc:creator>
      <pubDate>Wed, 02 Oct 2024 17:48:19 +0000</pubDate>
      <link>https://forem.com/thingengineer/how-volatile-immutable-and-stable-attributes-affect-functions-in-supabase-h79</link>
      <guid>https://forem.com/thingengineer/how-volatile-immutable-and-stable-attributes-affect-functions-in-supabase-h79</guid>
      <description>&lt;p&gt;In Supabase, which is built on PostgreSQL, when you create functions using PL/pgSQL (Procedural Language/PostgreSQL), you have the option to specify the &lt;strong&gt;volatility category&lt;/strong&gt; of each function: &lt;strong&gt;VOLATILE&lt;/strong&gt;, &lt;strong&gt;STABLE&lt;/strong&gt;, or &lt;strong&gt;IMMUTABLE&lt;/strong&gt;. These categories describe how the function interacts with the database, how predictable its output is, and whether it can have side effects. Understanding these distinctions is crucial for writing efficient, safe, and optimized database functions.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Volatility Categories Explained&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1. IMMUTABLE Functions&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition&lt;/strong&gt;: Functions that always return the same result for the same input parameters and have no side effects. They do not read or modify the database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Characteristics&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic&lt;/strong&gt;: Their output depends solely on their input parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Side Effects&lt;/strong&gt;: They cannot access tables, modify database data, or depend on any external state.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Mathematical computations: &lt;code&gt;abs()&lt;/code&gt;, &lt;code&gt;sqrt()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;String manipulations: &lt;code&gt;upper()&lt;/code&gt;, &lt;code&gt;concat()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Usage Notes&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Can be used in index expressions and materialized views.&lt;/li&gt;
&lt;li&gt;The query planner can optimize queries by precomputing or caching results.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;2. STABLE Functions&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition&lt;/strong&gt;: Functions that do not modify the database but can read data. They return consistent results within a single query execution but might return different results in different executions if the underlying data changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Characteristics&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read-Only Access&lt;/strong&gt;: They can read tables or views but not modify them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent Within a Query&lt;/strong&gt;: The function returns the same result throughout a single query execution.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Lookup functions: fetching a value from a table based on an input.&lt;/li&gt;
&lt;li&gt;Functions that depend on the current time (&lt;code&gt;CURRENT_TIMESTAMP&lt;/code&gt; is actually &lt;code&gt;STABLE&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Usage Notes&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Suitable for functions that depend on database data that doesn't change during the query.&lt;/li&gt;
&lt;li&gt;Cannot be used in certain index expressions because the output may change between queries.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;3. VOLATILE Functions&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Definition&lt;/strong&gt;: Functions that can perform any operations, including modifying the database. The results can vary even within a single query execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Characteristics&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Non-Deterministic&lt;/strong&gt;: Results may change for the same inputs at any time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Possible Side Effects&lt;/strong&gt;: Can insert, update, delete data, or perform external actions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Examples&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Functions that generate random values: &lt;code&gt;random()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Functions that read system status: &lt;code&gt;currval()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Functions that modify data: inserting logs, updating records.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Usage Notes&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Cannot be optimized by the query planner.&lt;/li&gt;
&lt;li&gt;Always executed as they appear in the query.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Why Volatility Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The volatility category affects how PostgreSQL (and thus Supabase) handles function execution and query optimization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Performance Optimization&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;The query planner can optimize queries more aggressively with &lt;code&gt;IMMUTABLE&lt;/code&gt; functions, such as by using indexes or caching results.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;STABLE&lt;/code&gt; functions have moderate optimization, while &lt;code&gt;VOLATILE&lt;/code&gt; functions have minimal optimization.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Correctness and Safety&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Misclassifying a function can lead to incorrect results or unintended side effects.&lt;/li&gt;
&lt;li&gt;For example, declaring a function as &lt;code&gt;IMMUTABLE&lt;/code&gt; when it reads database tables could cause the planner to use stale data.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Security and RLS (Row Level Security)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Incorrect volatility classification can affect how RLS policies are enforced.&lt;/li&gt;
&lt;li&gt;Functions that access tables with RLS policies need careful consideration.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Applying Volatility Categories in Supabase Functions&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When creating functions in Supabase, you choose the appropriate volatility based on what your function does:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;When to Use IMMUTABLE&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions that perform calculations or transformations purely based on input parameters.&lt;/li&gt;
&lt;li&gt;Example: A function that converts temperatures from Celsius to Fahrenheit.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not access or modify database tables.&lt;/li&gt;
&lt;li&gt;Ensure that the function's output depends only on its inputs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;When to Use STABLE&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions that read data from the database but do not modify it.&lt;/li&gt;
&lt;li&gt;Example: A function that returns a user's role based on their ID.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safe to read from tables, but writes are not allowed.&lt;/li&gt;
&lt;li&gt;The function's result might change between queries if the underlying data changes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;When to Use VOLATILE&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Functions that modify the database or perform actions that can produce different results even within the same query.&lt;/li&gt;
&lt;li&gt;Example: A function that logs actions to a table or generates random numbers.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Considerations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Necessary for functions with side effects.&lt;/li&gt;
&lt;li&gt;Accept that minimal query optimization will occur.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Examples&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;IMMUTABLE Function Example&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;add_numbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="k"&gt;IMMUTABLE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: This function simply adds two numbers. It doesn't access the database, so it's &lt;code&gt;IMMUTABLE&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;STABLE Function Example&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;get_user_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="k"&gt;SQL&lt;/span&gt; &lt;span class="k"&gt;STABLE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
  &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&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_id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: The function reads from the &lt;code&gt;users&lt;/code&gt; table but doesn't modify any data. It's &lt;code&gt;STABLE&lt;/code&gt; because it might return different emails if the &lt;code&gt;users&lt;/code&gt; table changes between queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;VOLATILE Function Example&lt;/strong&gt;
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;record_page_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="n"&gt;VOID&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt; &lt;span class="k"&gt;VOLATILE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;page_views&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;viewed_at&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Explanation&lt;/strong&gt;: This function inserts a new record into the &lt;code&gt;page_views&lt;/code&gt; table, modifying the database. It's &lt;code&gt;VOLATILE&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Impact on Query Planning and Optimization&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;IMMUTABLE Functions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can be evaluated at plan time if inputs are constants.&lt;/li&gt;
&lt;li&gt;Can be used in index expressions and indexed searches.&lt;/li&gt;
&lt;li&gt;Example: An index on &lt;code&gt;LOWER(email)&lt;/code&gt; allows for case-insensitive searches using an &lt;code&gt;IMMUTABLE&lt;/code&gt; function.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;STABLE Functions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evaluated once per query execution when used in a query.&lt;/li&gt;
&lt;li&gt;Cannot be used in index expressions.&lt;/li&gt;
&lt;li&gt;The planner assumes they return the same result during a single query.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;VOLATILE Functions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Evaluated every time they are called in the query.&lt;/li&gt;
&lt;li&gt;No assumptions are made about the result consistency.&lt;/li&gt;
&lt;li&gt;Can't be optimized or pre-evaluated.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Security Considerations in Supabase&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Row Level Security (RLS)&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;RLS policies can call functions to determine access rights.&lt;/li&gt;
&lt;li&gt;Functions used in RLS should typically be &lt;code&gt;STABLE&lt;/code&gt; or &lt;code&gt;IMMUTABLE&lt;/code&gt; to ensure consistent behavior during policy enforcement.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Function Privileges&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Be cautious with &lt;code&gt;SECURITY DEFINER&lt;/code&gt; functions, which run with the privileges of the function's owner.&lt;/li&gt;
&lt;li&gt;Ensure that functions don't unintentionally bypass security checks.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Accurately Declare Volatility&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always declare the correct volatility to match the function's behavior.&lt;/li&gt;
&lt;li&gt;Resist the temptation to declare a function as less volatile for potential performance gains if it doesn't match its true behavior.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Avoid Side Effects in STABLE and IMMUTABLE Functions&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not perform write operations or rely on mutable external state.&lt;/li&gt;
&lt;li&gt;Ensure that the function's classification aligns with what it actually does.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Use IMMUTABLE Functions When Possible&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For functions that perform calculations or manipulations without database interaction.&lt;/li&gt;
&lt;li&gt;Allows for better optimization and potential use in indexes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consider Function Dependencies&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If an &lt;code&gt;IMMUTABLE&lt;/code&gt; function calls another function that is &lt;code&gt;STABLE&lt;/code&gt; or &lt;code&gt;VOLATILE&lt;/code&gt;, the volatility must match the most volatile function in the chain.&lt;/li&gt;
&lt;li&gt;PostgreSQL enforces that a function cannot be less volatile than any functions it calls.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test Function Behavior&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify that functions behave as expected, especially when used in complex queries or with RLS policies.&lt;/li&gt;
&lt;li&gt;Check for consistency and correctness in different scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Summary&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;VOLATILE&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use for functions that can change data or whose results can vary unpredictably.&lt;/li&gt;
&lt;li&gt;Example: Functions that insert logs, generate random numbers, or read system variables that change rapidly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;STABLE&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use for read-only functions that query the database but don't modify it.&lt;/li&gt;
&lt;li&gt;Example: Functions that fetch and return data from tables.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;IMMUTABLE&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use for functions that always produce the same output from the same input and have no side effects.&lt;/li&gt;
&lt;li&gt;Example: Pure mathematical functions or deterministic conversions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By correctly categorizing your functions in Supabase, you help the database engine optimize queries effectively and maintain data integrity and security. Accurate volatility declarations ensure that the query planner makes the right assumptions, leading to better performance and reliable application behavior.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Additional Notes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Function Costs and Rows Estimates&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;You can also specify &lt;code&gt;COST&lt;/code&gt; and &lt;code&gt;ROWS&lt;/code&gt; estimates when creating functions, which can further help the query planner.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Updating Function Definitions&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;If you change a function's behavior, remember to update its volatility classification accordingly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Documentation and Maintenance&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Document your functions with comments explaining their purpose and why a particular volatility category was chosen.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;Understanding the differences between &lt;code&gt;VOLATILE&lt;/code&gt;, &lt;code&gt;STABLE&lt;/code&gt;, and &lt;code&gt;IMMUTABLE&lt;/code&gt; functions is essential when working with Supabase's PL/pgSQL functions. By carefully considering how your functions interact with the database and their potential side effects, you can write efficient, secure, and reliable database code.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>plpgsql</category>
      <category>postgres</category>
      <category>database</category>
    </item>
    <item>
      <title>The Great Data Debate: Is It 'Data Is' or 'Data Are'?</title>
      <dc:creator>Josh Campbell</dc:creator>
      <pubDate>Wed, 02 Oct 2024 14:55:11 +0000</pubDate>
      <link>https://forem.com/thingengineer/the-great-data-debate-is-it-data-is-or-data-are-3mo1</link>
      <guid>https://forem.com/thingengineer/the-great-data-debate-is-it-data-is-or-data-are-3mo1</guid>
      <description>&lt;p&gt;Hey folks! Ever stumbled over whether to say "data is" or "data are"? You're not alone. This little conundrum has tripped up many, including me! So, let's dig into why both usages exist and how you can confidently choose the right one for your context.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Origin of the Word "Data"&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Latin Roots:&lt;/strong&gt; The word "data" comes from the Latin plural "datum," meaning "something given" or "a piece of information."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Usage:&lt;/strong&gt; Because "data" is plural, it traditionally takes a plural verb, leading to phrases like "the data are."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Traditional vs. Modern Usage&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Traditional (Plural Noun) Usage&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example Sentences:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;"The data &lt;strong&gt;are&lt;/strong&gt; inconclusive."&lt;/li&gt;
&lt;li&gt;"These data &lt;strong&gt;have&lt;/strong&gt; been analyzed thoroughly."&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Contexts:&lt;/strong&gt; This usage is prevalent in academic, scientific, and statistical writing, where traditional grammar rules are paramount.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Reasoning:&lt;/strong&gt; Since "data" represents multiple pieces of information, the plural verb form makes logical sense.&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Modern (Mass Noun) Usage&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Example Sentences:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;"The data &lt;strong&gt;is&lt;/strong&gt; being processed."&lt;/li&gt;
&lt;li&gt;"This data &lt;strong&gt;shows&lt;/strong&gt; an interesting trend."&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Contexts:&lt;/strong&gt; More common in everyday language, journalism, business communication, and fields like IT and data science.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Reasoning:&lt;/strong&gt; "Data" is often treated as a mass noun (like "information"), representing a collection as a single entity.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why "Data Is" Sounds More Correct to Many&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Language Evolution:&lt;/strong&gt; Language naturally evolves, and "data" as a singular mass noun is part of this evolution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Common Usage:&lt;/strong&gt; Most people encounter "data" collectively, making the singular verb feel more intuitive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Industry Influence:&lt;/strong&gt; In technology and business, the singular usage dominates due to the way these sectors view and handle data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Current Acceptance&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dictionaries and Style Guides:&lt;/strong&gt; Both usages are recognized in many modern dictionaries and style guides:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Merriam-Webster Dictionary:&lt;/strong&gt; Notes that "data" can be singular or plural.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AP Stylebook:&lt;/strong&gt; Leans toward the singular for general usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Chicago Manual of Style:&lt;/strong&gt; Suggests use based on context.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Considerations for Usage&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Audience and Context:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scientific/Academic Writing:&lt;/strong&gt; If writing for a scientific audience, "data are" might be the way to go.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;General/Public Writing:&lt;/strong&gt; "Data is" is widely accepted and often clearer for general audiences.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be consistent throughout your document to avoid confusion.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Clarity:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go with what sounds natural and makes your sentence clear.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Examples Illustrating Both Usages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Plural Usage (Formal/Traditional):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The experimental data &lt;strong&gt;are&lt;/strong&gt; significant and support the hypothesis."&lt;/li&gt;
&lt;li&gt;"All the data &lt;strong&gt;have&lt;/strong&gt; been collected and analyzed."&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Singular Usage (Common/Modern):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"The customer data &lt;strong&gt;is&lt;/strong&gt; stored securely."&lt;/li&gt;
&lt;li&gt;"This data &lt;strong&gt;shows&lt;/strong&gt; a decline in sales over the last quarter."&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Regional Differences&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;American vs. British English:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Both forms are used in both dialects, although British English historically favored the plural form more frequently.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Some People Prefer "Data Are"&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adherence to Tradition:&lt;/strong&gt; Some sticklers for tradition prefer "data are," especially in academic and scientific contexts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Precision:&lt;/strong&gt; Using "data are" can emphasize multiple discrete pieces of information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Both Forms Are Correct:&lt;/strong&gt; Both "data is" and "data are" are grammatically acceptable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Choose Based on Context:&lt;/strong&gt; Decide based on your audience, context, and style guide preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language Evolves:&lt;/strong&gt; The shift towards "data is" reflects the evolution of language.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Additional Notes&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Datum" Usage:&lt;/strong&gt; The singular form "datum" is rarely used in everyday language. Most people say "data point" instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other Similar Words:&lt;/strong&gt; English has several words that transitioned from Latin plurals to mass nouns, such as "agenda" and "media."&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tips for Writers&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check Style Guides:&lt;/strong&gt; If writing professionally, consult your organization's preferred style guide.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mind Verb Agreement:&lt;/strong&gt; Ensure the verb matches your usage of "data."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid Ambiguity:&lt;/strong&gt; If in doubt, rephrase. Instead of "The data are," say "The data set is" or "The results are."&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;So, there you have it! Whether you lean towards "data is" or "data are" depends on your context, audience, and personal preference. Remember, both forms are correct—just pick the one that feels right for you. Happy writing! 📖✍️&lt;/p&gt;

</description>
      <category>english</category>
      <category>grammar</category>
      <category>writing</category>
      <category>language</category>
    </item>
    <item>
      <title>Improve Your PL/pgSQL Performance: Identifying and Resolving Common Bottlenecks</title>
      <dc:creator>Josh Campbell</dc:creator>
      <pubDate>Sun, 29 Sep 2024 19:26:17 +0000</pubDate>
      <link>https://forem.com/thingengineer/improve-your-plpgsql-performance-identifying-and-resolving-common-bottlenecks-5e2o</link>
      <guid>https://forem.com/thingengineer/improve-your-plpgsql-performance-identifying-and-resolving-common-bottlenecks-5e2o</guid>
      <description>&lt;p&gt;Hey folks! If you’re like me, at some point you've probably experienced the frustration of sluggish database performance with PL/pgSQL functions in PostgreSQL. It's a common struggle, but don't worry. I've been down that road and come out the other side with some valuable insights. Today, I want to share some of the most common bottlenecks I've encountered and how I managed to fix them. We'll look at some very brief code examples, both the pitfalls and the solutions so you can learn from my missteps and successes!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Row-by-Row Processing (Slow Loops)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Using loops (&lt;code&gt;FOR&lt;/code&gt;, &lt;code&gt;WHILE&lt;/code&gt;) to iterate over large datasets is like walking when you could be driving. It processes one row at a time, which is a massive time sink.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Inefficient Loop&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;large_table&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
  &lt;span class="n"&gt;PERFORM&lt;/span&gt; &lt;span class="n"&gt;some_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Enter set-based operations! SQL is designed to handle entire sets of data in one swoop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Efficient Set-Based Operation&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;results_table&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;some_function&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="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;large_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Unoptimized SQL Queries Within Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Ever written a query that just drags its feet? It might be missing indexes, full of unnecessary joins, or pulling more data than it needs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Unoptimized Query&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;some_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Always optimize your queries. Index those columns, select only what you need, and keep computations minimal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Optimized Query&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_some_column&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_column&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;specific_column&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;some_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Excessive Context Switching Between PL/pgSQL and SQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Switching back and forth between procedural code and SQL statements? That overhead piles up faster than you might think.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Excessive Context Switching&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
  &lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="s1"&gt;'INSERT INTO results_table VALUES ($1)'&lt;/span&gt; &lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Reduce context switches by combining SQL operations and trimming down procedural code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Reduced Context Switching&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;results_table&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Not Utilizing Function Volatility Properly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Function volatility (IMMUTABLE, STABLE, VOLATILE) isn't just a buzzword. Mislabeling it can trip up PostgreSQL's optimization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Incorrect Volatility&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;slow_func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt;
&lt;span class="k"&gt;IMMUTABLE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="c1"&gt;-- Some complex operation&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Make sure you correctly declare the function's volatility so the query planner can do its thing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Correct Volatility&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;FUNCTION&lt;/span&gt; &lt;span class="n"&gt;optimized_func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;RETURNS&lt;/span&gt; &lt;span class="nb"&gt;integer&lt;/span&gt;
&lt;span class="k"&gt;LANGUAGE&lt;/span&gt; &lt;span class="n"&gt;plpgsql&lt;/span&gt;
&lt;span class="k"&gt;STABLE&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="err"&gt;$$&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="c1"&gt;-- Some complex operation&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Overuse of Exception Handling
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Too many exception blocks? They're dragging you down. They add overhead, especially if you’re using them for things that should rarely happen.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Overused Exception Handling&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="c1"&gt;-- some code&lt;/span&gt;
&lt;span class="n"&gt;EXCEPTION&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;others&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
    &lt;span class="c1"&gt;-- handle exception&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Be sparing with exception handling. Keep those blocks as tight as a drum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Optimized Exception Handling&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
  &lt;span class="c1"&gt;-- some code that seldom fails&lt;/span&gt;
&lt;span class="n"&gt;EXCEPTION&lt;/span&gt;
  &lt;span class="k"&gt;WHEN&lt;/span&gt; &lt;span class="n"&gt;unique_violation&lt;/span&gt; &lt;span class="k"&gt;THEN&lt;/span&gt;
    &lt;span class="c1"&gt;-- handle specific exception&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Inefficient Data Type Casting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Frequent casting—especially within loops or big datasets—can feel like dragging weights around.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Inefficient Data Type Casting&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
  &lt;span class="n"&gt;PERFORM&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some_field&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Keep it consistent to avoid unnecessary conversions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Efficient Data Type Usage&lt;/span&gt;
&lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;
  &lt;span class="n"&gt;PERFORM&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;some_field&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt; &lt;span class="n"&gt;LOOP&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. Lack of Proper Indexing on Referenced Tables
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Your queries are only as fast as your indexes. No index? Get ready for those full table scans to bog you down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- No Index&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;some_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Create indexes on columns you frequently query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Indexed Query&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;INDEX&lt;/span&gt; &lt;span class="n"&gt;idx_some_column&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;some_column&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt; 
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;some_column&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'value'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Unnecessary Data Retrieval
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Are you guilty of selecting more data than you need? Join the club. It's a major performance killer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Unnecessary Data Retrieval&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Only grab what you need to get the job done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Streamlined Data Retrieval&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Neglecting to Use Prepared Statements for Dynamic SQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;If you're running the same dynamic SQL over and over, that constant parsing and planning hurts performance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Dynamic SQL Without Preparation&lt;/span&gt;
&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="s1"&gt;'SELECT * FROM '&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;table_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Use prepared statements to cut down on the overhead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- With Prepared Statement&lt;/span&gt;
&lt;span class="k"&gt;PREPARE&lt;/span&gt; &lt;span class="n"&gt;dynamic_stmt&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; 
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;some_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;EXECUTE&lt;/span&gt; &lt;span class="n"&gt;dynamic_stmt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Not Cleaning Up Temporary Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Temporary tables and variables are useful, but if they hang around too long, they start to eat up your resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Unmanaged Temporary Data&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TEMP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;temp_table&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Clean up when you’re done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Properly Managed Temporary Data&lt;/span&gt;
&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TEMP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;temp_table&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;big_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;-- Do something with temp_table&lt;/span&gt;

&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;temp_table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  11. Ignoring Transaction Scope
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Long-running transactions can hold locks and bloat your transaction logs, especially when things get busy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Long Running Transaction&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- lot of operations&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Keep your transactions short and sweet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Short Transaction&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;-- minimal operations&lt;/span&gt;
&lt;span class="k"&gt;COMMIT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  12. Failure to Analyze and Vacuum Tables Regularly
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Outdated statistics lead to poor query plans, and dead tuples bloat your tables. It's not pretty.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Regularly run &lt;code&gt;ANALYZE&lt;/code&gt; and &lt;code&gt;VACUUM&lt;/code&gt; to keep things humming along smoothly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Regular Maintenance&lt;/span&gt;
&lt;span class="k"&gt;ANALYZE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;VACUUM&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  13. Insufficient Hardware Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Issue:
&lt;/h3&gt;

&lt;p&gt;Overloaded CPU, memory, or disk I/O can slow things to a crawl, especially under heavy loads.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution:
&lt;/h3&gt;

&lt;p&gt;Monitor your resource usage and scale up your hardware as needed.&lt;/p&gt;




&lt;p&gt;By staying mindful of these common performance bottlenecks and applying the fixes, I've significantly boosted the efficiency of my PL/pgSQL functions. I hope this helps you as much as it helped me. Happy coding, and may your queries always be fast! 🚀&lt;/p&gt;

</description>
      <category>postgres</category>
      <category>plpgsql</category>
      <category>sql</category>
      <category>performance</category>
    </item>
  </channel>
</rss>
