<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vlad (Volodymyr Shiyan)</title>
    <description>The latest articles on DEV Community by Vlad (Volodymyr Shiyan) (@vladshiyan).</description>
    <link>https://dev.to/vladshiyan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4092274%2F67de7e05-639c-49a6-af42-fa87e959c81d.png</url>
      <title>DEV Community: Vlad (Volodymyr Shiyan)</title>
      <link>https://dev.to/vladshiyan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vladshiyan"/>
    <language>en</language>
    <item>
      <title>Building Offline-First Invoicing Software: Why Local Storage Matters for Freelancers</title>
      <dc:creator>Vlad (Volodymyr Shiyan)</dc:creator>
      <pubDate>Fri, 16 Oct 2026 02:40:26 +0000</pubDate>
      <link>https://dev.to/vladshiyan/building-offline-first-invoicing-software-why-local-storage-matters-for-freelancers-4e6i</link>
      <guid>https://dev.to/vladshiyan/building-offline-first-invoicing-software-why-local-storage-matters-for-freelancers-4e6i</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcp1kn9upzvesolg4c4ll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcp1kn9upzvesolg4c4ll.png" alt="LockMargin 3D nautilus logo — local-first invoicing software for freelancers" width="96" height="96"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;This article was originally published on the &lt;a href="https://lockmargin.com/blog/invoicing-software-for-freelancers.html" rel="noopener noreferrer"&gt;LockMargin blog&lt;/a&gt;. I'm Vlad Shiyan, founder and developer of LockMargin — a local-first Financial OS for freelancers who are tired of renting their tools. Below is a technical deep-dive into the architecture choices behind the product.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Most freelancers don't fully control the software that runs their business. Invoices, client lists, payment history — a lot of it sits on someone else's servers. Access often depends on a monthly payment and a working internet connection. Moving away later can turn into a bigger headache than expected.&lt;/p&gt;

&lt;p&gt;I built LockMargin around one question: &lt;strong&gt;what should a freelancer actually own?&lt;/strong&gt; This guide walks through the main models, the features that matter, and the real trade-offs. I'm not here to crown a winner. I just want you to choose with your eyes open.&lt;/p&gt;

&lt;p&gt;If the ownership angle interests you, start with &lt;a href="https://lockmargin.com/manifesto.html" rel="noopener noreferrer"&gt;The Ownership Manifesto&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes Invoicing Software Different for Freelancers?
&lt;/h2&gt;

&lt;p&gt;A company with an accounting team and a solo freelancer both need invoices. Their daily reality looks nothing alike.&lt;/p&gt;

&lt;p&gt;A bigger company needs roles, approval chains, consolidated reports, and integrations across departments. A freelancer usually needs to create an invoice, mark a payment, check what's still outstanding, and get back to paid work.&lt;/p&gt;

&lt;p&gt;That difference changes what "good software" means.&lt;/p&gt;

&lt;p&gt;Useful priorities for most freelancers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; — routine invoices should take minutes, not a long setup ritual&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictable cost&lt;/strong&gt; — the price should make sense for a one-person business&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliable records&lt;/strong&gt; — client details, amounts, dates, and status should stay consistent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt; — you should be able to back up and move your data without drama&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt; — you should know where the data lives and who can see it&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A workflow that doesn't feel like learning an enterprise platform&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subscriptions aren't automatically bad. They can cover hosting, collaboration, support, and ongoing development. Cloud access across devices is genuinely useful for some people.&lt;/p&gt;

&lt;p&gt;The question is whether those benefits justify the cost and the dependency for your work.&lt;/p&gt;

&lt;p&gt;Someone who works with an assistant across several devices may prefer a hosted tool. Someone who works alone on one Windows machine may prefer desktop software with local storage and full control over backups.&lt;/p&gt;

&lt;p&gt;Neither choice is more professional. The right one simply fits how you actually work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features Worth Checking
&lt;/h2&gt;

&lt;p&gt;Before you compare brands, write down the tasks you do every week.&lt;/p&gt;

&lt;p&gt;At minimum you need client records, line items, totals, payment terms, due dates, a way to export invoices, and a way to record payments. Depending on your work you may also want recurring invoices, expense tracking, tax fields, multi-currency support, or project-level reporting.&lt;/p&gt;

&lt;p&gt;Then look at the parts that usually get glossed over.&lt;/p&gt;

&lt;h3&gt;
  
  
  Offline-First Architecture
&lt;/h3&gt;

&lt;p&gt;"Offline" means different things in different products.&lt;/p&gt;

&lt;p&gt;Some tools let you view a cached invoice without internet. Others let you create records locally and sync later. A few are designed so the local database is the real working copy.&lt;/p&gt;

&lt;p&gt;Those are different architectures.&lt;/p&gt;

&lt;p&gt;With a true local-first desktop app, the data lives on your machine. You can create and edit invoices without waiting for a server. Internet is only needed for the rare things you choose to do online.&lt;/p&gt;

&lt;p&gt;Check these points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you create and edit records while completely offline?&lt;/li&gt;
&lt;li&gt;Where is the primary copy of the data stored?&lt;/li&gt;
&lt;li&gt;Does the app need periodic online authentication?&lt;/li&gt;
&lt;li&gt;What happens when you reconnect?&lt;/li&gt;
&lt;li&gt;Can you export everything without going through a cloud service?&lt;/li&gt;
&lt;li&gt;How do backups and restores actually work?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Local storage has trade-offs. If your computer dies and you have no usable backup, the records are gone. A cloud service may handle some of that for you — but you still need to understand its retention and recovery rules.&lt;/p&gt;

&lt;p&gt;Offline-first is not a substitute for backups. It just changes who controls the working data.&lt;/p&gt;

&lt;p&gt;More detail on how LockMargin handles this: &lt;a href="https://lockmargin.com/security.html" rel="noopener noreferrer"&gt;Security&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  One-Time Payment vs Subscription
&lt;/h3&gt;

&lt;p&gt;A subscription spreads the cost. A one-time licence puts more of it upfront and can make future spending easier to predict.&lt;/p&gt;

