<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Writing on Vinoo Ganesh</title>
    <link>https://vinoo.io/writing/</link>
    <description>Recent content in Writing on Vinoo Ganesh</description>
    <image>
      <title>Vinoo Ganesh</title>
      <url>https://vinoo.io/img/vinoo.jpg</url>
      <link>https://vinoo.io/img/vinoo.jpg</link>
    </image>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://vinoo.io/writing/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The Definitive Guide to Forward Deployed Engineering</title>
      <link>https://vinoo.io/writing/2026-02-05-forward-deployed-engineering/</link>
      <pubDate>Thu, 05 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2026-02-05-forward-deployed-engineering/</guid>
      <description>A comprehensive guide to Forward Deployed Engineering - the role, the skills, the career path, and how Palantir&amp;#39;s Project Frontline scaled FDE culture across the industry.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://nextplayso.substack.com/p/the-definitive-guide-to-forward-deployed">Next Play</a></em></p>
<p>If you work in tech, you should learn about Forward Deployed Engineering (FDE). It&rsquo;s quickly become one of the most popular roles that nearly all fast-growing AI companies are looking for&hellip;at the same time, it&rsquo;s the type of role very few people and companies seem to <em>actually</em> understand.</p>
<p>I designed Project Frontline at Palantir, a program that sent over 250 engineers into live customer deployments. Those engineers are now at OpenAI, xAI, Anduril, and dozens of leading companies.</p>
<h2 id="the-bottom-line">The Bottom Line</h2>
<p>The Forward Deployed Engineer (FDE) has become the most valuable credential in tech, and most people don&rsquo;t understand why.</p>
<p>If you look at job postings at OpenAI, xAI, Anthropic, Helsing, Anduril, Scale, or Palantir, you&rsquo;ll notice they&rsquo;re not just looking for software engineers. They&rsquo;re looking for engineers who can deploy, who can sit with customers, who can make software work in the real world.</p>
<p>Here&rsquo;s what you need to know:</p>
<p>An FDE is a software engineer who owns customer outcomes. Not customer relationships, not customer satisfaction scores, but outcomes: the actual results the customer is trying to achieve with the software. This distinction sounds subtle, but it changes everything. A sales engineer&rsquo;s job is to help close the deal. A solutions architect designs how the product fits the customer&rsquo;s environment. An FDE&rsquo;s job is to make sure the customer actually wins.</p>
<p>The critical insight is that you can&rsquo;t easily hire your way to a true FDE organization. The skill set is too rare, too specific, too dependent on experiences most engineers never have. Traditional engineering jobs don&rsquo;t build this skill set because they&rsquo;re structured to insulate engineers from customer reality. You write code, you ship it, you move to the next ticket. You never feel the weight of a customer depending on your work, never see what happens when your elegant system meets messy real-world data, never have to look someone in the eye and explain why the thing they needed isn&rsquo;t working.</p>
<p>So how do you hire forward deployed engineers? You don&rsquo;t. You grow them.
This was Palantir&rsquo;s critical insight, and it took us years to fully understand it. The only way to build an FDE organization is to take talented people and put them through a crucible that transforms how they think about building software.</p>
<p>Why this matters now: Three forces are making the FDE model the default rather than the exception.</p>
<p>First, AI is making deployment harder, not easier. AI systems require fine-tuning, prompt engineering, evaluation, and ongoing adjustment. You can&rsquo;t throw an LLM over the wall and expect customers to figure it out. OpenAI, Anthropic, xAI, and every serious AI company is building FDE-style functions, even if they don&rsquo;t call them that. There&rsquo;s a related point here about what it means to be an engineer at all: if AI can do much of what junior engineers used to do, the engineers who remain valuable are the ones who can do what AI can&rsquo;t, which is sit with a customer, understand their real problem, and own the outcome.</p>
<p>Second, defense tech is exploding. Anduril, Palantir, Shield AI, and dozens of startups are building software for military and government customers who can&rsquo;t tolerate deployment failure. These customers operate in austere environments with unique constraints, and you can&rsquo;t support them with a helpdesk. You need engineers in the field.</p>
<p>Third, enterprise buyers are getting smarter. After decades of shelfware, enterprises are starting to demand implementation guarantees. They want to see engineers on site and know that someone will own the deployment, not just the sale. The vendors who can deliver this will win.</p>
<p>Five years from now, I expect every serious enterprise software company to have an FDE function. If you&rsquo;re thinking about where to invest your career, this is the trend to bet on.</p>
<h2 id="why-this-matters-now">Why This Matters Now</h2>
<p>Three forces are making the FDE model increasingly standard:</p>
<p><strong>First, AI is making deployment harder.</strong> AI systems require fine-tuning, prompt engineering, evaluation, and ongoing adjustment. You cannot simply deploy an LLM and expect customers to figure it out. Companies like OpenAI, Anthropic, and xAI are building FDE-style functions, even if they use different terminology.</p>
<p><strong>Second, defense tech is exploding.</strong> Companies like Anduril and Palantir build software for military and government customers who cannot tolerate deployment failure. These customers operate in austere environments with unique constraints that require engineers in the field, not helpdesk support.</p>
<p><strong>Third, enterprise buyers are getting smarter.</strong> After decades of expensive software sitting unused, enterprises are demanding implementation guarantees and want to see engineers on site who own deployments, not just sales.</p>
<h2 id="the-grey-track-jacket">The Grey Track Jacket</h2>
<p><img alt="My Grey Track Jacket" height='Ұ' loading="lazy" src="/writing/2026-02-05-forward-deployed-engineering/grey-track-jacket_hu_f738f0516d238b25.webp" width='̠'></p>
<p>At Palantir, everyone got a black track jacket. Standard issue. But there was another jacket, a grey one, that you couldn&rsquo;t buy or request.</p>
<p>The mythology was that your black jacket had faded through years of experience, that you&rsquo;d worn it through enough deployments and enough hard field work that the black had burned away and become grey. Leadership awarded them when you had proven yourself in the field.</p>
<p>Brian Schimpf, now CEO of Anduril, awarded these jackets when he was one of Palantir&rsquo;s senior engineering leaders. When I got mine, I didn&rsquo;t feel pride or accomplishment. I felt the weight of what it represented: the late nights, the systems that failed, the customers who&rsquo;d depended on me when things went wrong. The jacket wasn&rsquo;t a trophy. It was an acknowledgment that you&rsquo;d been through something, and that something had changed you.</p>
<p>When engineers ask me how to become an FDE, they want skills to develop, certifications to get, keywords for their resume. But that&rsquo;s not what this is about. The jacket was just the symbol. The transformation is what matters.</p>
<p>When I received my grey jacket, I did not feel pride or accomplishment. I felt the weight of what it represented: the late nights, the systems that failed, the customers who depended on me when things went wrong. The jacket was not a trophy. It was acknowledgment that you had been through something, and that something had changed you.</p>
<h2 id="my-transformation">My Transformation</h2>
<p><em>If you want concrete recommendations on how to become an FDE, skip to &ldquo;The Playbook&rdquo; at the end. But if you want to understand why this transformation matters and what it actually feels like, read on.</em></p>
<p>I joined Palantir on the product development side in Palo Alto. I fixed Jira tickets, wrote code, built tests, did code reviews, architected systems. I attended sprint planning and hit my deadlines. By every internal metric, I was doing good work.</p>
<p>But once I rotated into the field, what I saw broke how I understood my own job.</p>
<p>We had a product called Phoenix. It worked beautifully for the use case it was designed for. Clean architecture, solid code, good test coverage. We were proud of it.</p>
<p>Then I watched it fail.</p>
<p>The system relied on a data integration that seemed straightforward: when new data comes in, we generate a keyspace in Apache Cassandra. We&rsquo;d designed it to create keyspaces in 10-minute increments for easy automated deletion. We thought it felt like a clever trick.</p>
<p>Then bad data came in. Well, specifically, no data came in. The date column was empty. Our system interpreted this as the epoch: January 1, 1970. So it did exactly what it was designed to do, and generated every keyspace between January 1, 1970 and October 7, 2013.</p>
<p>That&rsquo;s 2.3 million keyspaces. Cassandra requires roughly 5MB per column family. You&rsquo;d need 14 terabytes of RAM just to start up.</p>
<p>The system OOMed on startup. As was commonly said at Palantir back then, &ldquo;bad times on boats.&rdquo;</p>
<p>I sat there watching this happen, and I realized something that should have been obvious: we had never seen the data this system would actually process. We had never been in the room when garbage data showed up at 2am. We had never had to look a customer in the eye and explain why the system they depended on was suddenly unresponsive.</p>
<p>This wasn&rsquo;t a one-time thing. I saw it again on other projects. We would build something elegant and technically sophisticated, ship it to the field, and watch it collide with reality in ways we never anticipated. The pattern was always the same: we built without understanding, optimized for the wrong things, and solved problems that didn&rsquo;t exist while ignoring problems that did. The gap between what we were building and what users actually needed wasn&rsquo;t a small gap. It was a chasm.</p>
<p>After that first experience, I kept going back to the field: NYC, Singapore, Afghanistan, Israel, UAE, Toronto, SF, Mumbai, and government deployments I can&rsquo;t name. I spent hours in SCIFs working through data integrations across multiple networks. My laptop once overheated and nearly melted sitting in a car in the Middle East.</p>
<p>Each field experience taught me something new about the distance between building software and deploying it, about what happens when your code meets reality, about the difference between solving a problem in theory and solving it for a real human being who needs it to work right now.</p>
<p>I alternated between software engineering and forward deployed work for years, going back and forth between building and deploying. Each time I returned to product development, I built differently. I asked different questions and anticipated different failures. I understood, in a way I couldn&rsquo;t have before, what the software was actually for.
That oscillation changed me. And I became convinced it could change others.</p>
<h2 id="why-this-model-works">Why This Model Works</h2>
<h3 id="the-business-case">The Business Case</h3>
<p>The business case is simple: software that actually gets adopted is worth infinitely more than software that sits on a shelf.</p>
<p>Most enterprise software fails to deliver value not because it doesn&rsquo;t work technically, but because it never gets properly deployed, configured, adopted, and integrated into customer workflows. The industry&rsquo;s dirty secret is that a huge percentage of enterprise software purchases end up as shelfware. Customers buy it, try to implement it, hit friction, and give up.</p>
<p>Companies with an FDE model don&rsquo;t have this problem. Their software gets used because there&rsquo;s an engineer on site making sure it gets used. Problems get solved in real time, configurations get tuned to actual workflows, and edge cases get handled before they become blockers.</p>
<p>This creates a flywheel: deployed software generates feedback, feedback improves the product, better products deploy more easily, easier deployment means more customers, and more customers means more feedback.</p>
<p>Palantir generates over $1.1 billion in annual revenue from just their top 20 customers. That&rsquo;s not because the software is marginally better than competitors. It&rsquo;s because Palantir engineers own customer outcomes in a way that traditional enterprise software vendors simply don&rsquo;t.</p>
<p>The other reason companies want FDEs is that they&rsquo;re the best source of product insight. Engineers who work directly with customers see things that product managers reading survey data never see. They understand the actual workflows, the real constraints, the true pain points. The best product ideas at Palantir came from FDEs who&rsquo;d spent enough time in the field to understand what needed to be built.</p>
<p>One deployment I worked on had over fifty data pipelines running daily, and monitoring them was a nightmare. A few engineers who&rsquo;d experienced this pain firsthand built a pipeline monitoring tool that got deployed across multiple sites. They didn&rsquo;t build it because a PM told them to. They built it because they&rsquo;d felt the problem themselves.</p>
<p>That&rsquo;s the FDE advantage: engineers who build from experience, not from specs.</p>
<h3 id="a-correction-not-a-trend">A Correction, Not a Trend</h3>
<p>For a long time, the software industry optimized for building at scale while pushing deployment complexity onto customers and divorcing engineering from the business problems it was supposed to solve. The prevailing model was simple: throw it over the wall, let the customer figure it out, and hire systems integrators to clean up the mess.</p>
<p>This worked when software was simple and customers were patient, but neither of those things is true anymore.</p>
<p>The companies winning right now are the ones who own the full loop of building and deploying. They don&rsquo;t hand off to SI firms or blame customers for implementation failures. They send engineers into the field who own outcomes, not just outputs.</p>
<p>Palantir figured this out twenty years ago and got criticized for it. The criticism was relentless: &ldquo;It&rsquo;s not scalable.&rdquo; &ldquo;It&rsquo;s just consultants.&rdquo; &ldquo;It&rsquo;s not a real software company.&rdquo; Now everyone is trying to copy the model.</p>
<p>The problem is, you can&rsquo;t hire your way to an FDE organization.</p>
<h3 id="building-frontline-the-program-that-scaled-it">Building Frontline: The Program That Scaled It</h3>
<p>To really understand FDE, you need to understand Frontline.</p>
<p>At the time, Palantir had two organizations that didn&rsquo;t understand each other. Product Development (PD) built the software while Business Development (BD), which included the forward deployed engineers) put it in front of customers. The two groups were culturally and operationally separate, and that separation was causing real damage.</p>
<p>PD thought BD lacked technical rigor. BD thought PD lacked urgency. Deploying the product was painful, sometimes taking days or weeks. Engineers in the field drowned in problems that engineers in headquarters had never seen, while engineers in headquarters built features that solved the wrong problems because they&rsquo;d never felt the pain of the people using their software.</p>
<p>The best way to understand someone is to walk a mile in their shoes. We decided to make that literal.</p>
<p>Project Frontline was born from this insight. Software engineers would spend time in the field doing a forward deployed rotation before formally beginning their product development work. They would see how the software actually got used, feel the pain of deployment, and understand viscerally the gap between what we built and what customers needed. Then they would come back and build differently.</p>
<p>I had the opportunity to lead Frontline alongside Palantir&rsquo;s senior leadership: Matt Steckman, John Garrod, Bill Ward, Lynne Lu, and Randy Schults. Shyam Sankar, Palantir&rsquo;s now CTO, was directly involved, sitting in on our update meetings as we figured out what was working and what wasn&rsquo;t. This wasn&rsquo;t a side project. It was a strategic priority.</p>
<p>We learned quickly that throwing engineers into the field wasn&rsquo;t enough. They needed support and structure. Every Frontliner got a mentor who had been through the experience, who could guide them through the disorientation of going from building software to deploying it. They got leads who checked in frequently, not just to track progress but to surface problems early. We created feedback loops throughout the rotation so that when someone was struggling, we caught it early, and when something wasn&rsquo;t working, we heard about it fast.</p>
<p>We made mistakes along the way. The six month rotation timeline was supposed to be a guideline, but resourcing pressures sometimes stretched rotations to a year, and engineers felt stuck. There was friction between existing FDEs and the rotators, along with cultural clashes and different working styles.</p>
<p>We also discovered something crucial: often, the rotations weren&rsquo;t connected to the products engineers would eventually build. Someone would spend six months deploying software they would never touch again. They learned valuable things, but the connection was abstract. So we started aligning rotations with future product work. If someone was going to build pipeline monitoring tools, we sent them to deployments where pipeline monitoring was a problem.</p>
<p>They became users before they became builders.</p>
<p>This was transformative. When engineers experienced the pain of problems they would later fix, something clicked. They built with emotion and passion, with a deep understanding of what users actually needed. You could feel it in the products. The software wasn&rsquo;t just technically good; it was designed by people who cared, who had been there, who understood.
Over time, the program scaled. Over 250 engineers rotated through Frontline, and it stopped being an experiment and became the way things worked.</p>
<p>The proof is in what happened to the people who went through it. Frontline alumni are now at OpenAI, xAI, Helsing, Anduril, Hex, and dozens of other companies building important things. Bill Ward, who co-led Frontline, started Northslope Technologies, which offers FDE as a service. Jesse Rickard started Fourth Age, which does something similar. The model we built is now being replicated across the industry.</p>
<h2 id="what-makes-someone-great-at-this">What Makes Someone Great at This</h2>
<p>I&rsquo;ve watched hundreds of engineers go through the FDE crucible. Some became exceptional while others washed out. Here&rsquo;s what separates the great ones.</p>
<p><em>Great FDEs are relentlessly curious about the customer&rsquo;s world.</em> Good FDEs solve the problems they&rsquo;re given, but great FDEs understand the customer&rsquo;s business well enough to surface problems the customer had given up on or hadn&rsquo;t yet articulated. In other words, as I said above, they become users before they become builders.  I once spent a week at a customer site and noticed that every morning, an analyst spent 45 minutes manually downloading data from three different systems and combining them in Excel before she could start her actual work. She&rsquo;d been doing this for two years and had never thought to ask if it could be automated. She&rsquo;d just accepted it as part of her job. A good FDE would have built what she asked for. I built a pipeline that did her morning routine automatically and had it waiting in her inbox when she arrived. That&rsquo;s the difference.</p>
<p><em>Great FDEs calibrate their engineering to the situation.</em> They know when to build a robust system and when to write a script that just works. Here&rsquo;s a failure story: early in my FDE career, a customer asked for a way to deduplicate records. I spent two weeks building an elegant, configurable deduplication engine with fuzzy matching, confidence scores, and a review interface. What they actually needed was a SQL query that ran once to clean up a specific data import. They never used the engine again. I&rsquo;d overengineered by 10x. The opposite failure is equally painful: I once hacked together a &ldquo;temporary&rdquo; data deletion script that ended up running in production for eighteen months (vinoo.groovy, a name many of my old Palantir teammates still call me).</p>
<p><em>Great FDEs communicate across audiences.</em> They can explain complex systems to executives who don&rsquo;t care about the details and dive deep with technical counterparts who need to understand exactly how something works. In one meeting, I had to explain why a migration would take three months instead of three weeks. To the CTO, I said: &ldquo;The data has 15 years of accumulated edge cases that will break downstream reports if we don&rsquo;t handle them carefully. Rushing it risks the quarterly board reporting.&rdquo; To the engineering lead, I said: &ldquo;There are 847 columns across 12 tables with undocumented interdependencies, and the existing ETL has implicit type coercions that we need to preserve or we&rsquo;ll get silent data corruption.&rdquo; Same problem, different language.</p>
<p><em>Great FDEs stay calm when things break.</em> And things will break. I remember a deployment where the customer&rsquo;s CEO was demoing our product to their board when it crashed. My phone rang. Instead of panicking, I talked the customer&rsquo;s IT person through restarting the service (which I knew would work because I&rsquo;d diagnosed the root cause earlier that week), and the demo was back up in four minutes. The CEO never knew there was an engineer on the phone. How you handle a crisis matters as much as whether you fix it.</p>
<p><em>Great FDEs own outcomes without having authority.</em> This is the hardest skill. Once, I needed a product team to prioritize a bug fix that was blocking a major customer. I had no authority over that team. What didn&rsquo;t work: &ldquo;Can you please prioritize this bug?&rdquo; What did work: &ldquo;This customer represents $4M in annual revenue and their renewal is in six weeks. They&rsquo;ve told their exec sponsor that this bug is their top complaint. If we don&rsquo;t fix it, we risk losing the renewal, and I can get you a call with the customer to hear it directly if that would help.&rdquo; I got the fix in two days.</p>
<p><em>Great FDEs know when to push back.</em> They don&rsquo;t just do whatever customers ask. Once, a customer demanded we build a custom feature that would have taken three months of engineering time. Instead of saying yes or no, I spent two days understanding why they wanted it. It turned out they were trying to solve a problem that our existing product could handle with a configuration change. I showed them how to do it, and they were happier with that solution than they would have been with the custom feature. Pushing back isn&rsquo;t about saying no. It&rsquo;s about understanding the real need and finding the right solution.</p>
<p><img alt="The Palantir Singapore FDE team debugging an outage (h/t Satej Soman for the photo)" height='ɘ' loading="lazy" src="/writing/2026-02-05-forward-deployed-engineering/singapore-team_hu_ffaee4867e426ddb.webp" width='̠'></p>
<h2 id="why-you-might-not-want-this">Why You Might Not Want This</h2>
<p>I&rsquo;ve spent this essay explaining why FDE is valuable. Now let me tell you why it might not be right for you.</p>
<p>If you need deep focus time, this isn&rsquo;t your path. FDE work is interrupt-driven, with customers having emergencies and deployments hitting unexpected problems. Your calendar will look like that week I described above: chaotic, fragmented, constantly shifting.
If ambiguity paralyzes you, stay away. FDEs operate with incomplete information constantly. Requirements are unclear, priorities shift, and you have to make decisions without knowing if they&rsquo;re right.</p>
<p>If you want to go deep on a technical specialty, look elsewhere. FDEs are generalists by necessity. You&rsquo;ll learn a lot about a lot of things, but you won&rsquo;t become a world expert in any of them. If your goal is to be the best in the world at distributed systems or machine learning, pure product engineering is a better path.</p>
<p>If you take customer frustration personally, you&rsquo;ll burn out. Customers get frustrated and blame you for things that aren&rsquo;t your fault.</p>
<p>If you can&rsquo;t set boundaries, you&rsquo;ll work yourself to death. FDE work expands to fill all available time. I&rsquo;ve seen talented people burn out because they couldn&rsquo;t say no.</p>
<p>These aren&rsquo;t weaknesses; they&rsquo;re just characteristics that make FDE a bad fit. There are plenty of great engineering roles for people who have them.</p>
<h2 id="the-playbook">The Playbook</h2>
<h3 id="manufacturing-your-own-field-exposure">Manufacturing Your Own Field Exposure</h3>
<p>Most of you reading this don&rsquo;t work at a company with a Frontline program. Nobody is going to hand you this experience, so you have to create it yourself. Here&rsquo;s exactly how to do it.</p>
<p><em>Week 1-2</em>: Get on customer calls. Email your PM or customer success lead today with this exact message: &ldquo;I want to understand our customers better so I can build more robust features. Can I sit in on 2-3 customer calls over the next few weeks? I&rsquo;ll be on mute, just observing.&rdquo; Almost no one will say no to this. On the calls, don&rsquo;t take notes on feature requests. Take notes on these things: What does this person&rsquo;s day look like? What did they do before this call? What will they do after? What do they seem frustrated by that they&rsquo;re not explicitly complaining about? What workarounds are they using?</p>
<p><em>Week 3-4</em>: Shadow support or implementation. Find whoever handles customer escalations or implementations at your company. Ask to shadow them for three days. If you work remotely, ask to be added to their Slack channels and get on video calls with them when issues come in. Watch how problems get diagnosed. Notice the gap between what customers say is wrong and what&rsquo;s actually wrong. Pay attention to which parts of your product cause the most confusion.</p>
<p><em>Month 2</em>: Take an escalation. When a customer issue comes in, volunteer to own it end-to-end. Not just fix the bug, but talk to the customer, understand the impact, communicate the timeline, deploy the fix, and confirm it&rsquo;s resolved. This is the full loop. It will be uncomfortable. You will learn more from this one experience than from months of normal development work.</p>
<p><em>Month 3</em>: Visit a customer site (or do a deep-dive remote session). If your company has customers you can visit, ask to join a site visit. If not, ask if you can do a 2-hour screen-share session with a customer where you watch them use the product for their actual work, not a demo, not a training session, their actual job. While you&rsquo;re watching, identify one papercut you can fix in under a day. Then fix it and ship it before the week is over. Tell them you did it. This builds trust and goodwill like nothing else.</p>
<p><em>Month 4-6</em>: Build your feedback loop. By now you should have enough context to start seeing patterns. Create a simple document titled &ldquo;What I&rsquo;ve Learned From Customers&rdquo; and update it weekly. Share it with your product team. Include specific quotes, specific workflows, specific pain points. This document will make you invaluable. It will also prepare you for FDE interviews, where you&rsquo;ll need to demonstrate customer empathy.</p>
<h3 id="developing-the-six-traits">Developing the Six Traits</h3>
<p><em>Curiosity</em> is really about empathy. It develops when you force yourself out of the codebase and into the customer&rsquo;s environment. The next time you&rsquo;re on a customer call or a site visit, don&rsquo;t just listen for feature requests. Try to understand the customer&rsquo;s day: what are they doing before they open your software, what are they doing after, and what are the three things keeping them up at night that have nothing to do with your product?</p>
<p><em>Calibration</em> comes from getting it wrong in both directions. You need both scars. Deliberately vary your approach: on your next project, try solving it with the simplest possible thing, and on the one after, try building it properly. Pay attention to which approach the situation actually called for.</p>
<p><em>Communication</em> is a muscle you have to exercise. Think of it like the game of telephone: every time a message passes through another person, it degrades. FDEs short-circuit that chain. Practice writing one-page summaries of technical projects for non-technical stakeholders. If you can&rsquo;t explain what you built and why it matters in one page without jargon, you don&rsquo;t understand it well enough.</p>
<p><em>Staying calm</em> is about preparation and repetition, not personality. Put yourself in high-pressure situations voluntarily: volunteer for the on-call rotation, take the escalation, join the war room when production is down. By the tenth time, you&rsquo;ll have a playbook in your head.</p>
<p><em>Owning outcomes without authority</em> develops when you put yourself in situations where you need something from someone who doesn&rsquo;t report to you. Learn to make requests that explain the why, not just the what.</p>
<p><em>Pushing back effectively</em> runs on credibility. Think of credibility as points you can spend or lose. Early on, pick your battles carefully. The key is to always push back with an alternative, not just a no.</p>
<h3 id="what-you-should-actually-know-technically">What You Should Actually Know Technically</h3>
<p>FDEs are generalists, but that doesn&rsquo;t mean you can be shallow on everything. Here&rsquo;s the specific technical knowledge you need.</p>
<p><em>The XY Problem</em>. Customers will ask you for Y when what they actually need is a solution to X. Practice by asking &ldquo;what are you trying to accomplish?&rdquo; before jumping to solutions.</p>
<p><em>SQL</em>. JOINs, GROUP BY with HAVING, window functions, CTEs, subqueries. Target: write a query that finds &ldquo;the second-highest value per category&rdquo; without Googling. Data is objective and data analysis is your lifeblood.</p>
<p><em>Command line and Linux</em>. Navigating the filesystem, reading logs (grep, awk, tail -f), understanding processes (ps, top, kill), basic networking (curl, netstat, ping, traceroute). Know what &ldquo;out of inodes&rdquo; means. Resource: OverTheWire Bandit.</p>
<p><em>Containers</em>. What Docker does, difference between container and VM, where logs go. What Kubernetes does at a high level. Resource: Docker&rsquo;s getting started guide.</p>
<p><em>Networking</em>. DNS, HTTP status codes, TLS/SSL basics, debugging when you can ping but can&rsquo;t connect. Resource: Julia Evans&rsquo; zines.</p>
<p><em>Python scripting</em>. Read a CSV, transform data, write it somewhere. Call an API, handle pagination. Connect to a database. Be fast. Resource: Automate the Boring Stuff with Python.</p>
<p><em>Data quality</em>. What happens with timezone mismatches, encoding issues, unexpected nulls. The Cassandra story I told? That&rsquo;s a data quality issue.</p>
<h3 id="getting-hired-what-interviewers-actually-ask">Getting Hired: What Interviewers Actually Ask</h3>
<p>FDE interviews are heavy on behavioral questions because the job is about judgment, not just technical skill.</p>
<p><em>&ldquo;Tell me about a time you had to work with a difficult customer.&rdquo;</em> Bad: &ldquo;The customer was being unreasonable, but I stayed calm and eventually they came around.&rdquo; Good: &ldquo;The customer was frustrated because our product had lost their data. They were angry, and honestly, they had a right to be. I started by acknowledging that we&rsquo;d screwed up, not making excuses. Then I explained exactly what had happened, what we were doing to recover the data, and what we were doing to make sure it never happened again. I also gave them my cell phone number and told them to call me directly if anything else went wrong. It took two weeks, but by the end they renewed their contract.&rdquo;</p>
<p><em>&ldquo;Tell me about a time you disagreed with a customer&rsquo;s request.&rdquo;</em> Bad: &ldquo;The customer wanted something that didn&rsquo;t make sense, so I explained why they were wrong.&rdquo; Good: &ldquo;The customer wanted us to build a custom dashboard that would have taken a month of engineering time. Instead of saying no, I asked them to walk me through exactly how they&rsquo;d use it. It turned out they needed to answer a specific question for a weekly meeting. I showed them how to get that answer with our existing product plus a 10-minute SQL query. They were actually happier with that solution because they got it that day instead of waiting a month.&rdquo;</p>
<p><em>&ldquo;Tell me about a time something broke in production.&rdquo;</em> Bad: &ldquo;Our service went down, and I fixed it.&rdquo; Good: &ldquo;I was on-call when our main API started returning 500 errors. First, I checked monitoring to understand scope: 30% of requests, not all. That told me it probably wasn&rsquo;t new code. Error logs showed database connection timeouts. Database was at 100% CPU. Slow query log showed a full table scan on 50 million rows from a feature that launched that morning. I disabled the feature, fixed the API, then worked with the team to add an index. Whole thing took 45 minutes. Next day we implemented query review for large tables.&rdquo;</p>
<p>Technical questions focus on debugging and practical coding:</p>
<ul>
<li>&ldquo;How would you debug a slow API endpoint?&rdquo; (Walk through: monitoring, logs, profiling, database queries, external dependencies)</li>
<li>&ldquo;Write a script that processes this data.&rdquo; (Messy data problem. Handle edge cases. Python.)</li>
<li>&ldquo;Explain X to me like I&rsquo;m not technical.&rdquo; (DNS, database indexing, rate limiting. No jargon.)</li>
</ul>
<h2 id="your-first-90-days">Your First 90 Days</h2>
<p><em>Days 1-30: Learn</em>. Absorb context. Meet everyone. Read all documentation. Shadow every call. Build a glossary. Write down three things you learned each day. Don&rsquo;t try to add value yet. The most common failure mode is engineers who come in hot with opinions before they understand the environment.</p>
<p><em>Days 31-60</em>: Find your first win. One small thing you can own completely. A script that automates manual work. A bug fix that&rsquo;s been annoying customers. A dashboard replacing a spreadsheet. Something with a clear before and after. Ship it. Tell people.</p>
<p><em>Days 61-90</em>: Start forming opinions. Now you have context and credibility. Engage harder problems. Propose solutions. Be humble—three months in, you&rsquo;re still a beginner. But you&rsquo;re a beginner with context.</p>
<p>Traps to avoid:
<em>Overengineering</em>. I once saw a new FDE spend three weeks building a &ldquo;robust, scalable&rdquo; solution for a problem that needed a bash script. The customer cared about getting the answer by Friday.</p>
<p><em>Retreating into code</em>. When a meeting gets tense, your instinct is to hide behind your laptop. Don&rsquo;t. Stay present.</p>
<p><em>Overpromising</em>. Underpromise and overdeliver. &ldquo;Done by Wednesday&rdquo; when you finish Tuesday beats &ldquo;Done by Monday&rdquo; when you finish Wednesday.
Solving the wrong problem. &ldquo;What are you trying to accomplish?&rdquo; is the most important question in an FDE&rsquo;s toolkit.</p>
<h2 id="the-career-path">The Career Path</h2>
<p><em>Year 1: Learn</em>. Absorbing context, building relationships, developing judgment. Handling individual customer problems. Success: customers trust you, team relies on you for insights, you&rsquo;ve shipped things that made a real difference.</p>
<p><em>Year 2-3: Lead</em>. Owning larger customer relationships or leading small teams. Making prioritization decisions. Mentoring newer FDEs. Success: turned around a struggling customer relationship, shaped the product roadmap, people come to you when they don&rsquo;t know what to do.</p>
<p><em>Year 4+: Multiply</em>. Going deep (domain expert) or going broad (leading an FDE org, product leadership, starting a company). Many FDEs become founders because they have both technical skills and customer understanding. Others become product leaders. Some stay as senior FDEs handling the most complex deployments.</p>
<p>Frontline alumni have become founders of AI companies, heads of product at public companies, and engineering leaders at defense contractors. The FDE skill set is rare and valuable in almost any technical leadership role.</p>
<h2 id="resources">Resources</h2>
<p><em>Companies hiring FDEs</em>: Palantir, Anduril, OpenAI, Anthropic, Scale AI, Helsing, Hex, Databricks, Weights &amp; Biases</p>
<p><em>FDE-adjacent</em>: FDE as a service companies, defense tech startups, vertical SaaS with complex deployments, AI companies with enterprise customers</p>
<p>What to read:</p>
<ul>
<li>Palantir&rsquo;s S-1 filing (deployment methodology section)</li>
<li>Shyam Sankar&rsquo;s blog - <a href="https://www.shyamsankar.com/">https://www.shyamsankar.com/</a></li>
<li>&ldquo;The Mom Test&rdquo; by Rob Fitzpatrick - <a href="https://www.momtestbook.com/">https://www.momtestbook.com/</a></li>
<li>Julia Evans&rsquo; blog and zines - <a href="https://jvns.ca/">https://jvns.ca/</a></li>
</ul>
<h2 id="the-path-forward">The Path Forward</h2>
<p>The grey track jacket was just a symbol. What it represented was something deeper: the transformation that happens when you stop building software in a vacuum and start building it for real people, with real problems, in the real world.</p>
<p>That transformation is available to you whether or not you work at Palantir. It requires putting yourself in the field, feeling the pain of deployment, and understanding what customers actually need. It requires going through something that changes you.</p>
<p>The field is where the real education happens. Everything else is just preparation.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Context Is The Easy Part</title>
      <link>https://vinoo.io/writing/2026-01-30-context-is-the-easy-part/</link>
      <pubDate>Fri, 30 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2026-01-30-context-is-the-easy-part/</guid>
      <description>Context engineering isn&amp;#39;t a context problem. It&amp;#39;s an engineering problem - and the data world already solved it once.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://kepler.ai/blog-posts/context-is-the-easy-part">Kepler</a></em></p>
