<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Tech Untethered]]></title><description><![CDATA[All things Tech.]]></description><link>https://techuntethered.com</link><image><url>https://techuntethered.com/img/substack.png</url><title>Tech Untethered</title><link>https://techuntethered.com</link></image><generator>Substack</generator><lastBuildDate>Thu, 07 May 2026 01:11:12 GMT</lastBuildDate><atom:link href="https://techuntethered.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Prateek Jain]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[techuntethered@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[techuntethered@substack.com]]></itunes:email><itunes:name><![CDATA[Prateek Jain]]></itunes:name></itunes:owner><itunes:author><![CDATA[Prateek Jain]]></itunes:author><googleplay:owner><![CDATA[techuntethered@substack.com]]></googleplay:owner><googleplay:email><![CDATA[techuntethered@substack.com]]></googleplay:email><googleplay:author><![CDATA[Prateek Jain]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Claude Opus 4.7 Is Out. Here’s What I Actually Think.]]></title><description><![CDATA[And a harder question about where AI-driven engineering is really going.]]></description><link>https://techuntethered.com/p/claude-opus-47-is-out-heres-what</link><guid isPermaLink="false">https://techuntethered.com/p/claude-opus-47-is-out-heres-what</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Fri, 17 Apr 2026 03:43:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!QBEJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!QBEJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QBEJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 424w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 848w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 1272w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QBEJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png" width="1456" height="1477" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1477,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:878060,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://techuntethered.com/i/194477817?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!QBEJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 424w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 848w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 1272w, https://substackcdn.com/image/fetch/$s_!QBEJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a8f1b13-852f-4f47-8854-2e69a53f404c_2600x2638.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Source: Anthropic</figcaption></figure></div><p>Anthropic released Claude Opus 4.7 this week. The benchmarks look strong &#8212; better coding performance, dramatically improved vision, more reliable long-running tasks, and a model that now verifies its own outputs before reporting back. On paper, it&#8217;s a meaningful upgrade.</p><p>But here&#8217;s my honest reaction: I&#8217;m cautiously interested, not excited.</p><p>Let me explain why &#8212; and what it reveals about a bigger question in AI-driven software engineering.</p><div><hr></div><h2>The Way I Actually Use Opus</h2><p>If you&#8217;ve read my work before, you know I build AI-driven software engineering workflows. And in that context, I&#8217;ve landed on a pattern that works well for me:</p><p><strong>Opus handles the thinking. Sonnet handles the doing.</strong></p><p>When I&#8217;m starting a new feature, I bring Opus in for the hard stuff &#8212; brainstorming approaches, stress-testing assumptions, defining the architecture. This is where raw reasoning quality matters most. A bad plan executed perfectly is still a bad outcome, and Opus is genuinely better at catching the flaws before a line of code is written.</p><p>Then I hand off to Sonnet for code generation and execution. It&#8217;s faster, cheaper, and more than capable of implementing a well-defined plan. The combination works well precisely because each model is doing what it&#8217;s best at.</p><p>This isn&#8217;t just a cost hack. It&#8217;s a philosophy: <strong>AI models, like human team members, should be deployed where their specific strengths create the most leverage.</strong></p><div><hr></div><h2>So Why Am I Not Just Upgrading?</h2><p>Because Opus 4.7 uses more tokens than Opus 4.6.</p><p>Anthropic is transparent about this &#8212; the new tokenizer and increased reasoning at higher effort levels mean the same input can map to roughly 1.0&#8211;1.35&#215; more tokens. Their internal evals suggest the net efficiency is still favourable. Maybe it is. But &#8220;maybe&#8221; isn&#8217;t good enough when you&#8217;re running Opus on your most expensive, most critical tasks.</p><p>Opus has always required intentionality. You can&#8217;t just point it at everything and hope for the best &#8212; you&#8217;ll exhaust your token budget fast. The whole reason my Opus-Sonnet workflow exists is because I learned that lesson the hard way. If 4.7 compounds that constraint without delivering a proportional improvement in output quality, the calculus doesn&#8217;t change &#8212; it gets worse.</p><p>To be clear: I haven&#8217;t tested it enough yet to make a final call. And some of what I&#8217;m reading from early testers &#8212; particularly around long-horizon agentic tasks and self-verification &#8212; is genuinely compelling. But I&#8217;d encourage anyone evaluating this upgrade to resist the benchmark hype and measure what matters to <em>them</em>: cost per useful outcome, not raw capability scores.</p><div><hr></div><h2>The Bigger Picture I&#8217;m Watching</h2><p>Opus 4.7 is one release. The more interesting question it surfaces is: where is all of this actually going?</p><p>Here&#8217;s what I think: the next frontier in AI-driven software engineering isn&#8217;t more powerful individual models &#8212; it&#8217;s smarter orchestration between them.</p><p>We&#8217;re moving from &#8220;which model should I use?&#8221; to &#8220;how do I build a system where the right model handles the right task, automatically?&#8221; The teams winning at this right now aren&#8217;t the ones with the biggest models &#8212; they&#8217;re the ones with the best routing logic, the best context management, and the clearest understanding of where AI adds leverage versus where it burns budget.</p><p>Opus 4.7&#8217;s new <code>xhigh</code> effort level and task budgets (now in public beta) are a step in that direction &#8212; giving developers more control over how much the model reasons on hard problems. That kind of fine-grained control is going to matter a lot as workflows get more complex.</p><p>The models will keep improving. That&#8217;s almost guaranteed. The question is whether your workflows are built to take advantage of that &#8212; or whether you&#8217;re still treating AI as a single, monolithic tool you point at problems and hope for the best.</p><div><hr></div><h2>What I&#8217;ll Be Watching</h2><p>Over the next few weeks I&#8217;ll be running Opus 4.7 on my actual planning and architecture tasks &#8212; the ones where Opus earns its keep. I&#8217;ll share what I find.</p><p>If you&#8217;re doing similar things, I&#8217;d genuinely love to hear how you&#8217;re approaching the cost-quality tradeoff. Hit reply and let me know.</p><div><hr></div><p><em>Until next time.</em></p>]]></content:encoded></item><item><title><![CDATA[How I Use Agentic AI for Development — A Workflow That Actually Holds Up in Production]]></title><description><![CDATA[There&#8217;s a version of &#8220;using AI for development&#8221; that most developers are familiar with: tab-completing a function, asking it to explain an error, maybe generating a boilerplate class.]]></description><link>https://techuntethered.com/p/how-i-use-agentic-ai-for-development</link><guid isPermaLink="false">https://techuntethered.com/p/how-i-use-agentic-ai-for-development</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Mon, 06 Apr 2026 15:26:52 GMT</pubDate><content:encoded><![CDATA[<p></p><p>There&#8217;s a version of &#8220;using AI for development&#8221; that most developers are familiar with: tab-completing a function, asking it to explain an error, maybe generating a boilerplate class. That&#8217;s where I started too. Nearly a year later, I barely recognise that workflow. What I do today is fundamentally different &#8212; not because the tools changed (though they did), but because my mental model of what AI is in the development process changed.</p><p>This isn&#8217;t a piece about AI hype. It&#8217;s a detailed, honest account of how I actually use agentic AI &#8212; primarily Claude and GitHub Copilot &#8212; to build backend systems and data/ML pipelines. Including the parts that are still hard.</p><div><hr></div><h2>Where It Started: Autocomplete and One-Off Questions</h2><p>Like most developers, my first use of AI in coding was almost passive. GitHub Copilot sat in my editor and suggested completions. I&#8217;d occasionally paste a function into a chat window and ask what was wrong with it. Useful, occasionally impressive, but ultimately just a smarter Stack Overflow.</p><p>The shift wasn&#8217;t a single moment. It was gradual &#8212; a slow accumulation of realising that the more context and structure I gave the AI, the more it could actually carry. At some point I stopped thinking of it as a lookup tool and started thinking of it as a collaborator that needed to be briefed properly.</p><p>That reframing changed everything.</p><div><hr></div><h2>The Workflow Today: From Idea to Compounded Knowledge</h2><p>Here&#8217;s what the end-to-end process looks like now for any meaningful feature.</p><h3>1. Brainstorming Through an Interview</h3><p>I don&#8217;t start by writing a spec. I start by asking Claude to interview me about the feature.</p><p>This is deceptively powerful. Instead of me trying to articulate a half-formed idea into a structured document, the AI pulls the requirements out of me through questions. What problem are we solving? Who uses it? What are the edge cases? What are the constraints? What have we tried before?</p><p>By the end of that conversation, the shape of the feature is clear &#8212; not because the AI designed it, but because being asked good questions forced me to think it through properly.</p><h3>2. Planning the Feature</h3><p>With the brainstorm as context, I ask Claude to produce a structured implementation plan. This includes the breakdown of components, the sequence of development, the data flow, the test strategy, and &#8212; for larger features &#8212; a phased checklist that will later be used to track progress.</p><p>This plan is not final. It&#8217;s a first draft that I review critically.</p><h3>3. Reviewing and Deepening the Plan with Parallel Research</h3><p>After the initial plan is reviewed, I ask Claude to deepen it using multi-agent parallel research &#8212; essentially running concurrent threads of investigation across different aspects of the problem. For backend systems, this might mean simultaneously researching the best approach to a data schema, the right library for a pipeline stage, and the failure modes of a particular architecture pattern.</p><p>The output of this research feeds back into a revised, more detailed plan. I review it again. Only once I&#8217;m satisfied with the plan do I move to implementation.</p><p>This two-stage review &#8212; plan, then deepen, then review again &#8212; catches a surprising number of architectural issues before a single line of code is written.</p><h3>4. Implementation and Testing</h3><p>With a solid plan in place, I ask Claude to implement and test the feature. For large features with phased checklists, it marks each phase as completed in the planning document as it goes. This keeps both of us oriented on progress and makes it easy to resume after interruptions.</p><p>This is where GitHub Copilot becomes active in parallel &#8212; handling the in-editor completions and smaller in-context decisions while Claude manages the higher-level execution.</p><h3>5. Manual Review &#8212; And Why This Step Is Non-Negotiable</h3><p>Here&#8217;s something I want to be direct about: AI-generated code requires rigorous review. It is not safe to assume correctness.</p><p>In practice, code reviews on AI-assisted features take longer than they would on purely human-written code &#8212; precisely because the volume of output is higher and the AI can confidently produce code that is subtly wrong. The speed at which AI writes code does not translate linearly into faster shipping, because the review burden scales with it.</p><p>What this means in practice: I test manually, I trace through logic carefully, and I treat the AI&#8217;s output as a strong first draft from a very fast junior engineer &#8212; not as a finished product. The discipline of this review step is what separates useful AI-assisted development from dangerous over-reliance.</p><h3>6. The Compounding Layer &#8212; Where the Real Leverage Is</h3><p>This is the part of my workflow that I think most developers skip, and it might be the most valuable part.</p><p>Once a feature is built and verified, I ask Claude to go back through everything we did &#8212; the brainstorm, the plan, the implementation decisions, the mistakes, the iterations &#8212; and document the learnings. This includes:</p><ul><li><p>What approaches worked and why</p></li><li><p>What went wrong and what the correct approach turned out to be</p></li><li><p>Patterns specific to this codebase that the AI should know for next time</p></li><li><p>Dos and don&#8217;ts for future features in the same area</p></li></ul><p>This document lives alongside the codebase. The next time I work on a related feature, I load these learnings into context at the start.</p><p>The effect is compounding. Each feature makes the AI&#8217;s work on the next feature more accurate, more codebase-aware, and less prone to the same class of mistakes. It also serves as living documentation &#8212; not written as an afterthought, but derived from what actually happened.</p><div><hr></div><h2>What This Workflow Is Not</h2><p>It&#8217;s not autonomous. At every stage &#8212; brainstorming, planning, implementation, review &#8212; I am involved and making judgement calls. The AI does not ship features. I do. The AI dramatically expands what I can think through and execute in a given window of time, but the accountability and the critical thinking stay with me.</p><p>It&#8217;s not always faster. Depending on the feature, AI-assisted development can feel slower than just writing the code myself, especially when the review cycle catches things that need rework. The value is not raw speed &#8212; it&#8217;s the quality of thinking that goes into the feature before implementation begins, and the knowledge that accumulates afterward.</p><div><hr></div><h2>What It Requires From You</h2><p>To use AI this way, you need to be a capable enough engineer to know when it&#8217;s wrong. You need to review code, not just run it. You need to give it structured context, not lazy prompts. And you need to resist the temptation to skip the review step because the output looks right.</p><p>The developers who get the most out of agentic AI are not the ones who use it the most. They&#8217;re the ones who use it most deliberately.</p><div><hr></div><h2>Where This Is Heading</h2><p>The tools are improving rapidly. Multi-agent coordination is getting more capable. Context windows are expanding. What requires careful orchestration today will likely become more fluid.</p><p>But the underlying discipline &#8212; plan before you build, review what you ship, and compound what you learn &#8212; will remain the difference between AI that accelerates good engineering and AI that accelerates the production of bugs.</p><p>That part is still on us.</p>]]></content:encoded></item><item><title><![CDATA[Are AI Agents Burning a Hole in Your Pocket?]]></title><description><![CDATA[A $50 Reality Check.]]></description><link>https://techuntethered.com/p/are-ai-agents-burning-a-hole-in-your</link><guid isPermaLink="false">https://techuntethered.com/p/are-ai-agents-burning-a-hole-in-your</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Sun, 22 Mar 2026 10:50:55 GMT</pubDate><content:encoded><![CDATA[<p></p><p>A month ago, I set out on a mission. I wanted to see if I could finally hand over the reins of my daily grunt work&#8212;email management, content scraping, and deep product research&#8212;to autonomous AI agents.</p><p>I spun up an OpenClaw instance on a basic VPS, connected it to OpenRouter, and loaded my API keys with a cocktail of the top models: Claude&#8217;s Sonnet 4.6 and Opus 4.6, Minimax 2.5, and a dash of GPT.</p><p>My logic was sound: use cheaper models for basic tasks, and save the intelligence powerhouses for the complex research.</p><p>Four weeks later, I turned the entire system off. Here is why.</p><h4>The &#8220;Intelligence&#8221; Tax</h4><p>For basic tasks&#8212;summarizing emails or fetching data from a fixed source&#8212;the system worked beautifully. It was fast and affordable.</p><p>But the moment I asked the agent to do something complex, like executing my personal research workflow for a new product idea, the math broke.</p><p>Complexity requires tokens. A <em>lot</em> of them. To have an agent research a topic, plan a strategy, browse multiple sources, and synthesize an output, the context window needs to be constantly refreshed.</p><p>I watched as $10 on OpenRouter vanished over a few hours running Minimax 2.5 on &#8220;Nitro&#8221; mode. While the output was definitely better than standard mode, the token consumption was unsustainable for a personal project.</p><h4>The Subscription Wall</h4><p>Hoping to manage costs, I switched to model-specific subscriptions.</p><p>I bought the Minimax coding plan for around $20. It handled complex tasks better, but due to the sheer amount of context required for each iterative step, I constantly hit session limits. The automation would just stop mid-flow.</p><p>Then I tried Claude. I rely on it for complex reasoning, but even with the $20 personal subscription, my automated workflows (running every two hours) obliterated my usage limits. I was hitting my 5-hour reset limit within 30 to 60 minutes. On two occasions, I burned through my <em>weekly</em> limit within days.</p><h4>The ROI Calculation: Is it Scalable?</h4><p>By the end of the month, the bill looked like this:</p><ul><li><p>Claude Subscription: ~$20</p></li><li><p>Minimax Subscription: ~$20</p></li><li><p>Basic VPS: ~$5</p></li><li><p>Additional Pay-per-token API costs: ~$10+</p></li><li><p><strong>Total: ~$55+</strong></p></li></ul><p>$55 a month is sustainable if the output generates income or saves significant time. But it didn&#8217;t. Despite that spend, I never actually achieved complete automation for the complex operations. It still required babysitting due to rate limits and context failures.</p><p>Here is the inconvenient truth I realized: <strong>Relying on my data engineering experience to write a Python script using RSS feeds does 80% of my data fetching for pennies.</strong></p><p>Sure, I might lose the &#8220;AI summarization&#8221; layer, but I save $50. For general, minor use cases, the current cost of running autonomous agents is simply not justified by the Return on Investment.</p><h4>Going Back to Basics</h4><p>I am confident that AI agents work well for very unique, high-value enterprise use cases. But for a solo user looking for productivity gains, the math isn&#8217;t mathing right now.</p><p>This month, I am stopping my agent instances. I am going back to utilizing the customer-side subscriptions manually, and automating the rote tasks with reliable code.</p><p>Before you invest in building an agentic workforce, audit your process. Are you overpaying for &#8220;intelligence&#8221; when a simple script would do?</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techuntethered.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Caching, but without ElastiCache - Saving $39/month]]></title><description><![CDATA[How I saved roughly $39 a month by substituting Elasticache with Supabase]]></description><link>https://techuntethered.com/p/caching-but-without-elasticache-saving</link><guid isPermaLink="false">https://techuntethered.com/p/caching-but-without-elasticache-saving</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Tue, 23 Sep 2025 07:08:55 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!MNv9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As most of us can agree, caching is one of the most important pieces of any software development, because of benefits including, but not limited to, less pressure on database and quick read (and in some cases write) times.</p><p>While this is true, it also requires to build and maintain the infrastructure around it, which not only adds the costs for the server, but also managing it (specially if you self-host it). Even if you don&#8217;t self host it and use a product like AWS Elasticache, the cost can be a burden, specially when you are bootstrapping everything and just starting out, where every penny matters.</p><p>I found myself in the same situation when I was working on a side project and I had to use a cache, but I didn&#8217;t want to pay for a server or ElastiCache.</p><p>I was already using Supabase Cloud&#8217;s free version for this project, so I thought of using Supabase only for this purpose. If you have used Supabase before, you&#8217;d know that the free limits apply to an organisation and not the account. This meant that I could create a new organisation and maintain upto 500MBs of cache for free in Supabase cloud itself.</p><p>Let&#8217;s understand the main problem statement - I am using the external API for Reddit to fetch the list of subreddit names from a given keyword. The issue is that this API takes roughly 3-4 seconds for the results, and I don&#8217;t want my users to wait for that long, specially for each unique request.</p><p>Assumption: Assuming that the subreddit list wouldn&#8217;t change or have a significant difference at least for a week, I can cache the results for keywords the users have already searched for, for 1 week.</p><p>So here&#8217;s how I handled it - for every unique request, I follow this approach:</p><ol><li><p>I maintain a config table in the main database, which stores the location, schema name and expiry of that cache schema.</p><ol><li><p>If the config entry doesn&#8217;t exist, it means the cache schema also doesn&#8217;t exist, so I create a new schema with a predefined name and add entry to config table with expiry of T+7 Days.</p></li><li><p>If the config entry exists, then I need to check if it&#8217;s expiring today. If it&#8217;s expiring, then the cache schema needs to be destroyed and recreated again.</p></li><li><p>As a part of the schema creation or replacement, I also create a predefined set of tables which will act as my cache tables.<br></p></li></ol></li><li><p>I then query the &#8220;subreddit_list&#8221; table in the cache schema for the keyword given by the user.</p><ol><li><p>If EXISTS, then I simply return the entries from the cache</p></li><li><p>If DOES NOT EXIST, then I query the reddit API, get results and save it in the cache.</p></li></ol></li></ol><p>Here&#8217;s a visual representation of how it looks (the dotted lines mean they run as non-blocking background tasks):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MNv9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MNv9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 424w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 848w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MNv9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png" width="958" height="1080" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1080,&quot;width&quot;:958,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:164589,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://prateekjain6342.substack.com/i/174312450?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MNv9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 424w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 848w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 1272w, https://substackcdn.com/image/fetch/$s_!MNv9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa9a8990d-c1db-4184-b1ad-d3e4f527e97b_958x1080.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now, everything runs on AWS Lambda and I use Supabase to manage my databases and saving the money I would have had to spend on AWS Elasticache for cache.</p><p>Would be happy to hear your thoughts on this! I am open to hearing better alternatives to this approach, if any.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://techuntethered.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Why Using AI for Coding Can Lead to Shaky Results]]></title><description><![CDATA[You&#8217;ve probably seen posts claiming &#8220;I built an app in five minutes using AI!&#8221; It looks easy, until you try it yourself.]]></description><link>https://techuntethered.com/p/why-using-ai-for-coding-can-lead-to-shaky-results</link><guid isPermaLink="false">https://techuntethered.com/p/why-using-ai-for-coding-can-lead-to-shaky-results</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Mon, 04 Aug 2025 03:19:36 GMT</pubDate><content:encoded><![CDATA[<p><br>You&#8217;ve probably seen posts claiming <em>&#8220;I built an app in five minutes using AI!&#8221; </em>It looks easy, until you try it yourself.<br>Someone wasted eight hours on AI-written code that crashed during login tests. The system made up fake connection points, scattered app data across files, and left passwords visible in public scripts. This shows a big problem: rushing with AI often creates messy foundations. <br></p><div><hr></div><p><strong>Common Mistakes When Using AI Without Rules</strong></p><p><br><strong>1. Expecting Too Much</strong></p><p>AI handles small jobs well, like fixing typos in code or checking single functions<em>. But bigger tasks (logins</em>, spreading data across servers<em>) trip it up</em>. A 2024 study found 42% of AI-made login codes forgot time limits on sessions<em>, while many stored passwords in unsafe ways despite warnings</em><strong>.<br><br>Fix</strong>: Split projects into tiny pieces you can check<em>. Track changes step-by-step instead of accepting huge chunks of code</em>. <br><br><strong>2. Believing Made-Up Solutions</strong></p><p>AI invents code that looks right but fails: Studies show nearly 1/3 of AI solutions have serious bugs<strong>.</strong><br>Always test results<em>, ask teammates to review</em>, and write down how systems should work. <br><br><strong>3. Skipping Instructions</strong></p><p>AI writes code fast but doesn&#8217;t explain itself<em>. Teams get confusing parts without notes like puzzle pieces missing labels</em>. One developer couldn&#8217;t track how info moved through layers of AI-made code without drawings<strong>.</strong><br>Keep simple guides with your code. Treat explanations as important as the code itself<strong>.</strong></p><p><br><strong>4. Forgetting Safety Rules</strong></p><p>New security warnings say AI-made flaws are dangerous<em>. Common problems include letting people access things they shouldn&#8217;t (38%)</em><strong>, leaking private info (29%)</strong><em>, and hacker tricks (19%), costing companies big money</em>. Tools help catch these,<em> but humans must double-check</em><strong>.</strong></p><p><br><strong>5. Hurting Learning</strong></p><p>Using too much auto-complete makes developers worse at fixing errors (-17%) and slower at writing manual code (-23%) over time<strong>.</strong> Treat AI helpers like trainees ask &#8220;why?&#8221; before using their ideas. <br></p><div><hr></div><p><strong>Mixing Speed With Safety </strong><br>Successful teams plan first then use AI carefully:</p><p><strong>Draw first</strong>: Make simple sketches/plans before coding <br><strong>Ask why</strong>: Make AI explain its choices step-by-step <br><strong>Check quality</strong>: Don&#8217;t approve code until teammates test safety<br></p><div><hr></div><p><strong>Final Thought </strong><br>AI changes coding but doesn&#8217;t replace basics<strong>. Do well by focusing on</strong>:</p><p>- Clear plans before building <br>- Careful testing <br>- Using AI as helpful-but-mistake-prone tools <br><br>Choose: control these tools wisely, or let their shortcuts ruin your work.</p>]]></content:encoded></item><item><title><![CDATA[Databases & SQL for beginners]]></title><description><![CDATA[Let me guess, you have been thinking of and planning to start transitioning into or jumping directly into a career into Data related job roles, including but not limited to, Data Analytics, Data Engineering, Data Modelling, etc and the first thing you have been suggested by people in these fields is to learn about data and SQL.]]></description><link>https://techuntethered.com/p/databases-sql-for-beginners</link><guid isPermaLink="false">https://techuntethered.com/p/databases-sql-for-beginners</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Mon, 24 Mar 2025 04:24:13 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c8a348bd-efbf-4c46-9ad4-3c1dff9cff13_1029x637.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let me guess, you have been thinking of and planning to start transitioning into or jumping directly into a career into Data related job roles, including but not limited to, Data Analytics, Data Engineering, Data Modelling, etc and the first thing you have been suggested by people in these fields is to learn about data and SQL.</p><p>Well, I'm here just to help you through that. Databases and SQL is one of the most crucial concepts in my opinion - which you will use for the rest of your professional life in case you decide to pursue your career in data related roles, and while everyone wants to eventually start with the practical stuff, it's equally crucial to understand how it works in theory, not only because it will help you in interviews, but this will help you understand your everyday work better and solve problems by understanding the concepts at core. So, without wasting more of your precious time, I'll jump right into it.</p><div><hr></div><h2><strong>What is a database?</strong></h2><p>To keep the language simple, imagine a big container filled with smaller boxes or containers of varying sizes, which may also be linked to one another through some properties or attributes. These boxes have the ability to store a ton of information inside them and helps to organise information better according to the users' needs.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2fj_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2fj_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 424w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 848w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 1272w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2fj_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png" width="1029" height="637" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:637,&quot;width&quot;:1029,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!2fj_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 424w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 848w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 1272w, https://substackcdn.com/image/fetch/$s_!2fj_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe708ffbe-f21e-4c86-9740-7ac7f8df9910_1029x637.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Diagram 1: A visual diagram of a database with 15 tables</figcaption></figure></div><p>In the diagram 1 - You can see 15 tables from A-O inside a larger container. While these tables have their own storage, they also have the ability to be linked to each through their primary identifying attributes.</p><p>For example - Let's assume that Table A is used to store a list of customers for an e-commerce store and holds information such as their name, email address and phone number and Table B stores the list of orders for all the customers and stores information such as which customer placed the order, for how much amount and for what products. Assuming the engineer configured the table in such a way that the primary attribute which uniquely identifies a customer in Table A is the phone number (This will be called the "Primary Key" for Table A), in order to link Table A to Table B, the engineer would also create a "Foreign Key" in Table B which acts as the link between Table A and Table B. The Foreign Key holds the same value as it would in the Primary Key in Table A - so, Table B would hold the phone number of the customer who placed the order as a Foreign Key. You can visualise it better through Diagram 2.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SJxs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SJxs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 424w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 848w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 1272w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!SJxs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png" width="786" height="332" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:332,&quot;width&quot;:786,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!SJxs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 424w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 848w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 1272w, https://substackcdn.com/image/fetch/$s_!SJxs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818a811c-eb0d-4fe8-9fb6-0ddb7be101ad_786x332.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Diagram 2: Table A linking with Table B through Primary Key (PK)</figcaption></figure></div><p>Just to be transparent, attributes such as phone numbers, even though unique, may not be used as a primary key by most companies, the reason being that such fields are usually a part of PII (Personally Identifiable Information) information which is usually a sensitive set of data which most companies protect even from their internal employees and is shared only with those who absolutely need to work with or on the basis of PII information with certain policies in place which protect that set of information.</p><p>So what do companies use in place of PII information to create Primary Keys? They use simple integers or an alphanumeric IDs (commonly known as UUIDs) to create a unique identification as a primary key for each table. These keys are then used as foreign keys in subsequent tables which need to be linked together. So the tables in Diagram 2 would probably look a little different in the real world - as shown in Diagram 3.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gtto!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gtto!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 424w, https://substackcdn.com/image/fetch/$s_!gtto!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 848w, https://substackcdn.com/image/fetch/$s_!gtto!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 1272w, https://substackcdn.com/image/fetch/$s_!gtto!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gtto!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png" width="797" height="340" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:340,&quot;width&quot;:797,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!gtto!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 424w, https://substackcdn.com/image/fetch/$s_!gtto!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 848w, https://substackcdn.com/image/fetch/$s_!gtto!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 1272w, https://substackcdn.com/image/fetch/$s_!gtto!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1915ce-4b21-48b4-9bd4-d67d7b82b74b_797x340.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Diagram 3: Using IDs as Primary Key</figcaption></figure></div><h2><strong>ACID Properties</strong></h2><p>Now that you've some understanding of how databases look like in general - there are some rules / properties which need to be kept in mind while creating or working with databases - also commonly known as A.C.I.D. properties.</p><h3>A - Atomicity</h3><p>The idea behind atomicity is to maintain the integrity of a transaction. A transaction in databases can be a simple write transaction to your database, for example, you work for a company which provides a digital wallet to it's customers to use for faster and smoother payments, for them a simple transaction could be one customer paying to another customer paying some amount of money.</p><p>Let's say for that transaction, a customer X wants to send 100 bucks to customer Y through the wallet, then there are two sub transactions taking place in the database for this:</p><ul><li><p>Transaction 1: Debit 100 from X's wallet</p></li><li><p>Transaction 2: Credit 100 from Y's wallet</p></li></ul><p>What happens if transaction 1 succeeds but while transaction 2 is taking place, some error comes up in the system because of which it fails? If atomicity is not taken care, 100 bucks will get deducted from X's wallet by Y will never receive the money, thus leading to a faulty transaction. Therefore, atomicity states that the transaction as a whole will be considered successful if all the sub-transactions are successful, failing which the entire transaction shall be marked as a failure and all the changes, if any, shall be rolled backed to it's original state.</p><h3>C - Consistency</h3><p>Consistency can be considered as an extension to Atomicity. It states that after each operation, the database state should stay consistent before and after the transaction. Extending the example given above - considering the Transaction was successful, if 100 bucks from debited from X and credited to Y, the net amount should still be 100 in the system and not change. Consider a scenario where the transaction above failed, and because atomicity was not followed, 100 bucks got debited from the customer's wallet but Y didn't receive them. In terms of the database, the amount is now 100 bucks less because while there was a debit of that money, it never got credited, so the net change in the amount in system is now -100 instead of 0.</p><h3>I - Isolation</h3><p>Isolation states that multiple transactions should be able to occur independently and concurrently without waiting for previous transactions to finish while also maintaining the consistency and atomicity.</p><p>Continuing the example given in Atomicity, there would definitely be multiple users in the system who would be doing transactions between themselves at the same time, if the transactions are not allowed to be independently driven, each customer will have to wait for the previous transaction to be finished before they can start with their transaction. This poses another problem - Let's say that a customer Z has a total of 200 bucks as their wallet balance and they owe a total of 300 bucks to two different customers, X and Y (150 each).</p><p>If customer Z somehow initiates both the transactions one after the other, the system should be able to handle the transactions in a way where the first initiated transaction by the customer Z should make their wallet balance fall to 50 bucks which is insufficient for the second transaction even if the first transaction is still in progress, and should throw an error to the customer for the second transaction.</p><p>This is because if these properties are not followed, because when the customer initiated the second transaction at the same time as the first, the wallet balance would still have been the same and the customer would have been able to make two debit transactions of total 300 bucks on a wallet balance of 200 bucks.</p><h3>D - Durability</h3><p>Durability states that after each transaction, the updates and modifications and logs shall be stored in a disk so that the data persists even after a system failure. The effects of the transactions should never be lost</p><h2>Types of Databases</h2><p>There are broadly two types of databases, Relational Databases and No-SQL (Non SQL) databases.</p><h3>Relational Databases</h3><p>These kinds of databases are structured in nature, usually structured in rows and columns. These are the most commonly used kinds of databases in the industry and can handle <strong>complex</strong> transactions. Once a schema is defined for a table, all records in the table must follow the same schema. If a new attribute/column needs to be added in the table, then the attribute should also be assigned a value (default or by some custom logic) for all the previous records in the table as well.</p><h3>No-SQL Databases</h3><p>These kinds of databases are usually non-structured and are better for transactions which are simpler in nature. Every record can have a different schema inside the tables giving more flexibility for adding attributes without needing to add values for historical data.</p><p>One key difference between No-SQL and Relational Databases is the volume of data - generally speaking, No-SQL databases are preferred for use cases where the volume of data is very high because of it's unstructured nature and the ability to transform the data structure as per the requirements. On the contrary - use cases where more complex transactions or logics needs to be performed, relational databases are usually the go-to choice.</p><p>One example which comes to mind is - E-Commerce related data is usually stored in relational databases however the application and code logs maybe stored in a non-sql database since the volume of logs is high and generally don't require any complex computations.</p><div><hr></div><p>I have also uploaded a youtube video on this topic which you can watch as well for more detailed explanation</p><div class="captioned-image-container"><figure><div id="youtube2-YQA7x2LQI1Q" class="youtube-wrap" data-attrs="{&quot;videoId&quot;:&quot;YQA7x2LQI1Q&quot;,&quot;startTime&quot;:null,&quot;endTime&quot;:null}" data-component-name="Youtube2ToDOM"><div class="youtube-inner"><iframe src="https://www.youtube-nocookie.com/embed/YQA7x2LQI1Q?rel=0&amp;autoplay=0&amp;showinfo=0&amp;enablejsapi=0" frameborder="0" loading="lazy" gesture="media" allow="autoplay; fullscreen" allowautoplay="true" allowfullscreen="true" width="728" height="409"></iframe></div></div></figure></div>]]></content:encoded></item><item><title><![CDATA[From marketing manager to software engineer in less than 1 year]]></title><description><![CDATA[When I chose Commerce in school, it wasn&#8217;t because I loved the subjects &#8212; it was because I was scared.]]></description><link>https://techuntethered.com/p/from-marketing-manager-to-software-engineer-in-less-than-1-year</link><guid isPermaLink="false">https://techuntethered.com/p/from-marketing-manager-to-software-engineer-in-less-than-1-year</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Tue, 14 Jan 2025 12:42:26 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b3013f70-728b-406e-a7e9-d2ab2a657d10_800x800.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!85g4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!85g4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!85g4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!85g4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!85g4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!85g4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;From marketing manager to software engineer in less than 1 year&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="From marketing manager to software engineer in less than 1 year" title="From marketing manager to software engineer in less than 1 year" srcset="https://substackcdn.com/image/fetch/$s_!85g4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 424w, https://substackcdn.com/image/fetch/$s_!85g4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 848w, https://substackcdn.com/image/fetch/$s_!85g4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!85g4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F280a17a6-99ba-4dac-9069-59ff26552413_800x800.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><p>When I chose Commerce in school, it wasn&#8217;t because I loved the subjects&#8202;&#8212;&#8202;it was because I was scared. Scared of scoring less and ending up jobless. Playing it safe seemed like the only way forward.</p><p>Fast forward to my B.Com (H) at Delhi University, where I immersed myself in marketing. Internships, activities, projects&#8202;&#8212;&#8202;I explored every corner of the field. Yet, deep down, something felt off. I was learning, but not fully present.</p><p>Influencer marketing followed. For almost two years, I managed campaigns and offline accounts, checking all the right boxes. On paper, things looked great, but during my second role, I felt a quiet nudge&#8202;&#8212;&#8202;&#8220;This isn&#8217;t it.&#8221;</p><p>No performance issues, no big drama. Just the feeling that I wasn&#8217;t giving my 100%. Watching data analysts work their magic sparked curiosity. <em>Could I do that?</em> Thanks to the unconditional support of a senior colleague, I dove into Python and SQL, discovering a whole new world. And that was the turning point.</p><p>The path wasn&#8217;t easy. Coming from a Commerce background meant endless rejections for technical roles. &#8220;You&#8217;re not qualified for this,&#8221; they said. The education system back then didn&#8217;t support cross-domain careers, and I felt stuck.</p><p>Then luck knocked&#8202;&#8212;&#8202;a referral through a friend got me a role at an early-stage startup. I led data analytics, often Googling the <em>simplest</em> things while also learning how a tech team functions. The steep learning curve, endless challenges, and incredible mentors pushed me forward.</p><p>Today, I&#8217;m proud to say I work in a pure software role, and I completed my Masters in Computer Science in 2024.</p><p>This journey&#8202;&#8212;&#8202;from fear-driven choices to embracing a career shift&#8202;&#8212;&#8202;has been a rollercoaster. And this year, I&#8217;m committed to sharing my learnings, insights, and experiences, hoping they might inspire or guide even one person considering a career switch.</p><p>If you&#8217;ve ever felt stuck in a path you didn&#8217;t love, keep following along. The road might be tough, but trust me&#8202;&#8212;&#8202;it&#8217;s worth it.</p>]]></content:encoded></item><item><title><![CDATA[Using DuckDB for a Simple Bill Splitting Solution]]></title><description><![CDATA[For over a decade, my friends and I used a popular bill-splitting app to manage group expenses after trips or outings.]]></description><link>https://techuntethered.com/p/using-duckdb-for-a-simple-bill-splitting-solution</link><guid isPermaLink="false">https://techuntethered.com/p/using-duckdb-for-a-simple-bill-splitting-solution</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Thu, 02 Jan 2025 14:05:52 GMT</pubDate><content:encoded><![CDATA[<p>For over a decade, my friends and I used a popular bill-splitting app to manage group expenses after trips or outings. The process was simple: log all the expenses, assign each to specific group members, and calculate the final amount owed by each person. However, a recent change to its free plan introduced a frustrating limitation: users could only add 4&#8211;5 expenses per day. For someone managing upwards of 10&#8211;15 expenses from a single trip, this change rendered the app almost unusable.</p><p>This frustration led me to explore whether I could quickly build a simple bill-splitting tool that focused purely on the basics: calculations and group expense sharing, without unnecessary features like analytics or currency conversion. While it wasn&#8217;t about innovation, it was an opportunity to solve a problem for myself and potentially others.</p><h3>Repurposing DuckDB</h3><p>Around this time, I had been learning about <strong>DuckDB</strong>, an in-process analytical database designed for OLAP (Online Analytical Processing) workloads. It is typically used for analytical data processing tasks, but I saw an opportunity to repurpose it for something simpler: temporary data storage and calculation for bill-splitting. DuckDB&#8217;s flexibility, lightweight design, and SQL capabilities made it a suitable choice for this project, even though the use case was unconventional.</p><h3>The Technical Approach</h3><p>Here&#8217;s how I built the project:</p><p><strong>1. Session Isolation with UUIDs</strong> Each session generates a unique <strong>UUID</strong> to create and identify a temporary DuckDB database file. This ensures that data for each group or session remains isolated and secure.</p><p><strong>2. Temporary Data Persistence</strong> DuckDB files created during a session are stored temporarily. To prevent data buildup, a <strong>cron job</strong> automatically deletes files that haven&#8217;t been accessed for 72 hours. This approach ensures efficient storage management without requiring long-term data retention.</p><p><strong>3. Backend Functionality</strong> Using <strong>Python</strong>, I developed the backend to manage database file creation, data storage, and cleanup. Python&#8217;s integration with DuckDB made it easy to execute queries and handle data efficiently.</p><p><strong>4. Frontend Simplicity</strong> For the frontend, I used <strong>Next.js</strong> and <strong>Tailwind CSS</strong> to create a minimal and functional user interface. The UI is basic but sufficient for the core purpose of inputting expenses and viewing calculated results.</p><p><strong>5. Cost-Effective Deployment</strong> The project is hosted using:</p><ul><li><p><strong>Netlify</strong> for the frontend on its free tier.</p></li><li><p><strong>Oracle Cloud</strong> for the backend using its free-tier instance.</p></li></ul><p>With this setup, the operational cost remains under <strong>INR 300 per month</strong>, excluding the domain cost.</p><h3>A Quick Build</h3><p>The entire project, which I call <strong>Splitzer</strong>, was built in under 48 hours. While it&#8217;s not groundbreaking, it serves its purpose: offering a lightweight, no-frills solution to a common problem. By using DuckDB for a task outside its typical use case, I was able to create a practical tool for group expense sharing.</p><h3>Reflecting on the Experience</h3><p>What stands out most from this project is how flexible tools like DuckDB can be when applied to unconventional problems. Although it&#8217;s primarily designed for analytical workloads, its ability to handle temporary data storage and SQL queries made it a good fit for this simple bill-splitting app.</p><p>This wasn&#8217;t about reinventing the wheel but about repurposing available tools to address a personal frustration&#8202;&#8212;&#8202;one that I imagine many others may share.</p><h3>Conclusion</h3><p><a href="https://splitzer.org/?ref=prateekja.in">Splitzer</a> may not be innovative, but it&#8217;s an example of how technology can be applied creatively to solve everyday problems. By focusing on simplicity and leveraging the right tools, it&#8217;s possible to build something useful quickly and affordably.</p><p>Have you ever used a tool in a way it wasn&#8217;t originally intended for? I&#8217;d love to hear your experiences.</p>]]></content:encoded></item><item><title><![CDATA[Monte Carlo Simulations may help you save a lot of money!]]></title><description><![CDATA[Have you ever wondered how gambling businesses always stay in business?]]></description><link>https://techuntethered.com/p/monte-carlo-simulations-may-help-you-save-a-lot-of-money</link><guid isPermaLink="false">https://techuntethered.com/p/monte-carlo-simulations-may-help-you-save-a-lot-of-money</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Sun, 08 May 2022 07:24:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/440cd8bb-43c2-4230-a7b1-1bdc34065f12_800x273.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!41Q0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!41Q0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 424w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 848w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!41Q0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Monte Carlo Simulations may help you save a lot of money!&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Monte Carlo Simulations may help you save a lot of money!" title="Monte Carlo Simulations may help you save a lot of money!" srcset="https://substackcdn.com/image/fetch/$s_!41Q0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 424w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 848w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!41Q0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26ce474c-ee34-4257-9235-3f27160fe0eb_800x273.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><p>Have you ever wondered how gambling businesses always stay in business?</p><h3><strong>What is a Monte Carlo Simulation?</strong></h3><p>A Monte Carlo Method can be technically defined as a computational algorithm that rely on random sampling. Such a method can be used to solve any probabilistic interpretation. In simpler words, projecting business costs basis random variables, chances of failure for a machine, impact of launching a new product and many more could potentially be solved using the Monte Carlo method.</p><h3>How do we use this?</h3><p>Let&#8217;s begin with a simpler example, gambling. Whenever we talk about probability, gambling usually comes up as the first example in our head.<br>But, have you ever wonder why such businesses (Example - Casinos) always stay in profit? Or, why do they offer double, triple, or maybe even 10 times your invested amount as your prize money if you win the game?<br>Let&#8217;s take a look at it.</p><p>For this example, we&#8217;ll play a game which I&#8217;d like to call &#8216;<strong>Double Dice</strong>&#8217;.<br>The rules of this game are simple, you have to throw two dice at once, and if you get the same number on both dice, you win.<br>The casino decides to put a prize money of say 6 times the amount you bid on your turn if you win, and if you lose, you lose your bid amount. If you bid $10 on one roll of dice and you win, you $60, and if you lose, you lose $10. Seems like a pretty good deal, right? Well, if you look at it in terms of probability, you&#8217;ll realise that the house (Casino) always has more opportunities to win. So in this case, the total number of possible outcomes of a 2 dice roll are (6*6) = 36 and you only win in the following 6 outcomes:</p><ol><li><p>1,1</p></li><li><p>2,2</p></li><li><p>3,3</p></li><li><p>4,4</p></li><li><p>5,5</p></li><li><p>6,6</p></li></ol><p>That is, when both dice have the same number, therefore, the player can win in only 6 out of 36 outcomes.</p><p>Let&#8217;s build a Monte Carlo Simulation for this scenario.</p><p><strong>Building a function which simulates a 3 dice roll</strong></p><p>Now that we have simulated the main part of the game, let&#8217;s define the variables</p><ol><li><p>SIMULATIONS = Number of times we want to simulate the entire game</p></li><li><p>ROLLS_PER_GAME = Number of times we want the player to roll in the entire game</p></li><li><p>BET_AMOUNT = The betting amount for each role</p></li><li><p>WIN_PROBABILITY = An array of probability of wins after each game</p></li><li><p>END_BALANCE = The end wallet balance of the player after each simulation</p></li><li><p>STARTING_BALANCE = The starting wallet balance of the player at the start of each simulation</p></li></ol><p>Initiating a Plot Figure for our Simulations</p><p>Now we will begin writing our loops which will help us simulate the game. An outer for loop for running the simulation for the number of times mentioned in the &#8216;SIMULATIONS&#8217; variable, and an inner while loop to keep recording the outcomes of the each dice roll within each game and adding lines to our plot figure.</p><p>Displaying the plot figure after our simulationsplt.show()</p><p>After 10,000 simulations, our figure should look similar to this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3lXC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3lXC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 424w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 848w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 1272w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3lXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png" width="387" height="248" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:248,&quot;width&quot;:387,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Monte Carlo Simulations may help you save a lot of money!&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Monte Carlo Simulations may help you save a lot of money!" title="Monte Carlo Simulations may help you save a lot of money!" srcset="https://substackcdn.com/image/fetch/$s_!3lXC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 424w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 848w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 1272w, https://substackcdn.com/image/fetch/$s_!3lXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F422b830e-f0c8-4db0-a1f8-54c12ad35110_387x248.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">End Wallet Balance after 10000 simulations</figcaption></figure></div><p>Now let&#8217;s calculate the average wallet balance for a player after 10,000 simulations:overall_win_probability = sum(WIN_PROBABILITY)/len(WIN_PROBABILITY)overall_end_balance = sum(END_BALANCE)/len(END_BALANCE)print(f"Average win probability after {SIMULATIONS} runs: {overall_win_probability}")print(f"Average ending balance after {SIMULATIONS} runs: {overall_end_balance}")</p><p>The above code would give you the following result:Average win probability after 10000 runs: 0.16678711288711615<br>Average ending balance after 10000 runs: 11676.773</p><p>Therefore, on an average, the player would end up earning ~$1600</p><p>Now let&#8217;s try reducing the prize money for winning, we were assuming 6 times the betting amount for the above simulation, let&#8217;s see what happens if we change 6 to 4. The new figure would look something like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iKyG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iKyG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 424w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 848w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 1272w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iKyG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png" width="387" height="248" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:248,&quot;width&quot;:387,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Monte Carlo Simulations may help you save a lot of money!&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Monte Carlo Simulations may help you save a lot of money!" title="Monte Carlo Simulations may help you save a lot of money!" srcset="https://substackcdn.com/image/fetch/$s_!iKyG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 424w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 848w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 1272w, https://substackcdn.com/image/fetch/$s_!iKyG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F472a9d92-41cb-4851-bf85-ec2232ff66b3_387x248.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">End Wallet Balance after 10000 simulations with 4 times&nbsp;reward</figcaption></figure></div><p>Average win probability after 10000 runs: 0.16669690309690652<br>Average ending balance after 10000 runs: 8333.18</p><p>Woah! What happened? We see a drastic change in the average ending balance. But, why did that happen? We can clearly see that on the basis of how much payout percentage the casino gives, we can identify what the average outcome would be by the end of night. Therefore, if the casino chooses to give 6 times / 600% of the betting amount as prize money, they would essentially lose money on an average! But, if the casino keeps the prize money at 400%, which is still pretty generous, they would end up staying at top after the night ends.</p><p>Pretty interesting, right?</p><div><hr></div><h3><strong>Some other business use cases</strong></h3><p>We saw how Monte Carlo Methods can help businesses predict the outcome of events with random variables on an average thus helping them make better decisions.</p><p>Where else can we use this? There is certainly no limit to one&#8217;s imagination when it comes to applications of this method, for exampling, for a marketing manager, Monte Carlo Analysis of CAC (Cost of Acquiring a Customer) through paid marketing with variables such as Cost per lead could tell the business how much they should be paying per lead to stay profitable OR for a sales manager, after a new product is launched, this analysis with variables such as profits and expenses on selling a product in market mixed with it&#8217;s demand could help them forecast what factors need to be controlled in order to help them sell more while staying profitable.</p><div><hr></div><p>Thank you for reading this article! Kindly leave a clap in case you found this interesting. :)</p>]]></content:encoded></item><item><title><![CDATA[How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API]]></title><description><![CDATA[Let&#8217;s jump right in!]]></description><link>https://techuntethered.com/p/how-to-interact-read-write-data-to-your-google-sheets-using-python-and-google-sheets-api</link><guid isPermaLink="false">https://techuntethered.com/p/how-to-interact-read-write-data-to-your-google-sheets-using-python-and-google-sheets-api</guid><dc:creator><![CDATA[Prateek Jain]]></dc:creator><pubDate>Wed, 23 Feb 2022 07:59:32 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d236f1a1-27d5-4c48-a5d4-c0ece8b3c26f_640x230.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4w4E!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4w4E!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 424w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 848w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 1272w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4w4E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!4w4E!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 424w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 848w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 1272w, https://substackcdn.com/image/fetch/$s_!4w4E!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7fcf5484-ab64-46d9-8235-cc4e9717c232_640x230.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></a><p>Let&#8217;s jump right in!</p><p><strong>Steps:</strong><br>1. Enabling Google Sheets API<br>2. Creating Service / OAuth Credentials<br>3. Creating a function in Python to read / write data from / to Google Sheets.<br>4. Importing the function and using it</p><div><hr></div><p><strong>Enabling Google Sheets API</strong></p><p>Pre-requisites: You should have a personal (yourname@gmail.com) or a company (yourname@yourcompany.com) Google Account</p><p>Steps:</p><ul><li><p>Go to <a href="https://console.cloud.google.com/?ref=prateekja.in">Google Console</a> and login with your Google Account (if not already logged in)</p></li><li><p>On the header, create a new project: (Click on the dropdown that says &#8220;My First Project&#8221; in my case)</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!U4Lk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!U4Lk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 424w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 848w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 1272w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!U4Lk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png" width="1392" height="260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:260,&quot;width&quot;:1392,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!U4Lk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 424w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 848w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 1272w, https://substackcdn.com/image/fetch/$s_!U4Lk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a64e0f3-fdc4-4889-bc25-1b02dd9c34b1_800x149.png 1456w" sizes="100vw"></picture><div></div></div></a></figure></div><ul><li><p>From the dialogue box that opens up, click on &#8220;New Project&#8221; and give your project a name of your choosing and under location you can either keep it as default (No Organization) or select your organization, if listed. <br>Click on Create.</p></li><li><p>Google Cloud will automatically create a project for you and once it&#8217;s done, select the created project from the same dropdown in the header as done in Step 2.</p></li><li><p>After selecting your newly created project, your screen should look something like this:</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FyRe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FyRe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 424w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 848w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 1272w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FyRe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png" width="2000" height="1028" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d47a222-361c-4942-ab87-127bd4471318_800x411.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1028,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!FyRe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 424w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 848w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 1272w, https://substackcdn.com/image/fetch/$s_!FyRe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d47a222-361c-4942-ab87-127bd4471318_800x411.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>In the search bar, search for &#8220;Google Sheets API&#8221; and click on the first result and click on &#8220;Enable&#8221; on the screen that follows.</p></li></ul><p>Congratulations! You have successfully enabled the Google Sheets API for your account. Now we&#8217;ll set up our credentials so that our Python Script can authenticate and interact with the API.</p><div><hr></div><p><strong>Creating Service / OAuth Credentials</strong></p><p>After the above steps, you should have landed on a page which looks like this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wawY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wawY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 424w, https://substackcdn.com/image/fetch/$s_!wawY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 848w, https://substackcdn.com/image/fetch/$s_!wawY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 1272w, https://substackcdn.com/image/fetch/$s_!wawY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wawY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png" width="2000" height="1028" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8a211529-5489-4515-9266-3af161372b5e_800x411.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1028,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!wawY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 424w, https://substackcdn.com/image/fetch/$s_!wawY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 848w, https://substackcdn.com/image/fetch/$s_!wawY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 1272w, https://substackcdn.com/image/fetch/$s_!wawY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a211529-5489-4515-9266-3af161372b5e_800x411.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>From the side navigation bar, click on &#8220;<strong>Credentials</strong>&#8221; and click on &#8220;<strong>+ CREATE CREDENTIALS</strong>&#8221; from the sub-header and select &#8220;<strong>OAuth client ID&#8221;</strong>. (We will be setting our credentials up using <strong>OAuth</strong> because that is what I personally prefer due to an advantage it gives us over Service Account Credentials.)</p><p>From the screen that follows, click on &#8220;<strong>CONFIGURE CONSENT SCREEN</strong>&#8221;.</p><p>If you are setting this up from your company&#8217;s Google Account, then click on &#8220;<strong>Internal</strong>&#8221;, otherwise click on &#8220;<strong>External</strong>&#8221; on the &#8220;<strong>User Type&#8221; </strong>section of the OAuth Consent Screen and click on &#8220;<strong>CREATE&#8221;</strong>.</p><p>You will then be taken to a 4-Step process of configuring your consent screen.</p><ul><li><p>On the &#8220;App Information&#8221; page, fill in your &#8220;App Name&#8221; (It can be a random name since you are not opening up this functionality to any third party user and is entirely internal to your use), your email ID under the &#8220;User support email&#8221; and the &#8220;Developer contact information&#8221; field (towards the end of the page) and click on &#8220;SAVE AND CONTINUE&#8221;. You may leave the remaining fields empty since they are optional.</p></li><li><p>On the &#8220;SCOPES&#8221; page, click on &#8220;ADD OR REMOVE SCOPES&#8221;. From the page that pops up, search for &#8220;Google Sheets API&#8221; as shown below and select all the scopes that show up and click on &#8220;UPDATE&#8221;.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KCsk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KCsk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 424w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 848w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 1272w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KCsk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png" width="1500" height="1582" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1582,&quot;width&quot;:1500,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!KCsk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 424w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 848w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 1272w, https://substackcdn.com/image/fetch/$s_!KCsk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4e8c6710-7071-4715-86cd-519b2d5424dd_800x844.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>After clicking on Update in the above screenshot, this page will automatically close and you will see your scopes added on the page. Scroll down to the bottom and click on &#8220;SAVE AND CONTINUE&#8221;.</p></li><li><p>Under Test Users add your email ID as the test user and directly press &#8220;SAVE AND CONTINUE&#8221;. (This page will not show up if you are on a company account and you chose User Type as Internal on the first page.)</p></li><li><p>Scroll down on the Summary page and click on &#8220;BACK TO DASHBOARD&#8221;</p></li></ul><p>Click on &#8220;CREDENTIALS&#8221; page on the side navigation bar again and click on &#8220;<strong>+ CREATE CREDENTIALS</strong>&#8221; and choose &#8220;OAuth Client ID&#8221;. Choose the Application Type as &#8220;Desktop App&#8221; and give it a random name and click on create. You will now a screen similar to below screen:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CioH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CioH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 424w, https://substackcdn.com/image/fetch/$s_!CioH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 848w, https://substackcdn.com/image/fetch/$s_!CioH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 1272w, https://substackcdn.com/image/fetch/$s_!CioH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CioH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png" width="1052" height="928" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:928,&quot;width&quot;:1052,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" title="How to interact (read / write) data from/to your Google Sheets using Python and Google Sheets API" srcset="https://substackcdn.com/image/fetch/$s_!CioH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 424w, https://substackcdn.com/image/fetch/$s_!CioH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 848w, https://substackcdn.com/image/fetch/$s_!CioH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 1272w, https://substackcdn.com/image/fetch/$s_!CioH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a5bb111-3aec-4337-ac69-21b55d3b9051_800x706.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Download the JSON on your computer, we will be using this later.</p><p>Congratulations! Now you have successfully setup credentials to authenticate with your Google Sheets API.</p><div><hr></div><p><strong>Creating a function in Python to read / write data from / to Google Sheets.</strong></p><p>At this point, I am assuming you already have python installed in your system and you are ready to install and use new libraries.</p><p>Before we begin writing our script, we require some libraries for our script to utilise. Install the libraries using the following commands: (Open your terminal and run the following commands)# Will upgrade your pip to the latest versionpip install --upgrade pip# Installing gspread library and a third-party library to convert data from gspread to a dataframepip install gspread gspread-dataframe# Installing oauth2client for authenticationpip install oauth2client</p><p>Once all the above commands run successfully, you will have downloaded the required libraries in your system.</p><p>Let&#8217;s jump right in to create functions which will help us read/write data from/to our Google Sheet.</p><p>In the code above, &#8220;credentials&#8221; variables refer to the file path to your client secrets JSON which you downloaded in the previous step and &#8220;storage&#8221; variables refer to your storage.json file path. (Remember, storage.json should be created as an empty JSON file while running the code for the first time for the code to automatically generate access tokens and store in your storage.json file for the subsequent uses)</p><p>The &#8220;sheet_name&#8221; variable refers to the sheet in your workbook from / to where you want to read / write the data. For example, in your Google Sheet, you have a tab named &#8220;Sheet 1&#8221;, then &#8220;Sheet 1&#8221; shall be passed in your as your sheet_name argument.</p><p>The &#8220;dataframe&#8221; variable in the googleSheetWrite function takes in the dataframe which needs to be posted in the given sheet_name.</p><p>The &#8220;sheet_url&#8221; variable takes in the complete URL of the workbook where all this data needs to be written.</p><p>The &#8220;boolean&#8221; variable in the googleSheetWrite function takes in True or False values. If you pass True, then the function will remove all existing data from the sheet and paste your mentioned dataframe in the sheet else it will overwrite only the cells according to the shape of your dataframe.</p><p>The &#8220;row&#8221; and &#8220;col&#8221; variables take in integer values to mention the Row Number and Column Number from where the dataframe needs to start pasting. For example, if your row = 1 and col = 1, the the data will be pasted from A1, if row = 2 and col = 1, then the data will be pasted from A2, if row =1 and col = 2, then the data will be pasted from B1 and so on.</p><p>In the googleSheetRead function, &#8220;col&#8221; variable refers to an array of column numbers to be read as a dataframe from the given sheet_name and sheet_url.</p><p>For example, if you want to read data from columns A,B,C in the sheet,<br>col = [0,1,2], if you want to read only columns A and C, then,<br>col = [0,2].</p><p>Please note that the googleSheetRead function will also return the empty cells in the sheet as null values. You can drop the null rows using dropna() function of pandas.DataFrame.</p><p>Congratulations, now you can easily read / write data from any Google Sheet that is shared with an Editor Access with the Google Account that you generated the credentials from!</p>]]></content:encoded></item></channel></rss>