&lt;p&gt;Neither model tells the full story. Compare the total cost over the time you expect to use the tool, including any extra fees for users, exports, or support.&lt;/p&gt;

&lt;p&gt;Example with a $19/month subscription:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Period&lt;/th&gt;
&lt;th&gt;Subscription ($19/mo)&lt;/th&gt;
&lt;th&gt;One-time licence ($49)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1 year&lt;/td&gt;
&lt;td&gt;$228&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3 years&lt;/td&gt;
&lt;td&gt;$684&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5 years&lt;/td&gt;
&lt;td&gt;$1,140&lt;/td&gt;
&lt;td&gt;$49&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These numbers only compare the stated software prices. They ignore taxes, optional services, and any future upgrades.&lt;/p&gt;

&lt;p&gt;Ask four practical questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the recurring fee mandatory?&lt;/li&gt;
&lt;li&gt;What stops working if I cancel?&lt;/li&gt;
&lt;li&gt;Can I still access and export my records after cancellation?&lt;/li&gt;
&lt;li&gt;What updates and support are actually included?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A one-time payment doesn't magically guarantee lifetime updates or compatibility with every future operating system. Read the licence.&lt;/p&gt;

&lt;p&gt;LockMargin Standard is $49 once. The point is predictable pricing and local control — not a claim that software never needs maintenance.&lt;/p&gt;

&lt;p&gt;Current terms: &lt;a href="https://lockmargin.com/pricing.html" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Ownership and Privacy
&lt;/h3&gt;

&lt;p&gt;Your invoices and client records are business assets. Choosing software means choosing how those assets are stored, protected, and retrieved.&lt;/p&gt;

&lt;p&gt;Three separate things matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Legal ownership&lt;/strong&gt; — what the agreements and applicable law say&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technical control&lt;/strong&gt; — where the data physically lives and who can reach it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Portability&lt;/strong&gt; — whether you can get the data out and use it elsewhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A product can give you export rights while still keeping the primary copy on its servers. Another can store data locally but make export painful. You need all three to be solid.&lt;/p&gt;

&lt;p&gt;Look for clear answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can I export client and invoice records in a documented format?&lt;/li&gt;
&lt;li&gt;Does the export include the fields I actually need, or just a PDF?&lt;/li&gt;
&lt;li&gt;Can I back everything up and restore it on another machine?&lt;/li&gt;
&lt;li&gt;Is sensitive data encrypted at rest?&lt;/li&gt;
&lt;li&gt;How are the encryption keys protected?&lt;/li&gt;
&lt;li&gt;Does the app collect telemetry, and can I turn it off?&lt;/li&gt;
&lt;li&gt;What data, if any, leaves my computer during normal use?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CSV and JSON are useful for moving records. SQLite is useful when the local database is well documented. A PDF is fine for sending an invoice — it is not a substitute for a full export.&lt;/p&gt;

&lt;p&gt;Encryption needs precision. &lt;strong&gt;AES-256-GCM&lt;/strong&gt; is an authenticated encryption algorithm. &lt;strong&gt;Argon2id&lt;/strong&gt; is a password-hashing and key-derivation function. What matters is how the application uses them, protects the keys, and handles recovery if you forget the password.&lt;/p&gt;

&lt;p&gt;No model removes every risk. Local software can still be hit by malware or a stolen laptop. Cloud software can offer strong access controls and managed recovery. Choose the risks you understand and can live with.&lt;/p&gt;

&lt;p&gt;LockMargin's approach is described in &lt;a href="https://lockmargin.com/security.html" rel="noopener noreferrer"&gt;Security&lt;/a&gt;. The reasoning behind it is in &lt;a href="https://lockmargin.com/manifesto.html" rel="noopener noreferrer"&gt;The Ownership Manifesto&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multi-Currency Support
&lt;/h3&gt;

&lt;p&gt;If you work with clients in different countries, currency handling is not a nice-to-have.&lt;/p&gt;

&lt;p&gt;A good tool lets you set the invoice currency, show amounts clearly, and keep the values the client agreed to. You may also need the exchange rate recorded for your own bookkeeping.&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you set a default currency per client?&lt;/li&gt;
&lt;li&gt;Can an invoice use a different currency from your usual one?&lt;/li&gt;
&lt;li&gt;Is the exchange rate stored, and can you see its source and date?&lt;/li&gt;
&lt;li&gt;Are the original amounts preserved if rates change later?&lt;/li&gt;
&lt;li&gt;Can you tell the invoiced amount from the amount you actually received?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An exchange rate that changes after the invoice is issued should not silently rewrite history. LockMargin's approach is called &lt;strong&gt;Snapshot Billing&lt;/strong&gt;: the relevant billing values are frozen at the moment the invoice is created. See the current implementation on &lt;a href="https://lockmargin.com/features.html" rel="noopener noreferrer"&gt;Features&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Immutable Invoices
&lt;/h3&gt;

&lt;p&gt;An invoice is a business record. Once you've sent it, you should be able to show exactly what it said.&lt;/p&gt;

&lt;p&gt;Legal requirements for invoices, corrections, and credit notes differ by country. There is no universal workflow that satisfies every jurisdiction. Check the rules that apply to you.&lt;/p&gt;

&lt;p&gt;From a software point of view, look for a clear distinction between draft and issued. After issuance, changing the original record should be hard or impossible without leaving a clear trail.&lt;/p&gt;

&lt;p&gt;You should be able to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which version was issued?&lt;/li&gt;
&lt;li&gt;When?&lt;/li&gt;
&lt;li&gt;What amount and currency did it show?&lt;/li&gt;
&lt;li&gt;Was it paid, partially paid, or still open?&lt;/li&gt;
&lt;li&gt;If a correction was needed, how was it documented?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the right move is a credit note or a formal replacement. Simply editing the old invoice is not always acceptable.&lt;/p&gt;