<p>Everyone&rsquo;s talking about context engineering right now, but most of the conversation is focused on the wrong thing. Read the blog posts, the guides, the thought leadership. They&rsquo;re all asking the same questions: What should I include in the context window? How do I manage tokens efficiently? How do I curate what the model sees?</p>
<p>These are valid questions. They&rsquo;re also the easy part.</p>
<p>The hard part isn&rsquo;t deciding what context to include. It&rsquo;s building systems that deliver that context reliably, with provenance, at scale, every single time. That&rsquo;s not a context problem. That&rsquo;s an engineering problem. And engineering means something specific.</p>
<p>I spent fifteen years building data infrastructure at Palantir and Citadel, working on defense and intelligence systems where wrong answers weren&rsquo;t acceptable. Here&rsquo;s what I learned: knowing what data you need is trivial. Everyone knows what data they need. The hard part is building systems that deliver it validated, traceable, reproducible, and on demand.</p>
<p>The data world spent two decades learning this lesson. You don&rsquo;t solve data problems by choosing the right data. You solve them by building the infrastructure that makes data trustworthy. Context is the same problem wearing different clothes.</p>
<p>Watch how people approach context engineering today. They&rsquo;re selecting documents. Tuning retrieval parameters. Adjusting chunk sizes. Experimenting with what to include and what to leave out. Managing memory hierarchies. Optimizing token usage. This is prompt engineering with more inputs. It&rsquo;s not engineering.</p>
<p>Engineering means provenance: where did this context come from, and can I trace every piece back to its source? If the output is wrong, can I figure out which input caused it? Engineering means versioning: the context I retrieved yesterday and the context I retrieve today, are they the same, and if not, why? Can I reproduce last week&rsquo;s answer? Engineering means validation: how do I know the context is accurate before it reaches the model, what checks exist, and what happens when something fails? Engineering means determinism: same query, same context, every time, not mostly the same, but exactly the same. Engineering means observability: when context retrieval breaks, how do I know, how do I debug it, and how do I fix it without guessing?</p>
<p>Most context engineering today has none of this. It&rsquo;s artisanal, manual, and fragile. It works in demos and falls apart in production.</p>
<p>The failure mode is predictable. Someone builds a system that retrieves context and generates answers. It works well enough in testing, so they ship it. Then the context changes. A document gets updated. A source goes stale. A retrieval pipeline silently returns different results. The model keeps generating answers with the same confidence, but now the answers are wrong. Nobody notices until a customer does.</p>
<p>This is the same failure mode the data world lived through. Dashboards that showed numbers nobody could trace. Reports that changed when you refreshed the page. Metrics that meant different things to different teams. We solved it by building infrastructure: pipelines with lineage, transformations with tests, data contracts, observability. The unsexy plumbing that makes data trustworthy. Context needs the same infrastructure, and almost nobody is building it.</p>
<p>The current generation of AI tools is fragile in ways that aren&rsquo;t obvious. They work until they don&rsquo;t. They&rsquo;re right until they&rsquo;re wrong. And when they break, there&rsquo;s no way to diagnose why. The teams treating context engineering as an optimization problem will keep hitting this wall. They&rsquo;ll tune retrieval, adjust chunk sizes, swap embedding models, and still get inconsistent results they can&rsquo;t explain. The teams treating it as an engineering problem will build systems that are auditable, reproducible, and debuggable. They&rsquo;ll know where their context comes from. They&rsquo;ll know when it changes. They&rsquo;ll be able to defend their outputs. One approach scales. The other doesn&rsquo;t.</p>
<p>The term context engineering is new. The problem isn&rsquo;t. It&rsquo;s the same problem the data world faced: how do you build systems that deliver the right information, reliably, at scale? The answer was never &ldquo;choose the right data.&rdquo; The answer was always &ldquo;build the infrastructure that makes data trustworthy.&rdquo;</p>
<p>Context is data by another name. The lessons are the same. The question is whether we&rsquo;re going to spend another decade relearning them.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Databricks Delta Live Tables 101</title>
      <link>https://vinoo.io/writing/2024-03-08-databricks-delta-live-tables/</link>
      <pubDate>Fri, 08 Mar 2024 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2024-03-08-databricks-delta-live-tables/</guid>
      <description>A comprehensive guide to understanding Databricks Delta Live Tables and their role in modern data engineering workflows</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://synccomputing.com/databricks-delta-live-tables-101/">Sync Computing</a></em></p>
