<?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: Sohail Patel</title>
    <description>The latest articles on DEV Community by Sohail Patel (@sohail_patel_8260c837de75).</description>
    <link>https://dev.to/sohail_patel_8260c837de75</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4172007%2F52497914-973a-4f9b-919c-0825c2167bd7.jpg</url>
      <title>DEV Community: Sohail Patel</title>
      <link>https://dev.to/sohail_patel_8260c837de75</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sohail_patel_8260c837de75"/>
    <language>en</language>
    <item>
      <title>Building Dhunzza: How I Built a Modern Music Streaming</title>
      <dc:creator>Sohail Patel</dc:creator>
      <pubDate>Thu, 08 Oct 2026 19:28:15 +0000</pubDate>
      <link>https://dev.to/sohail_patel_8260c837de75/building-dhunzza-how-i-built-a-modern-music-streaming-4abm</link>
      <guid>https://dev.to/sohail_patel_8260c837de75/building-dhunzza-how-i-built-a-modern-music-streaming-4abm</guid>
      <description>&lt;h1&gt;
  
  
  Building Dhunzza: How I Built a Modern Music Streaming Platform with Next.js, Cloudflare D1 &amp;amp; R2
&lt;/h1&gt;

&lt;p&gt;I recently built &lt;strong&gt;Dhunzza&lt;/strong&gt;, a music streaming platform focused on discovering music through moods and different musical eras.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Live project:&lt;/strong&gt; &lt;a href="https://dhunzza.in/" rel="noopener noreferrer"&gt;https://dhunzza.in/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the interesting part wasn't building the music player.&lt;/p&gt;

&lt;p&gt;The real challenge was figuring out how to handle &lt;strong&gt;music metadata, media files, user requests, and database traffic efficiently&lt;/strong&gt; without creating unnecessary infrastructure costs.&lt;/p&gt;

&lt;p&gt;This post explains some of the architectural decisions behind Dhunzza and what I learned while building it.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqidl0tjtyrrtlsnxlzfz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqidl0tjtyrrtlsnxlzfz.png" alt=" " width="799" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7hd32iteooxrx6nibe1.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv7hd32iteooxrx6nibe1.png" alt=" " width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎧 The Idea Behind Dhunzza
&lt;/h2&gt;

&lt;p&gt;The concept was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Give users a place to discover music based on their mood and the era they want to explore.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of building another complicated streaming application, I wanted the interface to feel simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose a mood → choose an era → press play.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Music playback&lt;/li&gt;
&lt;li&gt;Mood-based discovery&lt;/li&gt;
&lt;li&gt;Era-based discovery&lt;/li&gt;
&lt;li&gt;Song metadata&lt;/li&gt;
&lt;li&gt;Song requests&lt;/li&gt;
&lt;li&gt;Admin music management&lt;/li&gt;
&lt;li&gt;A lightweight user experience&lt;/li&gt;
&lt;li&gt;Scalable media storage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏗️ The Initial Architecture
&lt;/h2&gt;

&lt;p&gt;The first version relied heavily on Firebase services.&lt;/p&gt;

&lt;p&gt;Firebase made development extremely fast, especially for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Realtime data&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Database operations&lt;/li&gt;
&lt;li&gt;File storage&lt;/li&gt;
&lt;li&gt;Rapid prototyping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an early-stage application, this was convenient.&lt;/p&gt;

&lt;p&gt;However, music streaming introduces a different problem.&lt;/p&gt;

&lt;p&gt;Audio files are relatively large compared with normal application data, and playback can generate significant bandwidth and storage activity.&lt;/p&gt;

&lt;p&gt;That made me rethink the architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  ☁️ Moving Media to Cloudflare R2
&lt;/h2&gt;

&lt;p&gt;One of the major changes was separating &lt;strong&gt;application data from media storage&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The architecture became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────┐
                    │    Next.js App  │
                    │     Vercel      │
                    └────────┬────────┘
                             │
                ┌────────────┴────────────┐
                │                         │
                ▼                         ▼
        ┌───────────────┐         ┌───────────────┐
        │ Cloudflare D1 │         │ Cloudflare R2 │
        │   Metadata    │         │ Audio / Media  │
        └───────────────┘         └───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is straightforward:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;D1 stores information about the song.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;R2 stores the actual media.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, a D1 record might contain:&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;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Song"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"artist"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Artist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"album"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Album"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"era"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2000s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mood"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"happy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"audio_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://..."&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;The database doesn't need to contain the actual audio file.&lt;/p&gt;

&lt;p&gt;It only needs to know where the media lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  🗄️ Why Separate Metadata and Media?
&lt;/h2&gt;

&lt;p&gt;This separation makes the system easier to reason about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database
&lt;/h3&gt;

&lt;p&gt;The database handles things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Song title&lt;/li&gt;
&lt;li&gt;Artist&lt;/li&gt;
&lt;li&gt;Album&lt;/li&gt;
&lt;li&gt;Mood&lt;/li&gt;
&lt;li&gt;Era&lt;/li&gt;
&lt;li&gt;Song requests&lt;/li&gt;
&lt;li&gt;Admin information&lt;/li&gt;
&lt;li&gt;Public feed information&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Object Storage
&lt;/h3&gt;