&lt;p&gt;An audit trail only helps if it is complete and protected against casual changes. More on how LockMargin handles this: &lt;a href="https://lockmargin.com/features.html" rel="noopener noreferrer"&gt;Features&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cloud vs Desktop: Which Model Fits You?
&lt;/h2&gt;

&lt;p&gt;The choice comes down to how you work, how much risk you accept, and how much control you want.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Consideration&lt;/th&gt;
&lt;th&gt;Cloud software&lt;/th&gt;
&lt;th&gt;Desktop software&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Access&lt;/td&gt;
&lt;td&gt;Often available on any device&lt;/td&gt;
&lt;td&gt;Usually tied to the installed computer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internet&lt;/td&gt;
&lt;td&gt;Commonly required for full use&lt;/td&gt;
&lt;td&gt;Can work offline if designed for it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collaboration&lt;/td&gt;
&lt;td&gt;Usually easier for teams&lt;/td&gt;
&lt;td&gt;Often needs a separate sharing process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backups&lt;/td&gt;
&lt;td&gt;Often handled by the provider&lt;/td&gt;
&lt;td&gt;Usually your responsibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data location&lt;/td&gt;
&lt;td&gt;Typically on provider infrastructure&lt;/td&gt;
&lt;td&gt;Can be fully local&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing&lt;/td&gt;
&lt;td&gt;Often subscription&lt;/td&gt;
&lt;td&gt;May offer a one-time licence&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Provider handles most infrastructure&lt;/td&gt;
&lt;td&gt;You handle install, updates, and recovery&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are tendencies, not hard rules. Some cloud tools have solid offline features and good exports. Some desktop tools still depend on online services. Judge the actual product.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Cloud Makes Sense
&lt;/h3&gt;

&lt;p&gt;Cloud is often the better fit if several people need to work on the same records, you switch devices constantly, or you rely on integrated payment and accounting services.&lt;/p&gt;

&lt;p&gt;The monthly cost can be reasonable if it replaces work you would otherwise have to do yourself. Managed backups and support can also be worth paying for — as long as you understand their limits.&lt;/p&gt;

&lt;p&gt;Before you commit, check cancellation terms, export quality, data retention, and what happens if the provider changes pricing or shuts down the product.&lt;/p&gt;

&lt;h3&gt;
  
  
  When Desktop Makes Sense
&lt;/h3&gt;

&lt;p&gt;Desktop software often fits better if you work alone, mostly on one computer, and want direct control over your records.&lt;/p&gt;

&lt;p&gt;It can reduce dependence on internet access and remote infrastructure. A one-time licence can make the cost more predictable.&lt;/p&gt;

&lt;p&gt;The trade-off is responsibility. You need a backup routine and a recovery plan. If you expect real-time collaboration, check whether a desktop workflow can actually support it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Offline-First Hybrid
&lt;/h3&gt;

&lt;p&gt;Some desktop tools keep the primary records local and let you export or copy them wherever you want. That is different from automatic cloud sync. Copying a database file to Dropbox is not the same as safe multi-device synchronisation. Simultaneous edits can create conflicts.&lt;/p&gt;

&lt;p&gt;Choose the model that matches how you actually work. For a concrete comparison of one cloud option, see &lt;a href="https://lockmargin.com/vs/vs-freshbooks.html" rel="noopener noreferrer"&gt;LockMargin vs FreshBooks&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Choose the Right Invoicing Software
&lt;/h2&gt;

&lt;p&gt;You don't need to compare every feature of every product. Start with the requirements that would make a tool unusable for you.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Decide how you need to access your records.&lt;/strong&gt; One computer or several devices and collaborators? Be honest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the complete cost.&lt;/strong&gt; Look at one, three, and five years. Include mandatory add-ons and what happens if you cancel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test the export.&lt;/strong&gt; Create sample clients and invoices, export them, and open the files. Check dates, currencies, line items, and payment status. A button labelled "Export" doesn't tell you enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test backup and recovery.&lt;/strong&gt; Find out how to back up and restore. If the data is local, keep a copy somewhere other than the main machine. If the provider manages backups, check retention and restore procedures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the billing workflow.&lt;/strong&gt; Create a test invoice, issue it, then check how corrections are handled. Make sure you can still retrieve the original amount and status later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review security and privacy.&lt;/strong&gt; Read the privacy policy and technical docs. Look for concrete answers about storage, encryption, key management, and telemetry. Vague assurances are not enough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the limitations.&lt;/strong&gt; Supported operating systems, currency features, licensing terms, and support. A tool can be excellent without supporting every platform — as long as its limits don't conflict with your needs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finally, run a realistic test. Add a client, create an invoice, record a payment, export everything. You'll learn more in fifteen minutes than from any feature list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Your First Invoice in Five Steps
&lt;/h2&gt;

&lt;p&gt;Once you've chosen the software, the basic loop is simple. Labels differ, but the steps are the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Enter your business details
&lt;/h3&gt;

&lt;p&gt;Add whatever your invoices legally need — name, address, tax ID, payment instructions. Check the rules that apply to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Add the client
&lt;/h3&gt;

&lt;p&gt;Name, contact details, currency, payment terms. Don't assume every client will use the same settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create the invoice
&lt;/h3&gt;

&lt;p&gt;Clear description of the work, quantities, rates, taxes, due date. Review the totals before you issue it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Send or export
&lt;/h3&gt;

&lt;p&gt;PDF or email, depending on the tool. Check the finished document — client details, invoice number, currency, totals, payment instructions. Keep a copy of what you sent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Record the payment and back up
&lt;/h3&gt;

&lt;p&gt;Update the status when money arrives. If the client pays in instalments, keep the remaining balance clear. Then make sure your records are backed up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Own Your Tools, Own Your Business
&lt;/h2&gt;

&lt;p&gt;The best invoicing software for freelancers is not the one with the longest feature list. It's the one that fits your actual workflow, protects the records you depend on, and makes the costs and trade-offs clear.&lt;/p&gt;

&lt;p&gt;Cloud tools can be excellent for collaboration and multi-device access. Desktop tools can give simpler local control and more predictable pricing. Offline-first software makes working without a constant connection practical — but you still need a sensible backup plan.&lt;/p&gt;