<p>Databricks&rsquo; DLT offering showcases a substantial improvement in the data engineer lifecycle and workflow. By offering a pre-baked, and opinionated pipeline construction ecosystem, Databricks has finally started offering a holistic end-to-end data engineering experience from inside of its own product, which provides superior solutions for raw data workflow, live batching and a host of other benefits detailed below.</p>
<p>Since its release in 2022, Databricks&rsquo; Delta Live Tables have quickly become a go-to end-to-end resource for data engineers looking to build opinionated ETL pipelines for streaming data and big data. The pipeline management framework is considered one of the most valuable offerings on the databricks platform, and is used by over 1,000 companies including Shell and H&amp;R block.</p>
<h2 id="what-are-delta-live-tables">What Are Delta Live Tables?</h2>
<p>Delta Live Tables, or DLT, is a declarative ETL framework that dramatically simplifies the development of both batch and streaming pipelines. Concretely though, DLT is just another way of authoring and managing pipelines in databricks. Tables are created using the <code>@dlt.table()</code> annotation on top of functions (which return queries defining the table) in notebooks.</p>
<p>Delta Live Tables are built using Databricks foundational technology such as the Delta Lake and Delta File format. As such, they operate in conjunction with these two. However, whereas these two focus on the more &ldquo;stagnant&rdquo; portions of the data process, DLT focuses on the <em>transformation</em> piece. Specifically, the DLT framework allows data engineers to describe <em>how</em> data should be transformed between tables in the DAG.</p>
<p>The magic of DLT is most apparent when it comes to datasets that both involve streaming data and batch processing data. Whereas, in the past, users had to be keenly aware of and design pipelines for the type of the &ldquo;velocity&rdquo; (batch vs. streaming) of data transformed, DLT allows users to push this problem to the system itself. Meaning, users can write declarative transformations and let the system figure out how to handle the streaming or batch components.</p>
<h2 id="how-are-delta-live-tables-delta-tables-and-delta-lake-related">How are Delta Live Tables, Delta Tables, and Delta Lake related?</h2>
<p>The word &ldquo;Delta&rdquo; appears a lot in the Databricks ecosystem, and to understand why, it&rsquo;s important to look back at history. In 2019, Databricks publicly announced the Delta Lake, a foundational element for storing data (tables) into the Databricks Lakehouse. Delta Lake popularized the idea of a <em>Table Format</em> on top of files, with the goal of bringing reliability to data lakes.</p>
<p>Tables that live inside of this Delta Lake are written using the Delta Table format and, as such, are called Delta Tables. Delta Live Tables focus on the &ldquo;live&rdquo; part of data flow between Delta tables – usually called the &ldquo;transformation&rdquo; step in the ETL paradigm. Delta Live Tables (DLTs) offer declarative pipeline development and visualization.</p>
<h2 id="breaking-down-the-components-of-delta-live-tables">Breaking Down The Components of Delta Live Tables</h2>
<p>There are two main ways to create tables within a Delta Live Tables pipeline:</p>
<h3 id="tables">Tables</h3>
<p>Tables in DLT are materialized views that are stored in the lakehouse. They represent the physical datasets that will be persisted and can be queried directly. These tables are created using the <code>@dlt.table()</code> decorator and contain the actual transformed data.</p>
<h3 id="views">Views</h3>
<p>Views in DLT are temporary datasets that exist only during the pipeline execution. They&rsquo;re useful for intermediate transformations and don&rsquo;t consume storage since they&rsquo;re computed on-demand. Views are created using the <code>@dlt.view()</code> decorator.</p>
<p>You can declare your datasets in DLT using either SQL or Python. These declarations can then trigger an update to calculate results for each dataset in the pipeline.</p>
<h2 id="when-to-use-views-or-materialized-views-in-delta-live-tables">When to Use Views or Materialized Views in Delta Live Tables</h2>
<p>The choice of View or Materialized View primarily depends on your use case. The biggest difference between the two is that Views are <strong>computed at query time</strong>, whereas Materialized Views are <strong>precomputed.</strong> Views also have the added benefit that they don&rsquo;t actually require any additional storage, as they are computed on the fly.</p>
<p>The general rule of thumb when choosing between the two has to do with the performance requirements and downstream access patterns of the table in question. When performance is critical, having to compute a view on the fly may be an unnecessary slowdown, in which case, Materialized Views may be preferred. The same is true when there are multiple downstream consumers of a particular View.</p>
<p>However, there are multiple situations where users just need a quick view, computed in memory, to reference a particular state of a transferred table. Rather than materializing this table, creating a View is more straightforward and efficient.</p>
<h2 id="what-are-the-advantages-of-delta-live-tables">What Are the Advantages of Delta Live Tables?</h2>
<p>There are many benefits to using Delta Live Tables:</p>
<h3 id="unified-streamingbatch-experience">Unified Streaming/Batch Experience</h3>
<p>By removing the need for data engineers to build distinct streaming/batch data pipelines, DLT simplifies one of the most difficult pain points of working with data, thereby offering a truly unified experience.</p>
<h3 id="opinionated-pipeline-management">Opinionated Pipeline Management</h3>
<p>The modern data stack is filled with orchestration players, observability players, data quality players, and many others. DLT offers an opinionated way to orchestrate and assert data quality.</p>
<h3 id="performance-optimization">Performance Optimization</h3>
<p>DLTs offer the full advantages of Delta Tables, which are designed to handle large volumes of data and support fast querying. Their vectorized query execution allows them to process data in batches rather than one row at a time.</p>
<h3 id="built-in-quality-assertions">Built-in Quality Assertions</h3>
<p>Delta Live Tables provide data quality features, such as data cleansing and data deduplication, out of the box. Users can specify rules to remove duplicates or cleanse data as data is ingested, ensuring data accuracy.</p>
<h3 id="acid-transactions">ACID Transactions</h3>
<p>Because DLTs use Delta format they support ACID transactions (Atomicity, Consistency, Isolation and Durability) which has become the standard for data quality and exactness.</p>
<h3 id="pipeline-visibility">Pipeline Visibility</h3>
<p>DLT provides a Directed Acyclic Graph of your data pipeline workloads, giving you a clear, visually compelling way to both see and introspect your pipeline at various points.</p>
<h2 id="change-data-capture-cdc-in-delta-live-tables">Change Data Capture (CDC) in Delta Live Tables</h2>
<p>One of the large benefits of Delta Live Tables is the ability to use Change Data Capture while streaming data. Change Data Capture refers to the tracking of all changes in a data source so they can be captured across all destination systems.</p>
<p>With Delta Live Tables, data engineers can easily implement CDC with the Apply Changes API (either with Python or SQL). The capability lets ETL pipelines easily detect source data changes and apply them to data sets throughout the lakehouse.</p>
<p>Delta Live Tables support Slowly Changing Dimensions (SCD) both type 1 and type 2. This is important because SCD type 2 retains a full history of values, which means you can retain a history of records in your data lakehouse.</p>
<h2 id="what-is-the-cost-of-delta-live-tables">What is the Cost of Delta Live Tables?</h2>
<p>The cost of Delta Live Tables depends on the compute function itself. On AWS, DLT compute can range from $0.20/DBU for DLT Core Compute Photon up to $0.36/DBU for DLT Advanced Compute. However, these prices can be up to twice as high when applying expectations and CDC.</p>
<p>From an efficiency perspective, DLT results in a reduction in total cost of ownership. Automatic orchestration tests by Databricks have shown total compute time to be reduced by as much as half with Delta Live Tables – ingesting up to 1 billion records for under $1.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Delta Live Tables represent a significant advancement in data engineering workflows, offering a unified approach to batch and streaming data processing. By providing built-in data quality checks, automatic orchestration, and comprehensive pipeline visibility, DLT simplifies many of the traditional pain points in data pipeline development.</p>
<p>While there are cost considerations to keep in mind, the efficiency gains and reduced operational overhead often justify the investment, especially for organizations dealing with complex data transformation workflows.</p>
<hr>
<p><em>This post was originally published on <a href="https://synccomputing.com/databricks-delta-live-tables-101/">Sync Computing&rsquo;s blog</a> on March 8, 2024.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>Rethinking Serverless: The Price of Convenience</title>
      <link>https://vinoo.io/writing/2024-02-09-rethinking-serverless/</link>
      <pubDate>Fri, 09 Feb 2024 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2024-02-09-rethinking-serverless/</guid>
      <description>Examining the hidden costs and challenges of serverless functions in modern enterprise environments</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://synccomputing.com/rethinking-serverless-the-price-of-convenience/">Sync Computing</a></em></p>
