{"id":718391,"date":"2026-07-30T03:33:14","date_gmt":"2026-07-30T03:33:14","guid":{"rendered":"https:\/\/www.newsbeep.com\/uk\/718391\/"},"modified":"2026-07-30T03:33:14","modified_gmt":"2026-07-30T03:33:14","slug":"excel-was-my-database-for-15-years-and-postgres-ended-that-in-a-weekend","status":"publish","type":"post","link":"https:\/\/www.newsbeep.com\/uk\/718391\/","title":{"rendered":"Excel was my database for 15 years, and Postgres ended that in a weekend"},"content":{"rendered":"<p>For the better part of my life, my &#8220;database&#8221; has been a spreadsheet. Everything from inventory counts, project trackers, budget breakdowns, and even a homegrown CRM cobbled together with conditional formatting and VLOOKUPs I was weirdly proud of has been in Excel. Why? Because Excel worked, it was fast to open, easy to edit, and everyone I worked with already knew how to use it.<\/p>\n<p>Then, one fine day, my spreadsheets broke under their own weight, and I needed a proper database. It took a weekend of researching and migrations, but Postgres filled that gap perfectly.<\/p>\n<p>                                                                                                                            <a href=\"https:\/\/www.makeuseof.com\/excel-function-eliminated-hours-manual-text-combining\/\" rel=\"nofollow noopener\" target=\"_blank\"><br \/>\n                        <img width=\"440\" height=\"248\" loading=\"lazy\" decoding=\"async\" alt=\"Excel on iPad pro on wooden desk.\" data-img-url=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/excel-on-ipad-pro.jpg\" src=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/excel-on-ipad-pro.jpg\"\/><\/p>\n<p>                    <\/a><\/p>\n<p>                    Related<\/p>\n<p>\t\t<a href=\"https:\/\/www.makeuseof.com\/excel-function-eliminated-hours-manual-text-combining\/\" title=\"This Excel function eliminated hours of manual text combining\" target=\"_blank\" rel=\"nofollow noopener\"><br \/>\n\t\t\tThis Excel function eliminated hours of manual text combining<br \/>\n\t\t<\/a><\/p>\n<p class=\"display-card-excerpt\">Sifting through data just got easier with this quick and easy Excel formula. <\/p>\n<p>                        Spreadsheets quietly became my database<\/p>\n<p>            Years of growth exposed Excel&#8217;s limits<\/p>\n<p>Nobody plans to outgrow a spreadsheet. You don&#8217;t wake up one day and decide <a href=\"https:\/\/www.makeuseof.com\/when-to-stop-using-excel-and-switch-to-something-else\/\" target=\"_blank\" rel=\"nofollow noopener\">it&#8217;s time to stop using Excel and switch to something else<\/a>. It happens gradually \u2014 a single spreadsheet becomes three tabs, then ten, then a master file referencing half a dozen others. Formulas start pointing at cells that got deleted years ago. Then someone fat-fingers a filter, and half your rows vanish, and you don&#8217;t even realize that until it&#8217;s time to get something useful out of the mess of data you call a database.<\/p>\n<p>The real problem isn&#8217;t the errors themselves; it&#8217;s that Excel&#8217;s safeguards are all optional. You can go the route of <a href=\"https:\/\/www.makeuseof.com\/error-checked-spreadsheets-with-excel-data-validation-and-caught-mistakes\/\" target=\"_blank\" rel=\"nofollow noopener\">replacing error-checking spreadsheets with Excel data validation<\/a> to catch mistakes before they happen, and Power Pivot can even model relationships between sheets, but almost nobody sets these up, and nothing stops you from overriding them later. There&#8217;s no enforced relationship the way a foreign key enforces one between tables. Every safeguard is a manual habit, and habits break under deadline pressure more often than you&#8217;d like.<\/p>\n<p>                        Postgres solved problems Excel never could<\/p>\n<p>            Built for structured, reliable data<\/p>\n<p>        <img width=\"1650\" height=\"886\" loading=\"lazy\" decoding=\"async\" alt=\"DBweaver showing Postgres database.\" data-img-url=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/dbweaver-showing-postgres-database.jpg\" src=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/dbweaver-showing-postgres-database.jpg\" class=\"img-brightness-opt-out\"\/><br \/>\n        Screenshot by Yadullah Abidi | No Attribution Required.<\/p>\n<p> My breaking point came when I realized I needed to cross-reference three spreadsheets to answer a question that should have taken 30 seconds. Instead, it took an afternoon of VLOOKUPs and copy-pasting, and I still wasn&#8217;t confident in the answer. That frustration finally pushed me to figure out a database solution, and Postgres was the perfect fit. It&#8217;s easy to set up, runs as a containerized service, and is easily pluggable into local LLMs for AI analysis.<\/p>\n<p>Given my usual habits of running things in Docker \u2014 these six Docker containers made my home server worth it long before this \u2014 spinning up Postgres wasn&#8217;t a huge leap. You just need the basics, and a Docker Compose file with a named volume for persistent storage had it running in under 10 minutes. I also had prior experience working with Postgres when <a href=\"https:\/\/www.makeuseof.com\/fixed-claudes-memory-problem-postgres-database-changed-everything\/\" target=\"_blank\" rel=\"nofollow noopener\">I fixed Claude&#8217;s memory issues by giving it a Postgres database<\/a>.<\/p>\n<p>                        One weekend was all it took<\/p>\n<p>            The migration was easier than expected<\/p>\n<p>The migration process took some planning, but it was easy enough to do. I started with my messiest spreadsheet, a client and order tracker held together with formulas, and sketched out the actual tables: customers, orders, payments. That exercise alone, thinking in normalized tables instead of flat rows, exposed how much duplicate and inconsistent data I&#8217;d been carrying around for years. Then I wrote a small Python script using pandas to read the old file, clean it up, and insert everything into Postgres with psycopg, the most popular Postgres adapter for Python.<\/p>\n<p>This put the schema in place with foreign keys and constraints. I spent the next day watching those constraints do the work I used to do by hand. A company was in the sheet twice under the same email, re-entered months later with a trailing space in the name that made it look new; the unique constraint on email refused the duplicate instead of letting a second copy sit there. One order had no date at all, and the non-null constraint kicked it back instead of letting it pollute my data ( I did have to track down the original entry and fix it).<\/p>\n<p>Another referenced a customer email that didn&#8217;t exist on the list at all, the kind of stray entry a VLOOKUP would happily return a blank for. Postgres&#8217;s foreign key rejected it outright. One payment had &#8220;paid in full&#8221; typed into the amount column instead of a number, which Postgres refused to store as currency until I fixed it.<\/p>\n<p>Not every messy column turned into a dramatic catch, though. My invoice column had yes, no, true, and N scattered across it, and Postgres&#8217;s boolean type parsed almost all of it happily. Constraints stop bad data, not bad formatting.<\/p>\n<p>                        Everything became easier to manage<\/p>\n<p>            Cleaner data, faster queries, fewer mistakes<\/p>\n<p>        <img width=\"1650\" height=\"886\" loading=\"lazy\" decoding=\"async\" alt=\"Postgres dashboard.\" data-img-url=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/postgres-dashboard.jpg\" src=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/postgres-dashboard.jpg\" class=\"img-brightness-opt-out\"\/><br \/>\n        Screenshot by Yadullah Abidi | No Attribution Required.<\/p>\n<p> The difference isn&#8217;t just speed, although that&#8217;s a major benefit. The client-invoicing question that used to take an afternoon in Excel is now a five-line SQL query, and my Flash dashboard shows the answer the moment the page loads. I no longer wonder if a formula got dragged into the wrong cell or someone overwrote a value. The database enforces rules I used to enforce through memory and vigilance. When it can&#8217;t, it fails loudly and forces me to fix the problem before it snowballs.<\/p>\n<p>Another major advantage is that I can literally talk to my data now, courtesy of a couple of local LLMs and Claude all having access to the same database. So for the most part, I don&#8217;t even have to write SQL. Simply asking my AI agents to find me a piece of data works well enough. Backups also run on schedule now, instead of me hoping I remembered to save a versioned copy before making permanent changes.<\/p>\n<p>                        Excel still has a place<\/p>\n<p>            Great for analysis, not long-term storage<\/p>\n<p>Excel isn&#8217;t useless, and I still use it for sharing data with people who aren&#8217;t going to run SQL queries. But as a system of record, it was never built for the job I was asking it to do.<\/p>\n<p>                                                                                                                            <a href=\"https:\/\/www.makeuseof.com\/local-llm-setup-was-missing-one-tiny-model-that-changed-everything\/\" rel=\"nofollow noopener\" target=\"_blank\"><br \/>\n                        <img width=\"440\" height=\"248\" loading=\"lazy\" decoding=\"async\" alt=\"Gemma 4 responding to a prompt on a MacBook in LM Studio\" data-img-url=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/gemma-4-responding-to-a-prompt-on-a-macbook-in-lm-studio.jpeg\" src=\"https:\/\/www.newsbeep.com\/uk\/wp-content\/uploads\/2026\/07\/gemma-4-responding-to-a-prompt-on-a-macbook-in-lm-studio.jpeg\"\/><\/p>\n<p>                    <\/a><\/p>\n<p>                    Related<\/p>\n<p>\t\t<a href=\"https:\/\/www.makeuseof.com\/local-llm-setup-was-missing-one-tiny-model-that-changed-everything\/\" title=\"The fix for local LLMs was never a bigger model\" target=\"_blank\" rel=\"nofollow noopener\"><br \/>\n\t\t\tThe fix for local LLMs was never a bigger model<br \/>\n\t\t<\/a><\/p>\n<p class=\"display-card-excerpt\">My local LLM kept choking on context until I added this 500MB model.<\/p>\n<p>Postgres didn&#8217;t just replace a tool for me. It replaced a fragile mental model I&#8217;d been patching for a very long time. The only regret I have is not migrating sooner.<\/p>\n","protected":false},"excerpt":{"rendered":"For the better part of my life, my &#8220;database&#8221; has been a spreadsheet. Everything from inventory counts, project&hellip;\n","protected":false},"author":2,"featured_media":718392,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[59,86,56,54,55],"class_list":["post-718391","post","type-post","status-publish","format-standard","has-post-thumbnail","category-technology","tag-gb","tag-technology","tag-uk","tag-united-kingdom","tag-unitedkingdom"],"_links":{"self":[{"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/posts\/718391","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/comments?post=718391"}],"version-history":[{"count":0,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/posts\/718391\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/media\/718392"}],"wp:attachment":[{"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/media?parent=718391"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/categories?post=718391"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.newsbeep.com\/uk\/wp-json\/wp\/v2\/tags?post=718391"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}