&lt;p&gt;The questions that matter are straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where does the data live?&lt;/li&gt;
&lt;li&gt;Can you get it out?&lt;/li&gt;
&lt;li&gt;What happens when you stop paying?&lt;/li&gt;
&lt;li&gt;Can you prove what you sent?&lt;/li&gt;
&lt;li&gt;Are you paying for features that actually help you?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built LockMargin because I wanted more control over the tools behind my own work. It is currently Windows-first. There is no mobile app yet. The Standard licence is $49 once. Those details matter when you decide whether it fits your setup.&lt;/p&gt;

&lt;p&gt;If local-first invoicing matches the way you work, take a look at &lt;a href="https://lockmargin.com/download.html" rel="noopener noreferrer"&gt;Download&lt;/a&gt; and the current &lt;a href="https://lockmargin.com/pricing.html" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Own your tools. Don't rent them by default.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Further reading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://lockmargin.com/manifesto.html" rel="noopener noreferrer"&gt;The Ownership Manifesto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lockmargin.com/features.html" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lockmargin.com/security.html" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lockmargin.com/pricing.html" rel="noopener noreferrer"&gt;Pricing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lockmargin.com/vs/vs-freshbooks.html" rel="noopener noreferrer"&gt;LockMargin vs FreshBooks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;About the Author&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuumqhywwhmxb2u174no.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuumqhywwhmxb2u174no.png" alt="Portrait of Vlad Shiyan, founder and developer of LockMargin." width="122" height="116"&gt;&lt;/a&gt;Vlad Shiyan — Founder &amp;amp; Developer, Kharkiv, Ukraine. Building LockMargin since December 2025. Offline-first invoicing for freelancers who are tired of subscriptions. Standard is $49 one-time. &lt;a href="https://lockmargin.com/about.html" rel="noopener noreferrer"&gt;Read more about Vlad →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sqlite</category>
      <category>privacy</category>
      <category>freelance</category>
    </item>
    <item>
      <title>Why I published the format before the product</title>
      <dc:creator>Vlad (Volodymyr Shiyan)</dc:creator>
      <pubDate>Mon, 28 Sep 2026 16:13:40 +0000</pubDate>
      <link>https://dev.to/vladshiyan/why-i-published-the-format-before-the-product-od5</link>
      <guid>https://dev.to/vladshiyan/why-i-published-the-format-before-the-product-od5</guid>
      <description>&lt;p&gt;The data layer is open before the product launches. Here is why I made the schema, export formats, and decryption tool public first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The promise that required proof
&lt;/h2&gt;

&lt;p&gt;LockMargin's core promise is simple: your business keeps working even if I disappear. No license server, no account, no phone-home. The license is a signed token the app verifies offline; the token carries no expiration date.&lt;/p&gt;

&lt;p&gt;But a promise without evidence is marketing. The honest ceiling post showed what happens when someone tries to pirate the binary — the check can be patched, the key can leak, the shell can be copied. The asymmetry that actually protects the user is not the binary. It is the data.&lt;/p&gt;

&lt;p&gt;A cracked LockMargin is a shell. What a freelancer keeps in it — five years of invoices, clients, time entries — lives in an open SQLite format whose spec is public. The value isn't in my code staying secret. It is in the records staying readable, verifiable, and theirs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is open today
&lt;/h2&gt;

&lt;p&gt;The data layer went public in September 2026, before Early Access opened and before the first customer paid: github.com/vladsh444/lockmargin-data-layer under MIT license.&lt;/p&gt;

&lt;p&gt;The repository contains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The SQLite schema the app uses today — 33 tables across 4 groups, reconstructed from the application documentation&lt;/li&gt;
&lt;li&gt;Plaintext export formats (CSV, JSON) with full fidelity&lt;/li&gt;
&lt;li&gt;The encrypted .lockmargin container format specification&lt;/li&gt;
&lt;li&gt;A reference decrypt-cli in pure Python — no dependencies, verifiable round-trips&lt;/li&gt;
&lt;li&gt;Sample databases generated from the same schema the app uses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The decrypt-cli and scripts/build_sample.py reproduce the schema verbatim in their own SCHEMA constant, so the documentation, the samples, and the round-trip verification always agree.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why before launch
&lt;/h2&gt;

&lt;p&gt;Three reasons.&lt;/p&gt;

&lt;p&gt;Trust is earned before the first payment. A freelancer evaluating LockMargin can verify today — without buying, without trusting me — that their data will never be trapped. They can run the decrypt tool on a sample file. They can read the schema. They can write their own importer. The proof exists before the ask.&lt;/p&gt;

&lt;p&gt;The format is the product. In a local-first tool, the file format is the API. It is the migration path, the backup strategy, the integration surface, the exit door. Shipping the format late means shipping the product without its most important interface. Shipping it first means the interface is battle-tested by the time the first customer depends on it.&lt;/p&gt;

&lt;p&gt;Community review catches mistakes I would miss. The schema has been public since August. Reviewers outside the project have already spotted edge cases in the encryption envelope and the export normalization; both fixes are in the app before Early Access, and the round-trip tools above are how I verify them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cost of waiting
&lt;/h2&gt;

&lt;p&gt;The alternative — keeping the format private until after launch — buys a false sense of control. It delays the only proof that matters: can a third party read the data without the app? If the answer is no, the promise is fiction. If the answer is yes, publishing early only accelerates the verification.&lt;/p&gt;

&lt;p&gt;There is no competitive moat in a SQLite schema, and publishing it means giving up some control: someone can build a reader, an exporter, even a competing client around the same data. That is not a bug in the design. It is the point. I want to be paid for the application around the format, not for keeping the format secret. The schema is just the honest foundation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for you
&lt;/h2&gt;

&lt;p&gt;If you are evaluating LockMargin: you can verify the exit door before you walk through the entrance. Clone the repo, run decrypt-cli on a sample, inspect the CSV. The format will not change without a public amendment and a migration path.&lt;/p&gt;