<p>Serverless functions have had their 15 minutes of fame (and runtime).</p>
<p>As is the case with many concepts in technology, the term Serverless is abusively vague. As such, discussing the idea of &ldquo;serverless&rdquo; usually invokes one of two feelings in developers. Either, it&rsquo;s thought of as the catalyst for this potential incredible future, finally freeing developers from having to worry about resources or scaling concerns, or it&rsquo;s thought of as the harbinger of yet another &ldquo;we don&rsquo;t need DevOps anymore&rdquo; trend.</p>
<p>The root cause of this confusion has to do with the fact that the catch-all term &ldquo;Serverless&rdquo; actually comprises two large operating models: functions and jobs. At Sync – we&rsquo;re intimately familiar with optimizing jobs, so when our customers gave us feedback to focus a portion of our attention on serverless functions, we were more than intrigued.</p>
<p>The hypothesis was simple. Could we extend our expertise and background in optimizing Databricks large scale/batch compute workloads to optimizing many smaller batch compute workloads.</p>
<h2 id="serverless-functions-how-we-got-here">Serverless Functions: How We Got Here</h2>
<p>One of the most painful parts of the developer workflow is &ldquo;real world deployment.&rdquo; In the real world, deploying code that was written locally to the right environment and to work in the same way was extraordinarily painful. Library issues, scaling issues, infrastructure management issues, provisioning issues, resource selection issues, and a number of other issues plagued developers. The cloud just didn&rsquo;t mimic the ease and simplicity of local developer environments.</p>
<p>Then Serverless functions emerged. All of a sudden, developers could write and deploy code in a function with the same level of simplicity as writing it locally. They never had to worry about spinning up an EC2 instance or figuring out what the material differences between AMI and Ubuntu are. They didn&rsquo;t have to play with docker files or even have to do scale testing. They wrote the exact same Python or NodeJS code that they wrote locally in a Cloud IDE and it just worked. It seemed perfect.</p>
<p>Soon, mission critical pieces of infrastructure were supported by double digit line python functions deployed in the cloud. Enter: Serverless frameworks. All of a sudden, it became even easier to adopt and deploy serverless functions. Enterprises adopted these functions like hotcakes. Many deployed in the hundreds or even thousands of these functions.</p>
<h2 id="industry-adoption-and-trends">Industry Adoption and Trends</h2>
<p>In 2022, an IBM blog post titled &ldquo;The Future Is Serverless&rdquo; was published, which cited the &ldquo;energy-efficient and cost-efficient&rdquo; nature of serverless applications as a primary reason that the future will be serverless. They make the – valid – case that reserving cloud capacity is challenging and consumers of cloud serverless functions are better served by allowing technologies such as KNative to streamline the &ldquo;serverless-ification&rdquo; processes.</p>
<p>In 2023, Datadog released their annual &ldquo;State of Serverless&rdquo; post, showing the continued adoption of Serverless technologies across all 3 major cloud vendors. The leader of the pack is AWS Lambda, which has traditionally been the entry point for developers to deploy their Serverless workloads.</p>
<p>Interestingly, 40%+ of Lambda invocations happen in NodeJS – which is not traditionally thought of as a distributed computing framework, nor is it generally used for large scale orchestration of compute tasks. But it seems to be dominating the Lambda serverless world.</p>
<h2 id="what-serverless-actually-solved">What Serverless Actually Solved</h2>
<p>Before diving into the problems, let&rsquo;s acknowledge where serverless functions truly excel:</p>
<h3 id="uptime-guarantees">Uptime Guarantees</h3>
<p>One of the critical, but most frustrating pieces of the developer lifecycle is uptime requirements. Many developers hear the term &ldquo;five-nines&rdquo; and shudder. Building applications that have specific uptime guarantees is not only challenging, it&rsquo;s also time-intensive. When large scale systems are made up of small, discrete pieces of computation, the problem can become all the more complex.</p>
<p>Lambda SLAs guarantee a fairly reasonable amount of uptime, right out of the box. This can save otherwise substantial developer efforts of scoping, building, and testing highly available systems.</p>
<h3 id="concurrency--auto-scaling">Concurrency + Auto Scaling</h3>
<p>Introspecting a large scale system isn&rsquo;t easy. In an environment where requests can burst unexpectedly, creating and designing systems that scale based on spot user demand is also difficult.</p>
<p>One of the most powerful aspects of a serverless or hosted model is the demand-based auto-scaling capabilities offered by the infrastructure. These effects are compounded, especially when the functions themselves are stateless. This effectively eliminates developers having to care about the <em>operational</em> concerns of autoscaling.</p>
<h2 id="the-problems-with-serverless-functions">The Problems with Serverless Functions</h2>
<p>Despite these benefits, our analysis revealed four critical problems that are undermining the serverless promise:</p>
<h2 id="problem-1-developer-bandwidth">Problem 1: Developer Bandwidth</h2>
<p>In a typical Serverless Function deployment, the initial choice of configuration tends to be the perpetual choice of configuration.</p>
<p>Wait, &ldquo;initial choice of configuration&rdquo;? It turns out, yes, users still need to manually pick a particular configuration for each serverless function they deploy. It&rsquo;s actually a bit ironic – with the promise of true 0-management jobs, users are still required to intelligently select resource configuration.</p>
<p>If an engineer deploys and accidentally overspecs a serverless function initially, it&rsquo;s fairly unlikely that they will ever revisit the function to optimize it. This happens for several reasons:</p>
<ol>
<li>
<p><strong>Time</strong> – Most engineers don&rsquo;t have the time to go back and ensure that functions they have written weeks, months, or even years ago are operating under the ideal resources.</p>
</li>
<li>
<p><strong>Incentives</strong> – Engineers are not incentivized by picking the optimal resource configuration for their jobs. They&rsquo;d rather have the job be guaranteed to work, while spending a bit more of their company&rsquo;s compute budget.</p>
</li>
<li>
<p><strong>Employee Churn</strong> – Enterprises have inherent entropy and employees are oftentimes transient. When other engineers inherit previous work, they are significantly more incentivized to just ensure it works, rather than ensure that it works optimally.</p>
</li>
</ol>
<h2 id="problem-2-serverless-still-requires-tuning">Problem 2: Serverless Still Requires Tuning</h2>
<p>Lambda is predicated on a simple principle – the resource requirements for workloads that take less than 15 minutes to run can be pretty easily approximated. Lambda makes it easy for developers to set-and-forget, offering only one knob for them to worry about.</p>
<p>That knob is memory. Using Lambda, you can configure the memory allocated to a lambda function as a value between 128 MB and 10,240 MB. Lambda will automatically decide how much vCPU to allocate based on the memory setting.</p>
<p>This sounds great in theory. &ldquo;I only have to pick one lever and all of a sudden, I get everything else figured out for me?&rdquo; If that were the end of the story, this would be a much shorter post.</p>
<p>Instead, life is all about tradeoffs – generally correlated tradeoffs. In this case, it&rsquo;s cost and performance. As an engineer, it&rsquo;s easy to pick the largest memory setting available just to ensure the Lambda function works, regardless of what its actual resource requirements are. Once it works, why would anyone ever touch it again?</p>
<p>Well, it turns out that picking large, frequently uncorrelated-to-necessary-resources values isn&rsquo;t the most cost effective approach. So much so that an AWS Solutions Engineer built and open sourced a tool to help users actually find the correct memory levels for their Lambda functions. The tool uses AWS Step Functions to walk users down to the minimum necessary level. It&rsquo;s been so popular that it has 5K stars on GitHub and 18.8K deployments.</p>
<p>Clearly, the one-knob-rules-all solution isn&rsquo;t working.</p>
<h2 id="problem-3-serverless-is-hard-to-introspect">Problem 3: Serverless Is Hard to Introspect</h2>
<p>The scale and growth testing that plagued engineers for decades before the rise of Serverless was unfortunately not in vain. Understanding how users will interact with an application, in terms of number of requests or compute load, gives engineers a powerful understanding of what to expect when things go live.</p>
<p>In the Serverless Function architecture, engineers don&rsquo;t think about these considerations and push the burden onto the infrastructure itself. As long as the infrastructure works – it&rsquo;s unlikely that an already oversubscribed engineer would spend time digging into the performance or cost characteristics of the Serverless function.</p>
<p>Absent home-rolled solutions, there are few tools that allow for the detailed observability of a single serverless function. Furthermore, there are usually hundreds if not thousands of serverless functions deployed. Observability across a fleet of functions is nearly impossible.</p>
<p>The primary mechanism for per-function observability is AWS CloudWatch. CloudWatch logs events for each lambda invocation and stores a few metrics. The major problem is that just collecting this information in CloudWatch has been observed to be more expensive than Lambda itself. There are full articles, posts, and best practices around just managing the costs associated with Lambda CloudWatch logs.</p>
<h2 id="problem-4-no-auto-optimization">Problem 4: No Auto-Optimization</h2>
<p>The year 2023 brought on a material shift in the mentality of &ldquo;compute&rdquo; consumers. Enterprises that were previously focused on growth at all costs shifted their focus to efficiency. Vendors in the generic Cloud, Snowflake, and Databricks ecosystem popped up at increasing rates. Most had a simple goal – provide high level visibility into workloads.</p>
<p>They provided interactive charts and diagrams to show ongoing cost changes… But they didn&rsquo;t provide the fundamental &ldquo;healing&rdquo; mechanisms. It would be like going to the doctor, having them diagnose a problem, but provide no recourse.</p>
<p>Consistent with their focus on efficiency, enterprises had a few options. Larger ones deployed full teams to focus on this effort. Smaller ones that didn&rsquo;t have the budget or manpower turned to observability tools… nearly all of which fell short, as they missed the fundamental optimization component.</p>
<p>Providing detailed visibility across a few, large scale jobs is considered table stakes for many observability providers, but for some reason providing that same level of visibility across many, small scale jobs, in an efficient and easy to optimize way hasn&rsquo;t become standard.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We&rsquo;re in a fairly unique period as an industry. Job visibility, tuning, introspection, and optimization have reemerged as key pieces of the modern tech stack. But most focus on the whales, when they should be focusing on the barracudas.</p>
<p>Serverless functions promised to eliminate the complexity of infrastructure management, but they&rsquo;ve simply shifted that complexity elsewhere. While they excel in certain areas like uptime guarantees and auto-scaling, the hidden costs of poor optimization, lack of visibility, and ongoing manual tuning requirements suggest that the serverless revolution still has room for improvement.</p>
<p>The future of serverless likely lies not in the elimination of optimization concerns, but in the automation of those concerns – turning the promise of &ldquo;set-and-forget&rdquo; into reality through intelligent, automated resource management and optimization.</p>
<hr>
<p><em>This post was originally published on <a href="https://synccomputing.com/rethinking-serverless-the-price-of-convenience/">Sync Computing&rsquo;s blog</a> on February 9, 2024.</em></p>
]]></content:encoded>
    </item>
    <item>
      <title>The Efficiently Guide to Snowflake (Top Down)</title>
      <link>https://vinoo.io/writing/2023-02-02-efficiently-guide-to-snowflake/</link>
      <pubDate>Thu, 02 Feb 2023 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2023-02-02-efficiently-guide-to-snowflake/</guid>
      <description>4 changes you can make right now to run Snowflake more Efficiently.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://vinooganesh.substack.com/p/snowflake-top-down">Efficiently (Substack)</a></em></p>