&lt;p&gt;R2 handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MP3 files&lt;/li&gt;
&lt;li&gt;Images&lt;/li&gt;
&lt;li&gt;Other media assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives each service a clear responsibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Keeping the Frontend Fast
&lt;/h2&gt;

&lt;p&gt;Another important consideration was reducing unnecessary requests.&lt;/p&gt;

&lt;p&gt;A music application can easily become request-heavy if every interaction causes another database query.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User opens application
       ↓
Fetch songs
       ↓
User changes mood
       ↓
Fetch songs again
       ↓
User changes era
       ↓
Fetch songs again
       ↓
Player changes song
       ↓
More requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, I wanted to minimize repeated metadata fetching and keep the client responsible for as much local state as possible.&lt;/p&gt;

&lt;p&gt;The goal was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Initial Load
     ↓
Fetch required metadata
     ↓
Cache / maintain client state
     ↓
Reuse existing data
     ↓
Only request what actually changed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes particularly important when the application is continuously playing music.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔄 Handling Song Requests
&lt;/h2&gt;

&lt;p&gt;Dhunzza also includes a song-request workflow.&lt;/p&gt;

&lt;p&gt;Users can submit a request for a song.&lt;/p&gt;

&lt;p&gt;The flow looks roughly 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;User
 │
 ▼
Submit Song Request
 │
 ▼
D1
 │
 ▼
Admin Reviews Request
 │
 ▼
Admin Adds Song
 │
 ▼
Song Metadata → D1
Audio File    → R2
 │
 ▼
Request Completed
 │
 ▼
Public Feed Update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps the workflow separate from the actual music playback system.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 Why Next.js?
&lt;/h2&gt;

&lt;p&gt;Next.js gives me a convenient foundation for the application.&lt;/p&gt;

&lt;p&gt;It provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React-based UI&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Server-side capabilities&lt;/li&gt;
&lt;li&gt;API endpoints&lt;/li&gt;
&lt;li&gt;Deployment flexibility&lt;/li&gt;
&lt;li&gt;Good performance tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend is deployed separately while Cloudflare handles the storage/data layer.&lt;/p&gt;

&lt;p&gt;This separation also means the application isn't tightly coupled to one backend provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 One of the Most Important Lessons
&lt;/h2&gt;

&lt;p&gt;Building a streaming application taught me something important:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't treat every piece of data the same way.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A song title is tiny.&lt;/p&gt;

&lt;p&gt;An audio file can be several megabytes.&lt;/p&gt;

&lt;p&gt;A chat message is temporary.&lt;/p&gt;

&lt;p&gt;A song request has a different lifecycle.&lt;/p&gt;

&lt;p&gt;Trying to put all of these into one system can make the architecture unnecessarily expensive or difficult to scale.&lt;/p&gt;

&lt;p&gt;Instead, I started thinking in terms of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is this data?
       ↓
How often does it change?
       ↓
How large is it?
       ↓
How long should it exist?
       ↓
How frequently will users access it?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those questions helped determine where each type of data should live.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 What's Next for Dhunzza?
&lt;/h2&gt;

&lt;p&gt;Dhunzza is still evolving.&lt;/p&gt;

&lt;p&gt;Some areas I'm exploring include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better music discovery&lt;/li&gt;
&lt;li&gt;More mood categories&lt;/li&gt;
&lt;li&gt;More musical eras&lt;/li&gt;
&lt;li&gt;Improved playlists&lt;/li&gt;
&lt;li&gt;Better caching&lt;/li&gt;
&lt;li&gt;Performance optimization&lt;/li&gt;
&lt;li&gt;Better mobile experience&lt;/li&gt;
&lt;li&gt;More intelligent recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal isn't simply to add more features.&lt;/p&gt;

&lt;p&gt;It's to make the experience of &lt;strong&gt;finding and listening to music&lt;/strong&gt; better.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎵 Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Dhunzza started as a music streaming idea, but building it became an interesting lesson in architecture, storage, performance, and data management.&lt;/p&gt;

&lt;p&gt;The biggest takeaway for me was simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Build the architecture around the behavior of your application, not just the features you want to add.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're interested in checking out the project:&lt;/p&gt;

&lt;p&gt;🎧 &lt;strong&gt;Dhunzza:&lt;/strong&gt; &lt;a href="https://dhunzza.in/" rel="noopener noreferrer"&gt;https://dhunzza.in/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're building a similar application, I'd also love to hear how you're handling media storage, caching, and streaming infrastructure.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tech stack:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Next.js&lt;/code&gt; · &lt;code&gt;React&lt;/code&gt; · &lt;code&gt;Cloudflare D1&lt;/code&gt; · &lt;code&gt;Cloudflare R2&lt;/code&gt; · &lt;code&gt;Vercel&lt;/code&gt; · &lt;code&gt;JavaScript&lt;/code&gt; · &lt;code&gt;Firebase (migration/legacy components)&lt;/code&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