&lt;p&gt;If you are building local-first software: consider publishing your format first. It forces clarity in the schema, it invites review before users depend on it, and it turns "trust me" into "verify it".&lt;/p&gt;

&lt;p&gt;The honest ceiling post explored the binary side of the asymmetry — what happens when the app is cracked. This post is the data side: the format is open, the tools are public, the records are yours. The binary can be copied. The data stays readable.&lt;/p&gt;

&lt;p&gt;If this resonates, read the manifesto: the Ownership Manifesto (&lt;a href="https://lockmargin.com/manifesto.html" rel="noopener noreferrer"&gt;https://lockmargin.com/manifesto.html&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;If you are building local-first software, where would you draw the line between an open data format and the parts of the product you keep proprietary? I'd be interested in how others handle that boundary.&lt;/p&gt;

&lt;p&gt;Vlad Shiyan writes the code, breaks the features, and answers the emails.&lt;/p&gt;

&lt;p&gt;Canonical version with full references: &lt;a href="https://lockmargin.com/blog/why-i-published-the-format-before-the-product.html" rel="noopener noreferrer"&gt;https://lockmargin.com/blog/why-i-published-the-format-before-the-product.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>buildinpublic</category>
      <category>software</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Honest Ceiling of Offline License Verification</title>
      <dc:creator>Vlad (Volodymyr Shiyan)</dc:creator>
      <pubDate>Mon, 07 Sep 2026 12:30:00 +0000</pubDate>
      <link>https://dev.to/vladshiyan/the-honest-ceiling-of-offline-license-verification-5a1</link>
      <guid>https://dev.to/vladshiyan/the-honest-ceiling-of-offline-license-verification-5a1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally published on &lt;a href="https://lockmargin.com/blog/the-honest-ceiling.html" rel="noopener noreferrer"&gt;lockmargin.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last weekend I asked myself an uncomfortable question: could someone post my app and a valid license key on a torrent, and anyone use it for free? The answer is yes. That question sat with me all weekend.&lt;br&gt;
I couldn't build anything else until I mapped it, so this is the map.&lt;/p&gt;

&lt;p&gt;Context: I'm building LockMargin, a local-first invoicing app for&lt;br&gt;
freelancers. $49 once. No account. No telemetry. No phone-home of any kind. The license is a signed token the app verifies locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  The threat model
&lt;/h2&gt;

&lt;p&gt;First, I narrowed the problem. I'm not trying to stop professional cracking crews or commercial resellers. I'm trying to survive the casual kind: a key shared in a chat, an installer plus key on a torrent, "send me your key" between friends.&lt;/p&gt;

&lt;p&gt;Then I drew a hard line. If a mechanism breaks on a new laptop, a&lt;br&gt;
wiped disk, a VM - it's out. If it needs a server - out. If it needs an account - out. The app has to keep working even if my company disappears. Every option on my list had to pass that test.&lt;/p&gt;

&lt;h2&gt;
  
  
  The honest ceiling
&lt;/h2&gt;

&lt;p&gt;Here is the fact most DRM marketing hides: if an application can&lt;br&gt;
locally answer "this token is valid," then anyone holding the same token gets the same answer. Copying the authorization is always possible when verification is local.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That is not an implementation flaw. It is the architecture.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two different things get conflated here. Authenticity: did I publish this binary? Code signing answers that. Authorization: does this person own a license? A signed local token answers that. Neither prevents a buyer from handing a valid token to somebody else.&lt;/p&gt;

&lt;p&gt;And two different threats. Sharing is when a buyer gives their key to another person - the contractual and social layers help with that.&lt;br&gt;
Cloning is when the installer and a valid key travel together. That is where the hard limit appears: if a real installer plus a real key spreads, an offline application cannot tell the new user from the owner. I say that plainly, because pretending otherwise is how DRM theater starts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four layers of friction
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cryptographic.&lt;/strong&gt; Each purchase gets its own signed key. There is no master key. The buyer's name from the payment record is embedded in the signed payload; changing it invalidates the signature. The email stays optional metadata, because the app never requires it. The key is scoped to the major version: a v1 key opens v1.x forever and simply doesn't grant v2. A leaked key identifies one purchase rather than compromising the product, and its value depreciates when v2 ships. For the honest customer, friction is zero: paste the key on any machine you own.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contractual.&lt;/strong&gt; The license says one person, the machines they own and control. A desktop and a laptop are fine. Passing the key around is not. A contract, not a checkpoint. The application doesn't need to phone home to enforce it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Economic.&lt;/strong&gt; The free tier removes the biggest reason people&lt;br&gt;
pirate small software: "I just want to try it." Start is free to try - up to 5 clients, 5 projects a month, unlimited invoices. No&lt;br&gt;
account, no card, same encryption, same offline database. And the&lt;br&gt;
paid version is $49 once. For a freelancer billing $50 an hour,&lt;br&gt;
fifteen minutes hunting for a crack already costs more than the&lt;br&gt;
software. There is also a hardship path: if someone genuinely cannot pay, they write to me. That's a personal decision, not a policy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Social.&lt;/strong&gt; The app shows "Licensed to: your name" in Help.&lt;br&gt;
Passing an abstract key is easy; passing a key with your own name&lt;br&gt;
signed into it is a different social operation. And transparency&lt;br&gt;
works as soft enforcement: the people who care about the no-DRM&lt;br&gt;
promise are probably not the people I'm trying to stop in the first place.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The snake oil I refused
&lt;/h2&gt;

&lt;p&gt;Hardware binding was on my first shortlist. Then I pictured the&lt;br&gt;
support email: "I wiped my disk and now your app thinks I'm a&lt;br&gt;
pirate." I would be my own first support ticket, while a determined pirate just removes the check. I killed it that afternoon.&lt;/p&gt;

&lt;p&gt;An offline lease - "the key remains valid for 90 days offline" -&lt;br&gt;
would effectively turn my perpetual license into a subscription, and it still clones with the disk.&lt;/p&gt;

&lt;p&gt;An activation counter without a server is a local variable. Whoever clones the state clones the count. Without an authority outside the copied state, the counter isn't enforcement. It's theater.&lt;/p&gt;

&lt;p&gt;Obfuscation and anti-tamper raise the cost of cracking for hours and add antivirus false positives and VM problems for years. For a solo developer, the support bill exceeds the benefit.&lt;/p&gt;

&lt;p&gt;Every one of these buys a little piracy resistance and charges it to the honest user. Some of them are reasonable choices for other&lt;br&gt;
products. For my constraints, all four failed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took from the products I studied
&lt;/h2&gt;

&lt;p&gt;Sublime Text gave me the closest precedent: a per-user license&lt;br&gt;
entered offline, no connectivity prerequisite, an honor system that has survived for years. BBEdit showed me that a version boundary can be explicit without pretending an upgrade is the same entitlement - perpetual license, paid major upgrades, usable free mode. Affinity showed that one-time, version-scoped ownership can work at scale, and that I don't want the account machinery they use to run it.&lt;br&gt;
Plasticity is my opposite example: once you introduce seat&lt;br&gt;
management, you're back to managing activation state - the thing&lt;br&gt;
ownership promises to abolish.&lt;/p&gt;

&lt;p&gt;None of them satisfies all five of my constraints. That's fine. The combination I ended up with - perpetual, version-scoped, locally verified, zero activation state, zero account, zero telemetry - is deliberately unusual.&lt;/p&gt;

&lt;h2&gt;
  
  
  The calculation
&lt;/h2&gt;

&lt;p&gt;I kept coming back to one conclusion: if I make piracy harder by&lt;br&gt;
adding friction, my honest customers are the ones who pay for it.&lt;br&gt;
Piracy exists; I'm not pretending otherwise. I just won't make every honest customer pay in friction to stop a small number of casual pirates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack I shipped
&lt;/h2&gt;

&lt;p&gt;Unique per-order signed tokens with the buyer's name and the major version in the payload, verified locally. A license that reads like a contract. The free Start tier as the legal alternative to a leaked key. "Licensed to: your name" in Help. No activation server, no revocation server, no telemetry.&lt;/p&gt;

&lt;p&gt;Five layers - and after that weekend, no sixth. I'll admit I kept&lt;br&gt;
looking for one more technical trick, some way to make a copied key less useful without a server. I spent more time on that search than I probably should have. There wasn't one.&lt;/p&gt;

&lt;p&gt;And one principle above the stack: a valid license should never&lt;br&gt;
depend on the continued existence of the company that issued it.&lt;br&gt;
Servers vanish, founders vanish; the copy you bought keeps working. That's not a feature - that's the product.&lt;/p&gt;




&lt;p&gt;If you ship offline software, where do you draw the line between&lt;br&gt;
protection and punishment - and what did I miss? I'd especially like to hear from people who tried hardware binding or offline production: what actually happened?&lt;/p&gt;

</description>
      <category>security</category>
      <category>drm</category>
      <category>privacy</category>
      <category>licensing</category>
    </item>
    <item>
      <title>Why I Chose SQLite Over PostgreSQL</title>
      <dc:creator>Vlad (Volodymyr Shiyan)</dc:creator>
      <pubDate>Mon, 24 Aug 2026 12:47:16 +0000</pubDate>
      <link>https://dev.to/vladshiyan/why-i-chose-sqlite-over-postgresql-26d1</link>
      <guid>https://dev.to/vladshiyan/why-i-chose-sqlite-over-postgresql-26d1</guid>
      <description>&lt;p&gt;Why I Chose SQLite Over PostgreSQL&lt;/p&gt;

&lt;p&gt;I chose SQLite over PostgreSQL because LockMargin is a desktop app that runs on the user's machine — not on a server. SQLite is embedded, zero-config, single-file, and requires no administration. PostgreSQL is a server database. For a freelancer who just wants to send an invoice, asking them to install PostgreSQL isn't a product. It's a sysadmin job.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision Point
&lt;/h2&gt;

&lt;p&gt;December 2025. I had the basic app working — create a client, generate an invoice, export to PDF. But I needed a database. Two options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; — embedded, single-file, zero-config&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; — server-based, multi-user, enterprise-grade&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'd spent 20 years building systems with PostgreSQL. I knew it. I loved it. But I chose SQLite. Here's why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Conversation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; I was leaning toward PostgreSQL. It's what I know. It's what I've used for factories, retail chains, service companies. It handles concurrency, transactions, complex queries. Why would I downgrade to SQLite?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; Because you're not building a factory system anymore. You're building a desktop app for one person. PostgreSQL is a server. Where's the server going to run?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; On the user's machine?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; Then you're asking freelancers to install PostgreSQL, configure it, manage backups, handle updates. That's not a product. That's a sysadmin job. I wouldn't install it myself, and I'm a backend engineer. Imagine an accountant from Zhytomyr who last saw a command line in 2009.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; Fair point. But SQLite — isn't it just for prototypes?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; No. SQLite is in every phone, every browser, every operating system. It's the most deployed database in the world. Apple uses it. Google uses it. Every Android phone has dozens of SQLite databases. It's not a toy. It's a tool. I lost three days in 2019 trying to set up PostgreSQL replication for a startup that shut down a month later. SQLite would have saved those days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; What about concurrency? Multiple users?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; Your app has one user. The freelancer. They're not sharing the database with 50 colleagues. SQLite handles single-user workloads perfectly. For multi-user, you'd need a server — which brings us back to PostgreSQL. But you don't want a server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; Right. Offline-first. No cloud. No server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; Exactly. SQLite is the database for offline-first apps. I'd say — for people who are tired of Docker Compose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Technical Comparison
&lt;/h2&gt;

&lt;p&gt;Let's get specific. Here's how SQLite and PostgreSQL compare for LockMargin's use case:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;SQLite&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Installation&lt;/td&gt;
&lt;td&gt;Zero (embedded)&lt;/td&gt;
&lt;td&gt;Required (server)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configuration&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Complex (pg_hba.conf, postgresql.conf)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Administration&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;DBA needed for production&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;Single file (.db)&lt;/td&gt;
&lt;td&gt;Multiple files, tablespaces&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup&lt;/td&gt;
&lt;td&gt;Copy the file&lt;/td&gt;
&lt;td&gt;pg_dump, WAL archiving&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Concurrency&lt;/td&gt;
&lt;td&gt;Single-writer, multi-reader&lt;/td&gt;
&lt;td&gt;Multi-writer, MVCC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Limited to one machine&lt;/td&gt;
&lt;td&gt;Unlimited (clustering, replication)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0 (self-hosted) or $5-50/month (managed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance (single-user)&lt;/td&gt;
&lt;td&gt;Faster (no network)&lt;/td&gt;
&lt;td&gt;Slower (network overhead)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance (multi-user)&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Offline support&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;Requires server connection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data portability&lt;/td&gt;
&lt;td&gt;Copy the file&lt;/td&gt;
&lt;td&gt;Export/import required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For LockMargin, SQLite wins on every dimension that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benchmarks
&lt;/h2&gt;

&lt;p&gt;I ran some tests. Here are the results for typical invoicing workloads:&lt;/p&gt;

&lt;h3&gt;
  
  
  Test Setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardware:&lt;/strong&gt; M2 MacBook Pro, 16GB RAM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database:&lt;/strong&gt; 1,000 invoices, 500 clients, 200 recurring invoices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operations:&lt;/strong&gt; SELECT, INSERT, UPDATE, complex JOINs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;SQLite&lt;/th&gt;
&lt;th&gt;PostgreSQL&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple SELECT (1 row)&lt;/td&gt;
&lt;td&gt;~0.3ms&lt;/td&gt;
&lt;td&gt;~1.2ms&lt;/td&gt;
&lt;td&gt;SQLite (~4x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex JOIN (5 tables)&lt;/td&gt;
&lt;td&gt;~2.1ms&lt;/td&gt;
&lt;td&gt;~3.8ms&lt;/td&gt;
&lt;td&gt;SQLite (~1.8x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INSERT (1 row)&lt;/td&gt;
&lt;td&gt;~0.5ms&lt;/td&gt;
&lt;td&gt;~2.1ms&lt;/td&gt;
&lt;td&gt;SQLite (~4x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UPDATE (1 row)&lt;/td&gt;
&lt;td&gt;~0.4ms&lt;/td&gt;
&lt;td&gt;~1.9ms&lt;/td&gt;
&lt;td&gt;SQLite (~4.7x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backup (full database)&lt;/td&gt;
&lt;td&gt;~5ms (copy file)&lt;/td&gt;
&lt;td&gt;~2.3s (pg_dump)&lt;/td&gt;
&lt;td&gt;SQLite (~460x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restore&lt;/td&gt;
&lt;td&gt;~5ms (copy file)&lt;/td&gt;
&lt;td&gt;~1.8s (psql)&lt;/td&gt;
&lt;td&gt;SQLite (~360x faster)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why SQLite is faster:&lt;/strong&gt; No network overhead. No server process. No connection pooling. The database is in the same process as the app. I checked three times because I didn't believe it. The third time I just used a stopwatch — copying the file in Finder took less time than opening a terminal for pg_dump.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why PostgreSQL is slower:&lt;/strong&gt; Every query goes through a socket, even on localhost. Connection setup takes time. MVCC adds overhead. It's like calling your neighbor through long-distance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trade-offs I Accepted
&lt;/h2&gt;

&lt;p&gt;Choosing SQLite means accepting some limitations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Trade-off 1: Single-writer concurrency
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Only one process can write to the database at a time.&lt;br&gt;
&lt;strong&gt;Reality:&lt;/strong&gt; LockMargin is a single-user app. The freelancer is the only writer. This is not a limitation — it's the correct model. I once tried opening the database from two windows simultaneously. Got an error. Thought: "Why would I need two windows?" Closed the second one. Problem gone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trade-off 2: No built-in replication
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Can't replicate the database to another server.&lt;br&gt;
&lt;strong&gt;Reality:&lt;/strong&gt; Backup is a file copy. Sync is a file copy. Replication isn't needed. I copy lockmargin.db to a USB stick once a week. That's my "replication." Been doing it since 2012, when I saved tax returns the same way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trade-off 3: Limited data types
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; No JSONB, no arrays, no custom types.&lt;br&gt;
&lt;strong&gt;Reality:&lt;/strong&gt; Invoicing data is relational. Clients, invoices, line items, payments. SQLite's type system is sufficient. I spent three days wondering if I needed JSONB for settings. Then I just made a separate table. Works fine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trade-off 4: No stored procedures
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Can't write complex logic in the database.&lt;br&gt;
&lt;strong&gt;Reality:&lt;/strong&gt; Business logic belongs in the app, not the database. This is a feature, not a bug. I've seen what happens when logic is smeared between SQL and code. Don't want to repeat that.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration Story (What If We Switched?)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; What if we needed to switch to PostgreSQL later? Could we migrate?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; Yes. SQLite to PostgreSQL migration is straightforward. The SQL is 95% compatible. The main differences: data types (SQLite is flexible, PostgreSQL is strict), some functions (date handling, string operations), concurrency model (WAL mode vs MVCC). I did one myself in 2021. The hardest part was explaining to the client why "just migrate" took a week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; How long would migration take?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; For LockMargin's schema? Maybe 2-3 days. Most of the work is testing, not rewriting. Or 2-3 hours if you're Vlad and do everything at night, then break production and fix it until morning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vlad:&lt;/strong&gt; So we're not locked in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jon:&lt;/strong&gt; No. SQLite is a starting point, not a prison. If you outgrow it, you can migrate. But for 99% of freelance apps, you won't outgrow it. I know. I counted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Reason
&lt;/h2&gt;

&lt;p&gt;Here's the honest truth: I chose SQLite because I didn't want to explain to a freelancer why they need to install PostgreSQL.&lt;/p&gt;

&lt;p&gt;Imagine the onboarding:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download LockMargin ✓&lt;/li&gt;
&lt;li&gt;Install PostgreSQL ✗&lt;/li&gt;
&lt;li&gt;Configure pg_hba.conf ✗&lt;/li&gt;
&lt;li&gt;Create a database ✗&lt;/li&gt;
&lt;li&gt;Set up backups ✗&lt;/li&gt;
&lt;li&gt;Handle updates ✗&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's not a product. That's a barrier to entry. I'd close the tab at step two.&lt;/p&gt;

&lt;p&gt;With SQLite:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download LockMargin ✓&lt;/li&gt;
&lt;li&gt;Open it ✓&lt;/li&gt;
&lt;li&gt;Your data is in a single file on your desktop ✓&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's a product. I opened lockmargin.db in DB Browser to check. A file. 2.4 megabytes. Everything I created in a month. Copied to a flash drive in 3 seconds. That's my backup strategy.&lt;/p&gt;

&lt;h2&gt;
  
  
  When PostgreSQL Is the Right Choice
&lt;/h2&gt;

&lt;p&gt;I'm not saying SQLite is always better. PostgreSQL is the right choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple users&lt;/strong&gt; need concurrent access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complex queries&lt;/strong&gt; with JSONB, full-text search, geospatial data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt; with replication and failover&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Large datasets&lt;/strong&gt; (terabytes, billions of rows)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise requirements&lt;/strong&gt; (audit logs, row-level security)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those use cases, PostgreSQL is unbeatable. But for a freelancer managing their own invoices? SQLite is the correct tool. I spent 20 years proving the opposite to clients. Now I'm proving it to myself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lesson
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Choose the database that matches your architecture, not the one you know best.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I knew PostgreSQL. I loved PostgreSQL. But PostgreSQL is a server database, and LockMargin is a desktop app. The architecture demanded SQLite.&lt;/p&gt;

&lt;p&gt;If you're building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A web app with multiple users&lt;/strong&gt; &amp;gt; PostgreSQL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A mobile app&lt;/strong&gt; &amp;gt; SQLite (or Realm)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A desktop app&lt;/strong&gt; &amp;gt; SQLite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An offline-first app&lt;/strong&gt; &amp;gt; SQLite&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A data warehouse&lt;/strong&gt; &amp;gt; PostgreSQL (or ClickHouse)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Match the tool to the job. I spent a week convincing myself PostgreSQL "would work too." Spent two more days on a Docker container. Then deleted everything and ran &lt;code&gt;cargo add rusqlite&lt;/code&gt;. Works.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;This is post #2 in the Building LockMargin series. Next up: the first time I dogfooded my own product, and what broke. Spoiler: I broke PDF export at 2 AM before a deadline. But that's another story.&lt;/p&gt;

&lt;p&gt;Follow the series at &lt;a href="https://lockmargin.com/blog-archive.html" rel="noopener noreferrer"&gt;Building LockMargin&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;p&gt;Is SQLite production-ready?&lt;/p&gt;

&lt;p&gt;Yes. SQLite is used by Apple, Google, Microsoft, and every major browser. It's the most deployed database in the world. It's not just production-ready — it's production-proven. I don't trust "proven" in marketing, but here — facts. Billions of devices.&lt;/p&gt;

&lt;p&gt;Can SQLite handle large datasets?&lt;/p&gt;

&lt;p&gt;SQLite can handle databases up to 281 TB. For invoicing, you'll never hit that limit. Most freelancers have thousands of invoices, not millions. I checked: my database after 4 months is 2.4 MB. After 10 years — maybe 60 MB. Smaller than one phone photo.&lt;/p&gt;

&lt;p&gt;What about data corruption?&lt;/p&gt;

&lt;p&gt;SQLite uses WAL (Write-Ahead Logging) mode by default, which prevents corruption even if the app crashes mid-write. I've never lost data to corruption in 6 months of daily use. I once dropped my laptop. The database was fine. The laptop — cracked. Priorities.&lt;/p&gt;

&lt;p&gt;Can I use SQLite with Rust?&lt;/p&gt;

&lt;p&gt;Yes. The &lt;code&gt;rusqlite&lt;/code&gt; crate is excellent. It's safe, fast, and well-maintained. LockMargin uses rusqlite for all database operations. I tried sqlx. Then Diesel. Went back to rusqlite. Just works.&lt;/p&gt;

&lt;p&gt;What if I need to sync across devices?&lt;/p&gt;

&lt;p&gt;SQLite doesn't have built-in sync. For LockMargin, sync is a file copy (USB, cloud storage, etc.). If you need real-time sync, you'd need a server — which defeats the offline-first purpose. I copy the file. Not perfect. But works. Like everything else in this post.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;P.S. — Jon agreed to stay anonymous. But he's real. We had coffee at a cafe in Berlin in 2019. He said then: "All scaling problems are solved by not scaling." I didn't understand then. I did in December.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;SQLite isn't a compromise. It's the correct choice for offline-first desktop apps.&lt;/p&gt;

&lt;p&gt;PostgreSQL is a server database. It's powerful, flexible, and enterprise-grade. But it requires a server, administration, and maintenance. For a freelancer who just wants to send invoices, that's overkill.&lt;/p&gt;

&lt;p&gt;SQLite is embedded, zero-config, single-file, and fast. It's the database that gets out of your way and lets you build your product.&lt;/p&gt;

&lt;p&gt;I chose SQLite because I wanted to build a tool, not a sysadmin job. And six months later, I'm glad I did.&lt;/p&gt;




&lt;p&gt;I build LockMargin - a local Financial OS for freelancers. No cloud, no subscription, no account. $49 once.&lt;br&gt;
Canonical: &lt;a href="https://lockmargin.com/blog/why-i-chose-sqlite-over-postgresql.html" rel="noopener noreferrer"&gt;https://lockmargin.com/blog/why-i-chose-sqlite-over-postgresql.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>sql</category>
      <category>privacy</category>
      <category>localfirst</category>
    </item>
  </channel>
</rss>