<p>The majority of my career has been focused on making data systems more efficient — whether that means performance, scalability, or cost. This series aims to democratize knowledge about how to Efficiently operationalize data.</p>
<p><img alt="Snowflake Guide" height='̠' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-cover_hu_6f6c9ab3061f635f.webp" width='̠'></p>
<h2 id="tldr">TLDR</h2>
<p>4 changes you can make <em>right now</em> to run Snowflake more Efficiently:</p>
<ol>
<li>File a Snowflake support ticket and request access to the <code>GET_QUERY_STATS</code> function</li>
<li><code>ALTER WAREHOUSE &lt;warehouseName&gt; SET AUTO_SUSPEND = 60;</code></li>
<li>For multi-cluster warehouses:
<ul>
<li><code>ALTER WAREHOUSE &lt;warehouseName&gt; SET MIN_CLUSTER_COUNT = 1;</code></li>
<li><code>ALTER WAREHOUSE &lt;warehouseName&gt; SET SCALING_POLICY = ECONOMY;</code></li>
</ul>
</li>
<li><code>ALTER WAREHOUSE &lt;warehouseName&gt; SET STATEMENT_TIMEOUT_IN_SECONDS=36000</code></li>
</ol>
<h2 id="snowflake--driving">Snowflake + Driving</h2>
<p>Snowflake optimization resembles efficient driving. There are four parallel constraints:</p>
<ul>
<li><strong>Car efficiency</strong> = warehouse size selection</li>
<li><strong>Driver skill</strong> = query authorship ability</li>
<li><strong>Road congestion</strong> = warehouse saturation</li>
<li><strong>Route optimization</strong> = query construction, schema design, and partitioning</li>
</ul>
<p><img alt="Snowflake optimization framework" height='ó' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-diagram_hu_fedf72f65065630f.webp" width='̠'></p>
<h2 id="top-down-vs-bottom-up">Top Down vs. Bottom Up</h2>
<p>This framework separates optimization into two approaches: <strong>Top Down</strong> (optimizing the environment/infrastructure without affecting users) and <strong>Bottom Up</strong> (optimizing operations — the &ldquo;driver&rdquo;).</p>
<p>This post focuses on the Top Down approach.</p>
<h2 id="insight-1-get-data">Insight #1: Get Data</h2>
<p>Solving problems requires data. Two critical functions provide the visibility needed for optimization:</p>
<ul>
<li><code>GET_QUERY_STATS</code></li>
<li><code>GET_QUERY_OPERATOR_STATS</code> (preview feature, available on all accounts)</li>
</ul>
<p>These functions are not available by default — you&rsquo;ll need to file a support ticket with Snowflake to request access.</p>
<h2 id="insight-2-turn-your-car-off">Insight #2: Turn Your Car Off</h2>
<p>Your car (warehouse) should only be on when you need it. Minimize the time that it is on and doing nothing.</p>
<p>Warehouses consume credits continuously while active, even during idle periods. The AUTO_SUSPEND parameter automatically stops idle warehouses after a specified duration.</p>
<p><img alt="Warehouse consumption history" height='Ǭ' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-consumption_hu_5acf710e67eebd89.webp" width='̠'></p>
<p>There are four warehouse states to understand:</p>
<ul>
<li><strong>Suspended</strong> — Off, no charges</li>
<li><strong>Running/Idle (Will Suspend)</strong> — On but no queries executing, within the auto-suspend window. Charging unnecessarily.</li>
<li><strong>Running/Idle (Won&rsquo;t Suspend)</strong> — On but no queries, yet a query is incoming before suspension triggers. This requires investigation.</li>
<li><strong>Running/Active</strong> — Queries are executing. This is the desired state.</li>
</ul>
<p><img alt="Warehouse states timeline (simple)" height='ɭ' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-timeline-simple_hu_8fed9c59c0ef5990.webp" width='̠'></p>
<p>The goal: minimize the Red &ldquo;No Queries Running&rdquo; while looking for ways to also minimize the Pink &ldquo;No Queries Running.&rdquo;</p>
<p><img alt="Warehouse states timeline (complex)" height='ɪ' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-timeline-complex_hu_80808b5947062ec9.webp" width='̠'></p>
<p>Snowflake&rsquo;s minimum auto-suspend is 30 seconds, but charges are incurred for full-minute increments regardless. Setting to 60 seconds is the optimal minimum:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> WAREHOUSE <span style="color:#ff79c6">&lt;</span>warehouseName<span style="color:#ff79c6">&gt;</span> <span style="color:#ff79c6">SET</span> AUTO_SUSPEND <span style="color:#ff79c6">=</span> <span style="color:#bd93f9">60</span>;
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="insight-3-car-engines--cylinders">Insight #3: Car Engines + Cylinders</h2>
<p>Clusters function like engine cylinders — more clusters mean more processing power but higher consumption.</p>
<p><img alt="Engine analogy" loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-engine.gif"></p>
<p>Snowflake bills at <code># Warehouse * # Clusters</code>. More clusters enable parallel processing but increase costs proportionally.</p>
<p><img alt="Warehouse states diagram" height='ɽ' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-warehouse-states_hu_ab136c1e3624d930.webp" width='̠'></p>
<p>Two configuration changes to make right now:</p>
<p>Start with a single cluster minimum:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> WAREHOUSE <span style="color:#ff79c6">&lt;</span>warehouseName<span style="color:#ff79c6">&gt;</span> <span style="color:#ff79c6">SET</span> MIN_CLUSTER_COUNT <span style="color:#ff79c6">=</span> <span style="color:#bd93f9">1</span>;
</span></span></code></pre></td></tr></table>
</div>
</div><p>Use economy scaling policy (scales only when strictly necessary):</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> WAREHOUSE <span style="color:#ff79c6">&lt;</span>warehouseName<span style="color:#ff79c6">&gt;</span> <span style="color:#ff79c6">SET</span> SCALING_POLICY <span style="color:#ff79c6">=</span> ECONOMY;
</span></span></code></pre></td></tr></table>
</div>
</div><p>The economy policy prioritizes cost efficiency over performance, scaling up only when queries are being queued.</p>
<h2 id="insight-4-restrict-trip-distance">Insight #4: Restrict Trip Distance</h2>
<p>Like Federal Motor Carrier Safety Administration regulations limiting how long drivers can be on the road, queries should have maximum execution times.</p>
<p><img alt="FMCSA regulations" height='Ĺ' loading="lazy" src="/writing/2023-02-02-efficiently-guide-to-snowflake/snowflake-fmcsa_hu_46240b5e24f416c8.webp" width='̠'></p>
<p>Snowflake&rsquo;s <code>STATEMENT_TIMEOUT_IN_SECONDS</code> defaults to 172,800 seconds — that&rsquo;s 2 days. This permits excessively long, potentially runaway queries to consume credits indefinitely.</p>
<p>Set a reasonable timeout of 36,000 seconds (10 hours):</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sql" data-lang="sql"><span style="display:flex;"><span><span style="color:#ff79c6">ALTER</span> WAREHOUSE <span style="color:#ff79c6">&lt;</span>warehouseName<span style="color:#ff79c6">&gt;</span> <span style="color:#ff79c6">SET</span> STATEMENT_TIMEOUT_IN_SECONDS<span style="color:#ff79c6">=</span><span style="color:#bd93f9">36000</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="conclusion">Conclusion</h2>
<p>There is a prevalent idea floating around that Snowflake is expensive. That can be true, but as is the case in most of these systems, it really comes down to how effectively and Efficiently you use Snowflake.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Hands-On: Predicate Pushdown</title>
      <link>https://vinoo.io/writing/2023-01-28-hands-on-predicate-pushdown/</link>
      <pubDate>Sat, 28 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2023-01-28-hands-on-predicate-pushdown/</guid>
      <description>A practical demonstration of how query optimizers leverage Parquet metadata to skip unnecessary data reads.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://vinooganesh.substack.com/p/hands-on-predicate-pushdown">Efficiently (Substack)</a></em></p>
<p>We&rsquo;ve spoken a lot about on-disk and distributed storage, as well as blocks. All of this theory is great, let&rsquo;s talk about this in practice.</p>
<p>In this post, I&rsquo;m going to:</p>
<ol>
<li>Read a CSV dataset into Spark</li>
<li>Write the dataset into 5 Parquet files (treating each file as a block)</li>
<li>Introspect metadata existing on the files</li>
<li>Run queries demonstrating predicate pushdown power</li>
</ol>
<p><img alt="Predicate Pushdown" height='ǻ' loading="lazy" src="/writing/2023-01-28-hands-on-predicate-pushdown/predicate-pushdown-cover_hu_159dd2e821d6e856.webp" width='̠'></p>
<h2 id="hands-on-setup">Hands-On: Setup</h2>
<p>The tutorial uses an airports dataset. Download it via:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>wget https://raw.githubusercontent.com/curran/data/gh-pages/vegaExamples/airports.csv -O dataset.csv
</span></span></code></pre></td></tr></table>
</div>
</div><p>The CSV contains columns: <code>iata</code>, <code>name</code>, <code>city</code>, <code>state</code>, <code>country</code>, <code>latitude</code>, <code>longitude</code>.</p>
<h3 id="loading-data-into-spark">Loading Data into Spark</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scala" data-lang="scala"><span style="display:flex;"><span><span style="color:#ff79c6">val</span> dataset <span style="color:#ff79c6">=</span> spark<span style="color:#ff79c6">.</span>read<span style="color:#ff79c6">.</span>option<span style="color:#ff79c6">(</span><span style="color:#f1fa8c">&#34;header&#34;</span><span style="color:#ff79c6">,</span><span style="color:#f1fa8c">&#34;true&#34;</span><span style="color:#ff79c6">).</span>option<span style="color:#ff79c6">(</span><span style="color:#f1fa8c">&#34;inferSchema&#34;</span><span style="color:#ff79c6">,</span><span style="color:#f1fa8c">&#34;true&#34;</span><span style="color:#ff79c6">).</span>csv<span style="color:#ff79c6">(</span><span style="color:#f1fa8c">&#34;dataset.csv&#34;</span><span style="color:#ff79c6">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>The inferred schema shows latitude and longitude as double types.</p>
<h3 id="writing-parquet-files">Writing Parquet Files</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scala" data-lang="scala"><span style="display:flex;"><span>dataset<span style="color:#ff79c6">.</span>repartition<span style="color:#ff79c6">(</span><span style="color:#bd93f9">5</span><span style="color:#ff79c6">).</span>write<span style="color:#ff79c6">.</span>parquet<span style="color:#ff79c6">(</span><span style="color:#f1fa8c">&#34;/root/parquet_dataset&#34;</span><span style="color:#ff79c6">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>This creates 5 Parquet files plus a <code>_SUCCESS</code> flag file.</p>
<h3 id="inspecting-parquet-metadata">Inspecting Parquet Metadata</h3>
<p>Install the inspection tools:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a>
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-3-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-2">2</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>pip3 install parquet-tools
</span></span><span style="display:flex;"><span>pip3 install parquet-metadata
</span></span></code></pre></td></tr></table>
</div>
</div><p>View file contents:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-4-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-4-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>parquet-tools show part-00000-53b27d15-b049-41db-a8aa-fa3033763836-c000.snappy.parquet
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="hands-on-query-plans">Hands-On: Query Plans</h2>
<h3 id="simple-filter-query">Simple Filter Query</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-5-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-1">1</a>
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-5-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-2">2</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scala" data-lang="scala"><span style="display:flex;"><span><span style="color:#ff79c6">val</span> simpleFilter <span style="color:#ff79c6">=</span> dataset<span style="color:#ff79c6">.</span>filter<span style="color:#ff79c6">(</span>$<span style="color:#f1fa8c">&#34;latitude&#34;</span> <span style="color:#ff79c6">&gt;</span> <span style="color:#bd93f9">30</span><span style="color:#ff79c6">)</span>
</span></span><span style="display:flex;"><span>simpleFilter<span style="color:#ff79c6">.</span>show<span style="color:#ff79c6">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>The result shows all rows where latitude exceeds 30.</p>
<p>The query plan analysis reveals three optimization stages: parsed logical plan, analyzed logical plan, and optimized logical plan. The optimized logical plan has added some null checking — which also matches our predicate.</p>
<h3 id="complex-filter-query">Complex Filter Query</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-6-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-6-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-scala" data-lang="scala"><span style="display:flex;"><span><span style="color:#ff79c6">val</span> complexFilter <span style="color:#ff79c6">=</span> dataset<span style="color:#ff79c6">.</span>filter<span style="color:#ff79c6">(</span>$<span style="color:#f1fa8c">&#34;latitude&#34;</span> <span style="color:#ff79c6">&gt;</span> <span style="color:#bd93f9">30</span><span style="color:#ff79c6">).</span>filter<span style="color:#ff79c6">(</span>$<span style="color:#f1fa8c">&#34;latitude&#34;</span> <span style="color:#ff79c6">&lt;</span> <span style="color:#bd93f9">40</span><span style="color:#ff79c6">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>As you can see, the plan has combined both of our predicates into one step as part of the query process (meaning that what would previously take two passes over the data now only requires one).</p>
<p>The optimized plan consolidates the filters: <code>Filter ((isnotnull(latitude#21) AND (latitude#21 &gt; 30.0)) AND (latitude#21 &lt; 40.0))</code></p>
<h2 id="hands-on-querying-with-parquet">Hands-On: Querying with Parquet</h2>
<h3 id="row-group-metadata-analysis">Row Group Metadata Analysis</h3>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-7-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-7-1">1</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>parquet-metadata /root/parquet_dataset/part-00000-...
</span></span></code></pre></td></tr></table>
</div>
</div><p>Critical metadata fields include:</p>
<ul>
<li><code>stats:min</code> — smallest value in the column</li>
<li><code>stats:max</code> — largest value in the column</li>
</ul>
<p>Example statistics from one file:</p>
<div class="highlight"><div style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-8-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-8-1">1</a>
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f" id="hl-8-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-8-2">2</a>
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>row_group 0 latitude stats:min 14.1743075
</span></span><span style="display:flex;"><span>row_group 0 latitude stats:max 70.46727611
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="predicate-pushdown-mechanism">Predicate Pushdown Mechanism</h3>
<p>For a second file with <code>stats:min=44.4430157</code> and <code>stats:max=74.46727611</code>, a query filtering for latitude between 30 and 40 would exclude this entire file — because we know from the metadata that no values in this file fall within our filter range.</p>
<p>In practice, this is called <strong>predicate pushdown</strong>. The requirements of the predicate (the query) have been pushed down, allowing the optimizers to look at the metadata on the row groups themselves to decide which row groups to read, and when they can be ignored.</p>
<h2 id="conclusion">Conclusion</h2>
<p>There is a lot of magic that goes into our ability to query data quickly and <em>Efficiently</em>. Query optimizers do a lot for us — and understanding how they work under the hood helps us write better queries and design better data layouts.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Distributed Data and Blocks</title>
      <link>https://vinoo.io/writing/2023-01-24-distributed-data-and-blocks/</link>
      <pubDate>Tue, 24 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2023-01-24-distributed-data-and-blocks/</guid>
      <description>Tuning the &amp;#39;chunks&amp;#39; of data that live on distributed file systems.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://vinooganesh.substack.com/p/distributed-data-and-blocks">Efficiently (Substack)</a></em></p>
<p>This is a continuation of a previous blog post about efficient data partitioning.</p>
<p>In the previous post, I discussed how data layout on disk impacts analytics performance. This post focuses on tactical implementation using open source technologies.</p>
<p>Topics I&rsquo;ll cover:</p>
<ol>
<li>HDFS</li>
<li>Blocks + Block Size</li>
<li>Block sizes + tradeoffs</li>
</ol>
<h2 id="background">Background</h2>
<p>Data organization on disk dramatically affects analytics performance. I previously explored row-oriented, columnar, and hybrid storage models — now let&rsquo;s connect these concepts to modern data infrastructure.</p>
<h2 id="hadoop">Hadoop</h2>
<p>Hadoop provides an ecosystem enabling:</p>
<ol>
<li>Distributed data storage (HDFS — Hadoop Distributed File System)</li>
<li>Data querying (MapReduce)</li>
<li>Compute resource management (YARN)</li>
<li>Additional commons library and object store (Ozone)</li>
</ol>
<p>This discussion focuses on HDFS as the most relevant storage-side component for understanding data partitioning.</p>
<h2 id="hdfs">HDFS</h2>
<p>Let&rsquo;s say you have an invaluable file that contains the names, addresses, and phone numbers of employees at your company.</p>
<p><img alt="Single server with employee data" height='ã' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-single-server_hu_4a9225ad49d791aa.webp" width='̠'></p>
<p>That file lives on a single server. What happens if the server goes down?</p>
<p><img alt="Server failure" height='Ĺ' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-server-failure_hu_f71ae30f2aa85d0f.webp" width='̠'></p>
<p>Nobody can access the file. That&rsquo;s a problem. So, you decide to store a copy of the file on two servers.</p>
<p><img alt="File replicated across two servers" height='ē' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-replication_hu_235c64de13b35da7.webp" width='̠'></p>
<p>Great — now if one server goes down, the file is still available. But what happens when someone updates the file? You now have two copies that need to stay in sync.</p>
<p><img alt="Synchronization problem" height='Ĺ' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-sync-problem_hu_55ec8d0dd02b271e.webp" width='̠'></p>
<p>This orchestration complexity is the central problem that HDFS solves.</p>
<h2 id="blocks">Blocks</h2>
<p>HDFS stores data in blocks. These are the same Blocks from the last post. They are indivisible segments of data.</p>
<p>A block represents the minimum amount of data readable in a single operation — any read requires reading at least one complete block.</p>
<p>Files are divided into blocks during storage.</p>
<p><img alt="File divided into blocks" height='ä' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-blocks_hu_a081ba7ca8158108.webp" width='̠'></p>
<p>These blocks are then distributed across multiple cluster nodes.</p>
<p><img alt="Blocks distributed across cluster nodes" height='ɘ' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-blocks-distributed_hu_d0d8485513512921.webp" width='̠'></p>
<p>And then replicated for fault tolerance.</p>
<p><img alt="Blocks with replication" height='Ʌ' loading="lazy" src="/writing/2023-01-24-distributed-data-and-blocks/hdfs-blocks-replicated_hu_c87cf08546966b45.webp" width='̠'></p>
<p><strong>Architecture Note:</strong> These diagrams intentionally simplify HDFS architecture, omitting NameNode/DataNode separation, clients, and other components. The focus remains on partitioning concepts.</p>
<h2 id="block-size">Block Size</h2>
<p>The default Hadoop block size is 128MB (previously 64MB). While initially seeming massive when working with small local files, this size becomes relevant when storing files of hundreds of gigabytes.</p>
<p>The block size is configurable on a per-client basis.</p>
<h3 id="tradeoffs">Tradeoffs</h3>
<p>Block size selection determines the number of chunks and corresponding I/O operations for reading and writing.</p>
<p><strong>Larger blocks:</strong></p>
<ul>
<li>Fewer blocks created</li>
<li>Fewer I/O operations needed</li>
<li>Increased memory requirements during processing</li>
</ul>
<p><strong>Smaller blocks:</strong></p>
<ul>
<li>More blocks created</li>
<li>More I/O operations required</li>
<li>Lower memory consumption per block</li>
<li>Benefits for small files and random access patterns</li>
<li>Increases NameNode metadata overhead</li>
<li>Creates scalability risks</li>
</ul>
<p>The <a href="https://blog.cloudera.com/the-small-files-problem/">small files problem</a> is a well-documented concern in distributed systems — too many small files create operational challenges.</p>
<p>Block size also impacts HDFS fault tolerance, though that falls outside this article&rsquo;s scope.</p>
<h2 id="tuning-for-efficiency">Tuning for Efficiency</h2>
<p>Reducing I/O through partition pruning provides substantial performance gains. Optimal block size selection yields strong results.</p>
<p>However, no universal solution exists. Selection depends on dataset characteristics, usage patterns, data type, use case, and additional factors.</p>
<p><strong>High-level recommendations:</strong></p>
<p><strong>Files under a few hundred megabytes:</strong> Use smaller block sizes (64MB or 128MB) to minimize wasted block space.</p>
<p><strong>Files several gigabytes or larger:</strong> Use larger block sizes (256MB or 512MB) to minimize generated blocks and unnecessary I/O.</p>
<p>These are just guidelines and selecting your optimal block size will likely require some testing on your side.</p>
]]></content:encoded>
    </item>
    <item>
      <title>On-Disk Storage Methods (w/ visualizations)</title>
      <link>https://vinoo.io/writing/2023-01-14-on-disk-storage-methods/</link>
      <pubDate>Sat, 14 Jan 2023 00:00:00 +0000</pubDate>
      <guid>https://vinoo.io/writing/2023-01-14-on-disk-storage-methods/</guid>
      <description>The way you write data can affect your performance. Exploring row-wise, columnar, and hybrid storage methods with visualizations.</description>
      <content:encoded><![CDATA[<p><em>Originally published on <a href="https://vinooganesh.substack.com/p/on-disk-storage-methods">Efficiently (Substack)</a></em></p>
<p>A few years ago, I gave a talk at <a href="https://www.databricks.com/session_na20/the-apache-spark-file-format-ecosystem">Spark Summit 2020</a> about File Formats covering Avro, ORC, and Parquet. I received numerous questions about that topic, responding point-to-point, leaving the knowledge confined to those forums alone.</p>
<p>That isn&rsquo;t helpful for most people. This post aims to fix that.</p>
<p>In this series, I&rsquo;ll outline the primitives of this topic and then explore the hands-on details.</p>
<h2 id="problem">Problem</h2>
<p>In the efficiency space, minimizing &ldquo;work&rdquo; is key. Whether work requires compute, network, or storage, &ldquo;the goal of efficient data usage is to get the most accurate answer in the fastest and cheapest way possible.&rdquo;</p>
<p>File Formats help data practitioners store their data in ways that minimize work. When you think of a file format, you may think of extensions like .xlsx, .pdf, .pptx. Similarly, technologies like Parquet, Avro, and ORC serve this purpose.</p>
<h2 id="background--example-data">Background / Example Data</h2>
<p>A partition is a logical segment of data. In the big data world, this usually means a piece of a larger dataset. For our purposes, I&rsquo;m going to use an example dataset below.</p>
<p>This dataset has 3 columns (Column A, Column B, and Column C) and 4 rows (Row 0, Row 1, Row 2, and Row 3).</p>
<p><img alt="Example data table" height='Ĺ' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/storage-example-table_hu_8baefa3a812c6cc7.webp" width='̠'></p>
<p>This table should look familiar — something you&rsquo;ve seen in Excel, Pandas, etc. Let&rsquo;s take this example further and split the individual elements into their own logical &ldquo;pieces.&rdquo;</p>
<p><img alt="Cell reference notation" height='ō' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/storage-cell-reference_hu_2231e9ea91e14a12.webp" width='̠'></p>
<p>We can refer to each &ldquo;cell&rdquo; by its &ldquo;&lt;column&gt;&lt;row&gt;.&rdquo; For example, the second row in Column B is called B1.</p>
<h2 id="storage">Storage</h2>
<h3 id="background">Background</h3>
<p>Data is stored on hard disks in what is called a <strong>block.</strong> A block is the minimum amount of data read during any read operation.</p>
<p>Blocks function like a suitcase. When checking a bag on a trip, you pay the same price regardless of how full or empty your suitcase is. It&rsquo;s optimal to fill your suitcase with as many relevant objects as possible, in as easy a way to find as possible.</p>
<p>Extending this analogy: packing unnecessary stuff isn&rsquo;t great. Bringing too many suitcases (unless strictly necessary) also isn&rsquo;t great. Inside the suitcase, you want to &ldquo;group&rdquo; similar things together — each pair of socks should be next to each other in the same suitcase, rather than split across different ones.</p>
<p>In hard drives, these insights apply. Reading unnecessary data is expensive. Reading fragmented data is expensive. Random seeks are expensive as well.</p>
<p>Our goal is to lay data out in a manner optimized for our workflows.</p>
<h3 id="row-wise-storage">Row-wise Storage</h3>
<p>In database land, the common way to store data used to be row-wise. It&rsquo;s pretty easy to understand why. Most people think about datasets as a list of rows.</p>
<p>Taking our dataset above, let&rsquo;s store this in a row-wise method.</p>
<p><img alt="Row-wise storage diagram" height='ś' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/row-wise-storage_hu_9b6d37bdbdf0da2.webp" width='̠'></p>
<p>I have taken each row in order and packed as much of the rows as I can into a block, before moving to the next block.</p>
<p>This method works great when the goal is to read the data sequentially. All that&rsquo;s required is a simple linear scan of the block in order. It doesn&rsquo;t work as well if, for example, you want to only look at Column C. In that case, you&rsquo;re required to read all of the block (i.e., read all of the data) and filter down to Column C.</p>
<p>This is <strong>row-wise</strong> storage methodology.</p>
<h3 id="columnar-column-wise-storage">Columnar (Column-wise) Storage</h3>
<p>Column-wise storage takes the opposite approach and orients around columns.</p>
<p><img alt="Columnar storage diagram" height='ŗ' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/columnar-storage_hu_1bce7707ed5e2a6b.webp" width='̠'></p>
<p>As you can see, we first take the entire column, pack it into a block, and then move onto the next column.</p>
<p>This method works great when the data is read in a columnar way (i.e., one column at a time). It doesn&rsquo;t work well if, for example, you want to reconstruct Row 0. In that situation, you&rsquo;d need to read all of the data and filter down to the elements that make up Row 0.</p>
<p>Now, we&rsquo;re in a dilemma — one approach seems to favor a row-oriented workflow, one approach seems to favor a column-oriented workflow. Luckily for us (and Goldilocks), there&rsquo;s a middle ground.</p>
<p><img alt="Goldilocks principle" height='ȕ' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/goldilocks_hu_70cd99c3e3eb2552.webp" width='̠'></p>
<h3 id="hybrid-storage">Hybrid Storage</h3>
<p>A hybrid storage model gives us the best of both worlds. First, we group a fixed number of Rows together and then further group that by columns. We segment these and call these &ldquo;Row Groups&rdquo; (at least in the Parquet terminology).</p>
<p>In this example, we first selected two rows — Row 0 and Row 1. We then grouped those rows by column, and inserted them into our first Row Group.</p>
<p><img alt="Logical row groups" height='Ŕ' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/storage-row-groups-logical_hu_28c4af6518c6d5c9.webp" width='̠'></p>
<p>I called these logical Row Groups because this is more of how we should be thinking about them, rather than how they may necessarily end up on disk.</p>
<p><img alt="Row groups on disk" height='Ī' loading="lazy" src="/writing/2023-01-14-on-disk-storage-methods/storage-row-groups-physical_hu_b50ebd16ae2331a6.webp" width='̠'></p>
<p>This representation of data is actually immensely powerful. It allows us to optimize our workflows for both row-oriented and column-oriented operations.</p>
<p>Let&rsquo;s talk about how this works.</p>
<p>In the case of a row-oriented workflow, let&rsquo;s say you want to recreate Row 2. To do this, you would simply need to look at Block 1 and Block 2. If you were operating in a Columnar storage model, you would need to look at Block 1, Block 2, and Block 3. You&rsquo;ve saved a whole Block!</p>
<p>In the case of a column-oriented workflow, let&rsquo;s say you want to recreate Column B. In this case, you would simply need to look at Block 1 and Block 2. If you were operating in a Row-wise storage model, you would need to look at Block 1, Block 2, and Block 3. You&rsquo;ve once again saved a whole Block!</p>
<p>Our examples used very small data, you can imagine how this extrapolates further with larger datasets.</p>
<h2 id="data-workflows">Data Workflows</h2>
<p>Throughout this post, I&rsquo;ve referred to my data workflows as &ldquo;row oriented&rdquo; or &ldquo;column oriented.&rdquo; Luckily for us, the big data community has come up with some terminology that should help bring these two workflows to life.</p>
<h3 id="oltp">OLTP</h3>
<p>Online Transaction Processing (OLTP) workloads generally involve larger amounts of short queries/transactions. These tend to be more focused on processing than analytics and as such have more data updates and deletions. Roughly — we can consider OLTP workflows as &ldquo;row oriented&rdquo; workflows.</p>
<h3 id="olap">OLAP</h3>
<p>Online Analytical Processing (OLAP) workloads are more analysis than processing focused. As such, there tends to be more analytical complexity per query and fewer CRUD transactions. Roughly — we can consider OLAP workflows as &ldquo;column oriented&rdquo; workflows.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Using data efficiently relies on using all levels of the &ldquo;data stack&rdquo; (storage, network, compute) efficiently. Reducing the amount of unnecessary data read during a query process can have compounding effects on the speed and efficiency of your analytics process.</p>
<p>In subsequent parts of this series, I&rsquo;ll be digging more into the details of how everything we have covered thus far can be applied in analytics workloads.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
