31 ms·
Engineers do not get to make startup mistakes when they build ledgers
- Uptrenda 2y agoThe blockchain industry is basically founded on incompetence. If you go back to early Silk Road and Mtgox you can see some shocking things. Like the founders were posting questions on Stackoverflow about database basics. They then ended up building systems with race conditions (withdrawal code for both systems.) See, if you're an engineer (from a web background) you might think that using a regular backend language with a relational DB would be fine. But this service is typically optimized for concurrency. That might sound amazing. But what you really want is a simple queue. This ensures everything is applied in order and makes it impossible to accidentally have transactions execute on stale state. Plus, a queue can be executed amazingly fast -- we're talking Nasdaq scales. If you use a standard DB you'll end up doing many horrible broken hacks to simulate what would be trivial engineering had you used the right design from the start. You've got other things to worry about, too. Financial code needs to use integer math for everything. Floating point and 'decimals' lead to unexpected results. The biggest complexity with running large-scale blockchain services is having to protect 'hot wallets.' Whenever an exchange or payment system is hacked the target is always the funds that sit on the server. When the industry began there were still many ways to protect the security of these hot wallets. The trouble is: it required effort to implement and these protocols weren't widely known. So you would get drive-by exchanges that handled millions of dollars with private keys sitting on servers ready to be stolen... Today there are many improvements for security. New cryptographic constructs like threshold ECDSA, hardware wallets, hardware key management (like enclaves), smart contract systems (decentralized secret sharing... and even multi-sig can go a long way), and designs that are made to be decentralized that remove the need for a centralized deposit system (still needs some level of centralization when trading to a stable coin but its better than nothing.) I would say the era where people 'build' ledgers though is kind of over. To me it appears that we're organizing around a super-node structure where all the large 'apps' handle their own changes off-chain (or alternatively based on regular trust.) The bottom layer will still support payments but it will be used less often. With more transaction activity happening on layers above. I think its still important to scale the chain and make it as secure as possible. Bitcoin has a unique focus here on security above everything else. Making it ideal for long-term hedges. For every day stuff I can't think of any chains that have more credible R & D than Ethereum. They seem to even have been doing research on the P2P layer now which traditionally no one has cared about.
- thaumasiotes 2y ago> Financial code needs to use integer math for everything. Floating point and 'decimals' lead to unexpected results. Decimals are integers. There's no difference between integer math and decimal math, only in the meaning of the bit pattern afterwards.
- lmm 2y ago> Decimals are integers No, most decimal types are decimal floating-point. (So, sure, technically redundant, but a lot of people say "floating point" to mean IEEE 754 specifically, even if that's technically incorrect).
- x3n0ph3n3 2y agonit: double entry accounting only goes back to the 13th century, not thousands of years.
- Aeolun 2y agoNo tests either? If you lose track of enough money every transaction that you can make an example of 'Every $5 purchased resulted in $4.98 in the transaction log' I think your problem is far, far bigger than not having double entry bookkeeping. Who builds a financial system like that an considers it normal? The compensation is one thing, but you'd flee a service like that with all possible haste.
- hotsauceror 2y agoThese guys. They said it themselves. “We could have built it right, but we didn’t.” They chose not to. It was not an accident. They made jokes about “dancing cents”. They did these things because there would never be meaningful consequences for doing them, and they knew it. They move fast, they broke things - money things - and they laughed about it. And now they’re lecturing people as if having willfully made these decisions gives them both moral and technical authority. This is magnificently pompous, startup VC culture nonsense.
- fallingknife 2y agoSounds like they refunded anything that went wrong so it's not really as bad as you make it sound.
- Retric 2y agoRefunds limit damages in a lawsuit, but don’t prevent legal issues. Especially important when explicitly saying you’ve done these things.
- rsanek 2y agocritically, only when customers reached out. which means tons of people that weren't eagle eyed got defrauded.
- kelnos 2y agoNo, they refunded when a customer complained. Any customer that didn't notice or didn't complain didn't get what was rightfully theirs. That should be criminal, if it isn't.
- blibble 2y agois there no individual accountability regime in the US? in the UK, as an engineer, if I'd built this I would expect the regulator to come after me personally for not ensuring the system had adequate controls to protect clients money/investments with a potentially unlimited fine + prison time
- HPsquared 2y agoDepends if the particular activity is regulated or not.
- blibble 2y agoa stock trading platform, as described in the article?
- hluska 2y agoIn North America, “engineer” doesn’t necessarily mean a software engineer with a professional certification. Software developers have taken to calling themselves engineers. Whether engineering professional bodies should start going after people for this or not is a different topic. But it’s entirely possible for someone who calls themselves an engineer to not actually be a certified engineer. So the activity wouldn’t be regulated because the person isn’t part of a professional body that regulates members. In that case, lack of competence would be a civil issue unless it resulted in something criminal.
- AlotOfReading 2y agoThere isn't even a way to get certified as a professional engineer for software in the US.
- blibble 2y agoit's what you're doing (your "function") that's regulated not your job title, or piece of paper that you have that says you're X, Y or Z
- fendy3002 2y agoIt's a suicide to build a finance system or similar without double entry ledger. Worse, I've worked at where the transaction reference id from vendor is not recorded, it's lost so the past data cannot be reconciled!
- simonvc 2y agoCool post, wish it existed 2 years ago when we started building Pave Bank, or 10 years ago when we started building Monzo. If you're starting a bank or need a ledger these days (and aren't using a core banking provider that has one), then i usually recommend Tiger Beetle.
- lmm 2y agoOK but apparently they did get to make the startup mistakes? They built the quick thing that worked well enough, got some customer traction, and then when they had bugs they were able to rework it and continue. Frankly I'm not even convinced that double-entry is the sole right answer in this space. There are things you need to be able to represent, but the original reasons for doing double-entry (making errors when subtracting figures) no longer apply. (I've worked at investment banks and fintech startups)
- NikolaNovak 2y agoHmm, can you elaborate on the original reasons for double entry and them not applying any.kre? I'm not in that space and double entry always seemed an extremely weird, arbitrary requirement / paradigm. Thanks!
- XorNot 2y agoThe main point of double-entry account keeping is the notion that money never vanishes, it's always tracked as going somewhere. I think this tends to get misrepresented by people trying to literally keep two entries like we were working with pen and paper book-keeping though. Because if I have a simple list of transactions, I can easily use a SQL query to recreate a view of double-entry book-keeping. It's perfectly fine to just record the amount of money, and two entity names in a table. Coz the whole point of the system is that you can explain where the money went at any given time, referenced against something which should be independently auditable: i.e. a vendor receipt which in turn says "there's a physical item of X we gave you". The "double entry" system's actual merit is when there's multiple people keeping the books. i.e. if you're in a business and your department is spending money on goods, then when you're doing that those transactions should be getting reflected in the shipping departments books (owned by a different person) and maybe your accounting department or the like. The point is that there have to be actual independent people involved since it makes fraud and mistakes hard - if you say you bought a bunch of stuff, but no one else in the business received it or the money to pay for it, then hey, you now need to explain where the money actually is (i.e. not in your pocket).
- theendisney 2y agoIm sure there is a point in the article but ive never seen a dancing cent nor can i imagine one. My numbers are all strings "5" is "5" forever. If one somehow ends up storing it as 4.99 why would the other entry be correct?
- that_guy_iain 2y agoYour second sentence tells us your first sentence was a lie. You can clearly imagine one which is why you specified which data type you use for money. You know a floating point issue is an issue. Now let's say your price is "0.00023" per unit and someone uses "213.34" units. Can you imagine it now?
- XorNot 2y agoThis is more a problem with ill-specified contracts though. It was a constant source of annoyance when I was sole-trading for a bit, because what happened was something like this: I'd be quoted a day-rate. That was what I was actually going to get paid, one day. But then I'd be told to bill it as an hourly rate. And then actually to bill it as 7.5 hours. But I wasn't told what the hourly was - the hourly was whatever my day rate was, divided by 7.5. So this led to the problem that it produced an irrational number as a result. Technically this should've been fine...except no one I dealt with knew or cared about this concept - they all used Excel. So if I rounded the irrational to nearest upper cent (since that's the smallest unit which could be paid) they complained it didn't add up. If I added a "correction item" to track summing up partial cents, they complained it wasn't part of the hourly. In the end I just send python decimal.Decimal to maximum precision, flowed through invoices with like 8 digits of precision on the hourly rate, and this seemed to make Excel happy enough. Of course it was completely useless for tracking purposes - i.e. no one would ever be able to pay or unpay 0.666666666667 cents. Because what's not in employment contracts that really should be? Any discussion on how numbers are to be rounded in the event of uneven division. You just get to sort of guess what accounting may or may not be doing. In my case of course it didn't matter - no one was ever going to hold me to anything other the day rate, just for some reason they wanted to input tiny fractions of a cent which they actually couldn't track. And it's not an idle problem either: i.e. in the case of rounding when it comes to wages, should it be against the employee? It's fractions of a cent in practice, but we're not going to define it at all?
- amluto 2y agoDoes anyone have a good explanation for why a ledger database should care about credits and debits and normal balances? This has always seemed more natural to me as a front-end / presentation layer concept. Your ledger entries always sum to zero for each transaction, your income account has a negative balance, and you display it in a sensible manner. I’m also surprised that this whole article starts by discussing stock trading but has no mention of how to represent stock trades. I assume they are “Sagas” consisting of money moving from the customer to the clearinghouse (or prime broker or PFOF provider or whatever) and shares moving from that provider to the account at which the shares are held. And maybe other associated entries representing fees? It seems to me that this is multi-entry accounting, which is quite common, and that entries don’t actually come in pairs as the article would like us to think.
- jfengel 2y agoI've never understood that either. As a computer guy it always struck me as a redundancy -- the kind of redundancy where one thing will always eventually be wrong. I assumed it has to do with the fact that it was invented for bookkeeping by hand. Accountants assure me that it's even more important with computers, but I've never managed to figure out how that works
- fallingknife 2y agoNeither have I. It always seems like a massive cargo culting. Human accountants are liable to make very different kinds of mistakes than computers.
- dboreham 2y agoI've been doing this so long that I've finally realized that if someone can't explain why something is the way it is, that means it's wrong, or at least some arbitrary choice among several equally good alternatives.
- dagenix 2y agohttps://en.wikipedia.org/wiki/G._K._Chesterton#Chesterton's_fence https://en.wikipedia.org/wiki/G._K._Chesterton#Chesterton's_...
- gregw2 2y agoPardon me an old story... I never built a double entry accounting system but decades ago I did build a billing system for a internet/telcom startup that grew to a modest 8 figures revenue. By accident and not knowing any better as a young dev, I ended up building the billing logic from day one, and for better and worse building it in two places in the system (on a consumer-facing billing webpage, and on a separate backed process that generated invoices and charged credit cards.) It turned out to be remarkably hard to keep them in sync. We were constantly iterating trying to get traction as we burned down our capital, releasing new products and services, new ways of discounting and pricing (per use, per month, first X free, etc), features like masterpayer/subaccounts for corporate accounts, user-assignable cost centers, tax allocation to those cost centers with penny allocation, etc such that new wrinkles and corner cases would keep popping up causing the numbers on my two screens/methods not to match. Being personally responsible for the billing, I would go over all the invoices by hand for a couple days each month to insure they matched before we charged the credit cards and mailed out printed invoices as a final check to prevent mistakes. There was always/often some new problem I'd find affecting one or a small handful of customers which I would then fix the code before we billed. I never felt good letting go and not doublechecking everything by hand. I thought about refactoring the billing logic to occur in one place to eliminate these mismatches and my manual crosschecking, but after a lot of thought I realized I wasn't comfortable with a single codebase and liked having two codebases as it helped me catch my own errors. I then just made it easier and easier to run automate and crosschecks between the two. The billing code was a little too gnarly to be proud of, but I was very proud of the outcome in how accurate our billing was, the lack of complaints and many near misses we avoided for many years. I do feel twinges of guilt for the complexity I left my successors but I still don't really regret it. After that experience, the motivation for double entry bookkeeping has always made a lot of sense to me. I had sort of reinvented it in my own hacky way with double logic billing code to prevent my mistakes from causing problems for my customers...
- icapybara 2y agoNo offense but this sounds like a nightmare. It also sounds like you did a fantastic job achieving accuracy despite the complexity of the system. That’s something to be proud of.
- cynusx 2y agoAccounting systems are super hard when you do them wrong and kind of trivial when you do it right. There is no in-between. Martin fowler wrote quite a bit on the subject and it's a good match for event-sourcing.
- yapyap 2y ago> It’s just that…it goes without saying that fintech companies should know better haha, if only. move fast, break everything if it gives profit
- pyrolistical 2y agoBtw for those wondering what to do instead is to simply use https://tigerbeetle.com/ https://tigerbeetle.com/
- 2mol 2y agoI mean, tigerbeetle looks extremely cool (I've watched the project develop since its inception), and I trust them to be rock-solid. But saying "just use this project that is very new and unproven, written in a new and unproven programming language" is just pretty unserious. At least talk about pros, cons, risks, and tradeoffs.
- kiwicopple 2y ago>very new and unproven, written in a new and unproven programming language while i'd generally agree with this, in the case of TigerBeetle i think it's safe to trust their tech based on their test-suite/practices - one of the most impressive things I've seen in the past 5 years. they extend the testing practices of FoundationDB (now spun out into Antithesis[0]), going a layer deeper to test for data integrity when there is disk io corruption. check out from ~20:30 in this demo: https://youtu.be/sC1B3d9C_sI?feature=shared&t=1228/ https://youtu.be/sC1B3d9C_sI?feature=shared&t=1228/ [0] https://antithesis.com https://antithesis.com
- saaaaaam 2y agoThank you for posting this. I’m trying to get my head around how to build a fairly complex ledger system (for managing the cost schedules in large apartment buildings where everyone might pay a different proportion and groups of apartments contribute towards differing collections of costs) and you’ve just massively accelerated my thinking. And possibly given me an immediate solution. Have you used tigerbeetle in production?
- jes5199 2y agoI found this paragraph > Prerequisites: TigerBeetle makes use of certain fairly new technologies, such as io_uring or advanced CPU instructions for cryptography. As such, it requires a fairly modern kernel (≥ 5.6) and CPU. While at the moment only Linux is supported for production deployments, TigerBeetle also works on Windows and MacOS. wha— what? why?? they must be solving some kind of scaling problem that I have never seen
- jeffnappi 2y agoFeeling vindicated for the double entry transaction system we built at clearvoice.com for our two-sided marketplace, leveraging the fantastic DoubleEntry Ruby Gem from Envato.
- hn_throwaway_99 2y agoTell that to Synapse customers. Many millions of dollars are missing. Banks have to follow strict rules to account for where all the money goes. But the way fintechs work, they usually just have one or a couple underlying "FBO" accounts where all the pooled money is held, but then the fintech builds a ledger on top of this (and, as the article points out, to varying levels of engineering competence) to track each individual customer's balance within this big pool of money. In Synapse's case, their ledger said the total amount of all of their individual customer balances ended up being much more than the actual funds held in the underlying FBO accounts. Lots of folks are assuming fraud but I'm willing to put money that it was just a shitty, buggy ledger. FWIW, after seeing "how the sausage is made", I would never put money into a fintech depository account. Use a real bank. Fintechs also often put out the fake promise that deposits are FDIC insured, but this only protects you if the underlying bank goes belly up, not if the fintech loses track of your money. See https://www.forbes.com/sites/zennonkapron/2024/11/08/what-the-yotta-saga-reveals-about-fintech-shortcomings/ https://www.forbes.com/sites/zennonkapron/2024/11/08/what-th...
- mrfox321 2y agoAt a big co I worked at, the lack of consistency between trading systems caused money to (dis)appear (into)out of thin air. Prior to one of these hiccups, I hypothesized, given how shitty the codebase was, that they must be tracking this stuff poorly. This led to an argument with my boss, who assumed things magically worked. Days later, we received an email announcing an audit one one of these accounting discrepancies. JPMC proposed using crypto, internally, to consistently manage cash flow. Not sure if it went anywhere.
- hooverd 2y agoIt's all merkle trees under the hood. I feel like the crypto coin stuff has overshadowed the useful bits.
- trog 2y agoIs a Merkle tree needed or is good old basic double ledger accounting in a central database sufficient? If a key requirement is not a distributed ledger then it seems like a waste of time.
- bsder 2y agoLosing cents is because somebody didn't use Decimal for currency. And that's just flat out malfeasance--possibly even regulatory malfeasance. Double entry is irrelevant, here. I love the "use crypto" to fix the problem suggestion. LOL! It's kind of poignant since crypto has given me a fantastic club to beat executives over the head with whenever they want to do stupid handling of money. Since crypto has so many decimal places, you break dumbass floating point handling of money immediately and irretrievably for way more than just "a couple cents". Your CFO starts jumping up and down really excitedly about handling money properly when he has to worry about a rounding error forcing him to compensate a Bitcoin price jump/crash.
- phonon 2y agoIt could be rounding issues as well (roundings do not all cancel out), or having to divide an even amount unevenly (how do you pay $10 in three "equal" installments?) Even with infinite decimal precision there will be special handling involved.
- zitterbewegung 2y agoIf told people that I was using a database system where one and 100th of the data was missing after every 10 transactions would you seriously take my advice as an engineer blog post like these that seem to be calmly focused toward an advertisement of a person’s or a group’s promotion and that it’s just introducing concepts.
- namaria 2y agoWat
- fifilura 2y agoThe user name "zitterbewegung" sounds like a German. They build sentences like that. You have to think about a sentence like a stack and read it slowly and carefully and take note of the push and pop operations. Germans are like RPN where everyone else is a regular calculator.
- namaria 2y agoI'm afraid it's not just sentence structure that is the problem here: > one and 100th of the data was missing No idea what that means > an advertisement of a person’s or a group’s promotion What in god's name is an "advertisement of a group's promotion"?
- roelschroeven 2y agoI read that as "(an advertisement of a person) or (a group's promotion)".
- callmeal 2y ago>> one and 100th of the data was missing >No idea what that means 1/100th of a dollar is a cent - goes towards the "missing cents" glossed over by calling that "dancing cents" in the blog post.
- 2y ago
- mrkeen 2y agoI'm not sold on double entry here. If a new transaction enters the system now, I could follow the advice and record it as two sources of truth. Or I could just record it once. If I could turn a single transaction into two ledger entries today, I could do the same later if I needed to.
- cts1 2y agoThere's no redundancy. Imagine you have 2 buckets, you reach into bucket A and grab some cash and put it in bucket B. $x dollars leaving bucket A is entry part 1, $x dollars entering bucket B is entry part 2. That's all it is. I honestly don't understand what single entry is by comparison - it sounds like losing an essential attribute of the transaction.
- teaearlgraycold 2y agoSingle would be recording the two accounts, one being the source account and the other the destination, and a quantity.
- jes5199 2y agosingle entry is like a receipt at a store, is says what you owed and what you paid, but there’s no “other side” that is getting credited or debited the same amount
- mrkeen 2y ago"Two sources of truth" is an anti pattern in computing and isn't redundancy. Use replication or backups for that. You can't imagine simpler than what you described because it's single entry. Double-entry is twice as complicated, makes sense only to accountants and not to computing people. Your example of 1 transaction would be doubly-kept as some nonsense like BucketA revenue:$x CR cash:$x CR BucketB revenue:$x DB cash:$x DB
- jes5199 2y agono. single entry is when you track BucketA’s balance without regard to other buckets at all
- chris_wot 2y agoIt took me a while to realise what double-entry bookkeeping actually was, then one day it hit me: it's literally just the flow of money through a system. Understand that, and you understand the cornerstone of accountancy.
- intelVISA 2y agoif only accountancy 'learned' from OOP and just had one mutable balance for each account :)
- cromulent 2y ago> A double-entry system is an accounting method that tracks money at both its source and destination. Nope. Double entry bookkeeping means every transaction is recorded in (at least) two accounts.
- cromulent 2y agoTo illustrate the difference (hopefully I get this right): A transaction needs to balance, left vs right. For example, you receive a sales order for 1000€ of widgets, which cost you 600€. You ship them. You invoice for 1000€. No money moved (hopefully you do get paid at some point though). However, you need to do some bookkeeping. On the left side of the ledger (debits): Accounts receivable 1000€. Cost of goods sold 600€. On the right side of the ledger (credits): Revenue goes up by 1000€. Inventory goes down by 600€. These completely match. No money has moved, but the books are now up to date and balance. Any transaction that does not balance should be rejected.
- _1tem 2y agoWait, why can’t I just use a Postgres database with the Decimal type and call it a day?
- zie 2y agoYou need to keep state, so that when something goes wrong you can figure out that something went wrong. PG's rounding can be summed up as: we round to the nearest digit you specify, but how we get there is mostly undefined. Every bank and organization you do business with(especially if you cross-jurisdictions) will likely round pennies differently. PG and the decimal data type(which is actually the numeric data type) are only part of the solution, as they won't handle rounding pennies correctly for you, but they will store it, if you round properly yourself. PG also has a money data type, but it also doesn't let you specify the rounding rules, so you have to be careful. Also, money is tied to lc_monetary, which is handled outside of PG's control, so you have to be very careful with it, when moving data across PG instances, or you might be surprised. Also, it doesn't let you specify which currency this money is, which means you have to store that yourself, if you ever have more than one currency to care about. If you don't care about balancing to the penny with your external organizations(banks, CC processors, etc), you are 100% guaranteed to have a bad time eventually.
- dataflow 2y agoCould someone explain something fundamental to me about the need for double-entry accounting? Why can't your source of truth instead be proper SQL tables following these schemas (using Python tuple/list notation for convenience)? transactions: [ (txID, timestamp, [ (accountID, delta, otherInfo), ... ], reason), ... ] accounts: [ (accountID, routingNumber, accountNumber, ownerID), ... ] Crucially, notice that "accounts" don't track balances here, and so I'm asking: why would I need TWO entries per transaction, and why would I need to do my own tracking of the balance of every account, when I can just keep a single entry per transaction in a proper ACID database and then build any view I need on top (such as running balances) with a battle-tested projection mechanism (like a SQL View) so that I still track a single source of truth?
- pkd 2y agoSQL or not doesn't really matter. Double entry provides redundancy, and redundancy allows for auditing. It's like checksumming to detect errors.
- dataflow 2y agoI guess I'm asking: what would go wrong with the design in my comment, which makes transactions first-class and has a single entry for each one? What errors would double entry prevent that this doesn't?
- namaria 2y agoYou offered no design. Db schema has nothing to do with transaction guarantees.
- jes5199 2y agowhat you’ve sketched out already looks like a double-entry bookkeeping system, if you have the constraint that all of the deltas in your array on your transaction sum to zero (so money always _moves_ and is not created or destroyed) calling it “double” might be misleading - in the ledger systems I’ve worked on, a transaction that has only two entries - a single source and a single destination - is actually rare. In practice, a payment tends to have a source, the intended destination, a secondary destination for platform fees, possibly another destination for taxes. And much more complicated situations are possible - I currently work in medical billing where there are multiple virtual internal accounts involved in each transaction for different kinds of revenue (including, for example, money we billed for but don’t expect will actually get paid) so a transaction becomes a bundle of a set of several debits or credits that happen simultaneously and sum to zero. if you have that, you have double-entry bookkeeping, even if you schema puts it all in one table
- cryptica 2y agoIt's just like it was with pen and paper... Everyone trusts what is written on the financial statement but when they come to withdraw the cash, all at once, suddenly everyone finds out that the gold isn't there. It's the same with computer systems. The charts show something, but until enough people decide to all withdraw their money or sell their stock at the same time, nobody has any idea that the money or asset simply isn't there or nobody knows just how frothy the valuation is. Social media and search algorithms are highly optimized to ensure that people don't sell or withdraw stuff at the same time. Modern media directs massive attention towards certain topics as a way to draw attention away from other topics which could collapse the economy. Also, imagine a bank has a serious bug which causes millions or billions of dollars to disappear every year or creates extra illegitimate dollars. Imagine they only discover this bug after a few years of operation... How likely is it that they will report it to an authority? They didn't notice it for years, why not pretend they didn't notice it for a few MORE years... The incentive to delay the reckoning is an extremely powerful one.
- superzamp 2y agoPrecisely. Designing a transactional system can be solved. Designed a transactional system that properly entangles the bits with the assets they represent is the hard part.
- jes5199 2y agoliterally every startup I’ve worked at has had busted accounting system that had to be painfully and expensively rewritten as a proper ledger. We should be teaching “Accounting for Programmers” as a required course in CS programs, or at least spreading memes about how money data must be append-only and immutable or you are being negligent in ways far more serious than most programming errors
- probably_wrong 2y agoThe Software Engineering department next door from my CS department had a mandatory course on accounting. I don't think CS needs accounting, but I did learn two skills that would have helped here: why one should never use floating point for money (which may not apply here, who knows), and how to stick to a formal specification. "Money is neither lost nor created" is the most trivial example one can think for an invariant. Relatedly, some months ago I asked how to correctly record food in a double-entry bookkeeping system [1] and it triggered a 1300-words, 8-levels-deep discussion. We should remember more often than accounting is a degree by itself. [1] https://news.ycombinator.com/item?id=39992107 https://news.ycombinator.com/item?id=39992107
- tonyhart7 2y agoI think because programmer find it confusing about translation of model in computer to real world Accounting predates computer by hundreds of years, there are better way to do certain thing of course but we must follow convention here because that's the norm and everyone understood
- jes5199 2y agocomputers evolved out of tabulating machines and tabulating machines were designed to make pen&paper accounting easier. These are our roots and we should appreciate them
- mrkeen 2y agoHaha, same. https://news.ycombinator.com/item?id=39994886 https://news.ycombinator.com/item?id=39994886 I kept digging and digging on a "sell some lemonade for $5" example, and ended up at: - $5 debit to cash (asset => debit means +5) - $5 credit to revenue (equity => credit means + 5) - $X debit to cost of goods sold (liability => debit means - X) - $X credit to inventory (asset => credits mean - X) A double-entry for the money, and a double-entry for the inventory, for a total of 4 entries. It's too complicated for me. I'd model it as a Sale{lemonade:1,price:$5} and be done with it. Nothing sums to zero and there's no "Equity + Income + Liabilities = Assets + Expenses" in my version. But this is HN, and I think a lot of people would call my way of doing things "double" because it has both the lemonade and the money in it. So when I say I'm not sold on doing actual double-entry [https://news.ycombinator.com/item?id=42270721 https://news.ycombinator.com/item?id=42270721] I get sweet down-votes.
- thecleaner 2y agoI guess the lesson here is to not bank with an a16z company. I have been using Wise for years. Very very happy.
- 2mol 2y agoGreat article. I have an observation to the "engineers should know this and do good engineering" though: I work for a payments company and there is a fundamental career problem with becoming the ledger ninja: It's not enough work, and it's eventually done! I've seen the following major phases of this work: 1) Build the ledger (correctly), and it will work well for a while. 2) Add convenience code for the callers, assist finance in doing reports/journaling, fix some minor bugs, take care of the operational bits (keep the database up). 3) Reach the scaling limits of your initial approach, but there are some obvious (not trivial) things to do: re-implement the transaction creation directly in the database (10x perf gain), maybe sharding, maybe putting old tx into colder storage, etc. This is spread out over a while, so I haven't seen it be a full-time job, even at real startup-level (+10% MoM) growth. Even if it was, that's one person, not a whole team. I understand engineers that instead are pulled towards projects where they are in higher demand. In another comment somebody said ledger systems are trivial when done right and super hard when done wrong - so if you did a good job it kinda looks like you just created 3 tables and some code. That seems thankless, and job searching as this type of specialist is harder than just being a generalist.
- scary-size 2y agoI suspect this is a "small company" problem which don't sell too many different things. A larger enterprise might have a platform for connecting businesses with businesses and businesses with customers. They might sell services (subscriptions) but also one-time purchases which require different forms of revenue recognition. Those might even be split up across different revenue streams. You end up building sub-ledgers for each one of them because the ERP can't handle the scale. Oh, and you're a public company so make sure everything is SOX compliant and easy to audit. Ah, and you operate on a global scale so do all those things in different currencies for different legal entities. There's a reason Stripe is as successful as it is. And then there's a world where a company outgrows Stripe. There are worse career choices ("prompt engineer" LOL) than financial engineering.
- fragmede 2y agoStripe isn't a bookkeeper/accountant. Something like http://Pilot.com http://Pilot.com is though. stripe on bookkeeping: https://stripe.com/guides/atlas/bookkeeping-and-accounting https://stripe.com/guides/atlas/bookkeeping-and-accounting
- nobodywillobsrv 2y agoSV Tech Bros roasting themselves on HN. Every engineer in London is laughing at this right now. Wow double entry! Ledgers are hard! Wow. So true.
- jasim 2y ago> Instead of using negative numbers, Accounts have normal balance: normal credit balance literally means that they are normal when its associated entries with type credit have a total amount that outweighs its associated entries with type debit. The reverse is true for normal debit balance. But that is an interpretation made by the viewer. A customer typically is an asset account, whose balances are in the debit column. But if we somehow owe them money because let's say they paid us an advance, then their balance should be in the credit column. The accounting system need not bother with what the "right" place for each account is. It is quite practical to have only a simple amount column rather than separate debit/credit columns in a database for journal entries. As long as we follow a consistent pattern in mapping user input (debit = positive, credit = negative) into the underlying tables, and the same when rendering accounting statements back, it would remain consistent and correct.
- fendy3002 2y ago> It is quite practical to have only a simple amount column rather than separate debit/credit columns in a database for journal entries. As long as we follow a consistent pattern in mapping user input (debit = positive, credit = negative) into the underlying tables, and the same when rendering accounting statements back, it would remain consistent and correct. Another benefit of Credit / Debit side on double-entry bookkeeping is you need to balance both side in a single transaction. Say if the user account 2003201 is in Credit and it got an addition of 1000 value, a same value need to be added on Debit side. If it's (1) a cash topup, then 1000 value need to be added to Cash account (let's say 1001001) on Debit side. Otherwise if it's a transfer (2) from another user account 203235, then the account need to be Debited 1000 value as well. It's Asset = Liabilities + Equity, while the left equation is Debit (which increase value when a Debit transaction happen, and the right equation is Credit, which increase when a Credit transaction happen. In (1) case, the cash account increase since it's on Debit account, while in (2) case, the user account decrease because it's a debit transaction on Credit account.
- jasim 2y agoWith negative/positive, the invariant would be sum(amount) = 0; with your approach, it would be sum(debit-credit)=0. Both are valid, it is just two ways of expressing the same thing. I think it is useful to think about double-entry book-keeping in two layers. One is the base primitive of the journal - where each transaction has a set of debits and credits to different accounts, which all total to 0. Then above that there is the chart of accounts, and how real-world transactions are modelled. For an engineer, to build the base primitive, we only need a simple schema for accounts and transactions. You can use either amount (+/-ve), or debit/credit for each line item. Then if you're building the application layer which creates entries, like your top-up example, then you also need to know how to _structure_ those entries. If you have a transfer between two customer accounts, then you debit the one who's receiving the money (because assets are marked on the debit side) and credit the other (because liabilities are on the credit side). If you receive payment, then cash is debited (due to assets), and the income account is credited (because income balances are on the credit side). However, all of this has nothing to do with how we structure the fundamental primitive of the journalling system. It is just a list of accounts, and then a list of transactions, where each transaction has a set of accounts that get either debited/credit, with the sum of the entire transaction coming to 0. That's it -- that constraint is all there is to double-entry book-keeping from a schema point.
- supermatt 2y agoThe payments industry is rife with nonsense like this. At a fintech startup I was working with, we built a "shadow ledger" because we couldn't trust a 3rd party PP to give us the correct information, which would otherwise allow double spending on accounts. We tried 3 different (major!) PPs - they ALL had similar flaws.
- afiodorov 2y agoBlockchains are examples worth learning from about how to build ledgers. Append-only transactions which start as pending and then eventually confirmed. Balances are cumsums of confirmed transactions.
- watt 2y agoI don't understand why the author chooses to bring up the mantra “make it work, make it right, make it fast“ in a negative light, perhaps he misunderstands where the "make it fast" comes in? to clarify: "make it right" is the second step, and until you make things work correctly ("right"), that's where the work stops, you have to make the system work soundly. the "make it fast", as in, optimize, comes in only after you have got it right, that all correctness and soundness issues are resolved perfectly. then you can start optimizing it (making it run fast). it has nothing to do with delivery speed. it has nothing to do with working quickly. it's about optimizing only as a last step. perhaps the author is lamenting the fact that it is possible for something to sort of "work", but to be so far from being "right" that you can't go back and make it right retroactively, that it has to be "right" from the inception, even before it starts barely working?
- deleted 2y ago[deleted]
- zaphodias 2y agoI think author chose the wrong mantra too! What happens in fast paced startups is that you ship what essentially is a MVP as soon as possible (i.e. you stop at the "make it work" step) because you need to build your customer base, finances, etc. A better mantra would've been Facebook's "move fast and break things". But, that only works if you can fix the things later. You wouldn't do it if you're building an aircraft for example.
- badcppdev 2y agoI think your last sentence is correct. I think author is saying that you can't make it work and THEN make it right with payment systems. This is my opinion as well and I've been involved in the audit of a fintech system where auditors had to download EVERYTHING into excel spreadsheets and make the numbers balance before they would sign off on the books. That took a lot of time and money I'm guessing made a difference of at least .1 unicorns in the liquidity even that took place 3 years later.
- jeremyjh 2y agoThey said the engineering team followed this mantra, which includes the phrase "make it right". But they didn't. They didn't even bother to find out what they didn't know about fintech before they started building a product. Given the context in which he used it, I think the misunderstanding you suggest in the first sentence is most likely. Immediately afterward he talks about the time pressure startups face.
- elzbardico 2y agoAn incredibly depressing thing in our profession is how we collectively lack memory. We routinely re-discover stuff that probably was already solved by a quiet lady writing a CICS transaction in a s-360 system in 1969. Yeah, dealing with money and especially others people money without double entry bookkeeping is a bad practice. But this particular problem is the consequence of the choice of using floating point binary math to deal with monetary quantities. Given the fact that most modern languages have very awkward support for arbitrary precision decimal numbers the most sensible way to deal with money usually boils down to store it as an integer.
- deleted 2y ago[deleted]
- BlueTemplar 2y agoI don't see how these are related (except of course for the errors in the second that could be caught by the first), and hopefully nobody in fintech is so ignorant/dumb to use floating point for money ? Or are we talking about random scammers as 'fintech' now rather than banks (the fintech of which might indeed be old enough to be still running on COBOL-like systems) ?
- morbicer 2y agoHot take: I blame the culture of obsession with CS topics, leetcode, tail recursion, dependent types etc and not enough focus on solid engineering and domain knowledge in areas encountered by 90% of real life jobs. Starts in the education and perpetrates via hiring, blogosphere and programmer celebrities.
- kdeldycke 2y ago> When I decided to write a post on ledgers, I already knew there were a few good resources out there to help me. One that's not referenced in this article and compile all of them is: https://github.com/kdeldycke/awesome-billing#readme https://github.com/kdeldycke/awesome-billing#readme
- zerop 2y agoBuilding fintech platforms are not easy, specially for large systems which not only require robustness, scale, but also traceability, daily reconciliations. We even had features to undo and redo (correct and replay) transactions from a time in history. I did not like finance much, but building a fintech system really teaches a lot, not only from technology perspective but from managing stakeholders, processes, compliance, dealing with all kinds of finance-specific issues. One should always work in fintech, at some point of time in career.
- bvrmn 2y agoI don't understand what the difference in modeling between: Entry(account, direction, non-negative amount), direction is debit or credit. vs Entry(account, signed amount), + is debit, - is credit (for example). It's a two way mapping and should be equivalent. Unless debit or credit amount could be negative. But as I understand it's a big NO-NO in accounting.
- tonyhart7 2y agoHey, great works I literally build the same system and ask for HN Ask but no one answer it and already using double entry and ledger based on some research and AI advice lol I implement all the check its mention in your page and quite satisfied using postgress constraint and trigger function to detect abnormality before bad row is inserted but the problem now is populate the database using fake data because how rigirous my constraint and rule are, I need to simulate real world use case and duplicate it on development machine but this are hard if you ever read this, can you give some advice please, because simply looping that function is not gonna work because constraint of double entry and ledger
- bobnamob 2y agoFor a glimpse at the _real_, human consequences of this kind of slipshod mentality toward money shuffling software see the Post Office scandal[1]. https://en.wikipedia.org/wiki/British_Post_Office_scandal https://en.wikipedia.org/wiki/British_Post_Office_scandal Anything that moves money should be treated with upmost seriousness and be aware of as many historical mistakes as possible.
- throw0101a 2y ago> https://en.wikipedia.org/wiki/British_Post_Office_scandal https://en.wikipedia.org/wiki/British_Post_Office_scandal The four-part miniseries with Toby Jones (mentioned above in §Media:Dramatisation) was really good and goes over things pretty well: * https://en.wikipedia.org/wiki/Mr_Bates_vs_The_Post_Office https://en.wikipedia.org/wiki/Mr_Bates_vs_The_Post_Office
- rkharsan64 2y agoMost of the comments here echo what the article is criticising. I can see countless threads of back-and-forth defending single-entry bookkeeping. Sure, single-entry bookkeeping might be easier and more normalized, but sometimes it is a good idea to just stick with the systems and abstractions that have been developed over centuries. Just use double-entry bookkeeping unless you definitely need something else. Sure, it might be icky for the programmer inside you, but I think you'll be thankful if you ever need to get actual accountants involved to sort out a mismatch. On a related note: does anybody know of any good resources for programmers in payments and adjacent fields? Something like an "Accounting for Programmers"?
- karanbhangui 2y agoThese articles might be a good starting point: https://martin.kleppmann.com/2011/03/07/accounting-for-computer-scientists.html https://martin.kleppmann.com/2011/03/07/accounting-for-compu... https://www.moderntreasury.com/journal/accounting-for-developers-part-i https://www.moderntreasury.com/journal/accounting-for-develo...
- fragmede 2y agoI consider that first link, Accounting for Computer Scientists, as the canonical guide for computer scientists as to wtf double entry accounting is and why it's the right way to do it.
- bobnamob 2y agoKleppmann's Designing Data Intensive Applications is also pure gold. Worth reading once a year imo
- inopinatus 2y agoI read an article from Modern Treasury that advocated for mutable pending transactions to vary entry amounts by replacing entries¹, which is just about the worst idea I ever heard in the design of a DE system, and their reasoning boiled down to: if you're running a settlement system but are too lazy to implement a clearinghouse layer separately, no worries, just violate the entire DE covenant instead. So I'd take anything they write with a pinch of salt. [1] https://www.moderntreasury.com/journal/how-to-scale-a-ledger-part-ii#discarding-entries https://www.moderntreasury.com/journal/how-to-scale-a-ledger...
- swyx 2y ago> And yet, I used to work for a startup that, on every transaction, simply lost track of a couple of cents. As if they fell from our pockets every time we pulled out our wallets. is this not the literal plot of Office Space? did you check for a Michael Bolton employee?
- adamcharnock 2y agoIf you're looking for a pre-built double entry accounting Postgresql schema that provides database-level integrity checks: https://github.com/adamcharnock/django-hordak https://github.com/adamcharnock/django-hordak I created and maintain this, along with a couple of others. It is built for Django (so great if you're using Django), but extracting the schema wouldn't be too hard. It also has MySQL support, but the integrity checks are more limited. (Side note: I'm a freelancer and available!)
- ndjdjddjsjj 2y agoI feel there is no excuse. Startups cut all sorts of corners but why? Get rich at other people's expense? The tech founder should know their shit prior to building it so that time and runway and deadlines are no excuse. Really if you are doing fintech you should have employment experience and understand all the operations well. Otherwise they are no better than say home builders who mismanage and go bankrupt. Or less geneously, they are conmen.
- tomgp 2y agoThis reinforces for me the importance of domain knowledge in engineering leadership. i.e. if you work for a finance company you need to have a decent understanding of finance in order to make the correct technical decisions and tradeoffs, same goes for journalism, same goes for commerce etc. etc. Successful organisations I've worked for have always included domain specific, non-technical, questions to tech team interviews whilst some of the most technically acomplished teams I've worked with have floundered through a lack of domain insight.
- collinmcnulty 2y agoI agree with your sentiment here, but I think it helps to think of those domain specific questions as technical questions, just from a different technical domain. Finance is technical, mechanical engineering is technical, even sports management and sociology have big technical components too. I think having an expansive view of what technical competence is breeds the humility necessary to work across domains.
- tomgp 2y agoYes, sure, if it helps you to think in those terms I guess that makes sense. Being a bit reductive perhaps but I think what it comes down to is having an interest in the "why" as much as the "what" and the "how".
- spencerchubb 2y agoever since i started working for an insurance company, i realized that understanding the insurance industry is far more difficult than understanding the codebases. if the codebase is acting weird, at least i can step through it with a debugger!
- kdmtctl 2y agoReinsurance is a beast. I spent a good time cracking layers and trying to implement the logic with a team.
- sotix 2y ago
- jimnotgym 2y agoThere is a bigger lesson here. When you are creating something new it pays to understand what came before. Do you need to disgard everything? I gave a boorish lecture to a junior accountant recently... When you make things up yourself it is just you and Excel. When you use double entry you have 100s of years of history to fall back on. https://en.m.wikipedia.org/wiki/Double-entry_bookkeeping https://en.m.wikipedia.org/wiki/Double-entry_bookkeeping
- BlueTemplar 2y agoThough there's a weirder life lesson here : a lot (most / all ?) of successes come from founders not having enough experience to know just how difficult their enterprise is. More experienced founders would take a look at it and immediately nope out of it, and so not achieve success (after a grueling amount of work).
- figassis 2y agoThis is the type of thing where it helps to hire the right people from the start. You hire a bunch of leetcode experts, but never stop to ask if, besides conjuring data structures and algos in their minds they actually can build the thing you want to build. If your people know how to build the thing, you don't need to sacrifice growth, it gets built right from the start. Sometimes you need engineers that have some other type of education, maybe accounting, maybe finance, maybe biology. I always thought that the most important part of my career was understanding every industry I built for, deeply, and knowing experts in those areas so you could ask the really important questions. That is problem solving and engineering. The rest is programming/coding.
- slashdave 2y agoIn some circles, there is the irritating tendency to believe that technology can solve every problem. Experts are eschewed because innovation is valued above all else.
- manyxcxi 2y agoI have never come across a post on HN that was so scarily describing my current day to day and with a comment I agree with so wholeheartedly. I’ve spent the majority of my career in tech with a finance angle to it, mostly sales and use tax compliance. What I never fully appreciated was how much those accountants, controllers, and lawyers were rubbing off on me. I was recently advising a pretty old startup on their ledgering system and was beyond appalled at what it looks like when a bunch of engineers with no finance or accounting background build an accounting system. We don’t have to find magical accountant engineers either, it will wholly suffice if we sit actual accountants in with our engineering team during the design process. After my design of their complete overhaul I had a friend who is a CPA completely review my work, we found a few holes in certain scenarios, but by and large we were good. Money is a difficult engineering problem because with money comes all the human goofery that surrounds it.
- kdmtctl 2y agoThis. Ledgers are a domain knowledge. Anything else should be built on top, including high load optimizations.
- bob1029 2y agoIf you are trying to reinvent parts of banking, you could maybe start with what already works as a thought experiment. Here's an example of a core banking deposit transaction schema that has been extensively battle tested in many small & mid-size US institutions: https://jackhenry.dev/open-enterprise-api-docs/operational-data-integration/odi-extracts/silverlake/deptrn/ https://jackhenry.dev/open-enterprise-api-docs/operational-d... You may note fields like "Effective Date" & "Affects Balance/Interest", which imply doing this correctly may involve exploring some interesting edge cases. Wouldn't it be cool if you could just cheat and start with an approach that already considers them?
- cranium 2y agoDouble-entry accounting is like strongly typed programming languages. Yeah it's a real pain to get started because you need to understand the core concepts first then fight to balance the transactions ("compile errors") before you have anything useful. And when your results are wrong, you know that at least it's not because of the basic stuff.
- exabrial 2y agoThe whole "move fast and do a shit job" is laughably stupid. It's pure incompetence and egotism and a product of excess salary in the market. Doing it the right way doesn't take any longer than doing it the shitty way. Successful startups focus on extreme minimalism, not focus on doing the worst possible job.
- jprosevear 2y agoExcept if you don't actually know what to do, or even what concepts to apply. This is where I see many start ups fall down.
- dang 2y agoOk, but please don't fulminate on HN. This is in the site guidelines: "Please don't fulminate." https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html.
- revskill 2y agoFintech is safe heaven for scam.
- taneq 2y agoOnce upon a time I worked for a company that made accounting software. While there I had to explain to the other devs: 1) That being able to escape characters in CSV files is kind of important. (Some customers noticed that a single quote in a transaction description would make the importer silently fail to import the rest of the transactions... :S ), and 2) Why it wasn't good to store all dollar values as doubles. I'm reasonably sure I quoted Superman 3 at some point during this discussion.
- stavros 2y agoIt really irks me that the author assumes I know how double-entry accounting works and doesn't mention a single sentence about it. I read half way through the article and couldn't follow it, except that single-entry is bad and double-entry is good.
- foobarian 2y agoI've been trying to figure out double-entry accounting for years now and still don't get it. Most explanations are along the lines of "Here is a simple explanation that you are guaranteed to understand: <proceeds to describe the procedure>" which lacks intuition on why this is useful. I suspect I would need to do a gig as an accountant and run into some error conditions that double-entry solves to really grok it. Edit: no offense but sibling comment is an example :P
- stavros 2y agoAgreed, exactly the same here. I was hoping the article would explain, but sadly, no.
- stocknoob 2y agoImagine you’re running a physics simulation. With conservation of energy: if energy shows up somewhere, it went down somewhere else. We shouldn’t assume a balance changed on its own without any other effects in the system. If you start “losing net energy” you can see what’s going on.
- tetha 2y agoFrom what I've learned from a few guys, double ledger accounting is a technique which optimizes for consistency, error detection and fraud detection. Each movement of money, or material should always be written down in two or possibly more places. Ideally by independent people or systems. Once you pair this with another entity or company doing the same, it becomes very hard for money or goods to vanish without the possibility to track it down. Either your books are consistent (sum of "stock" + sum of "ingress" - sum of "egress" - sum of "waste" makes sense), or something is weird. Either your incoming or outgoing goods match the other entities incoming or outgoing records, or something is amiss in between. This is more about anomaly detection, because paying a clerk can be cheaper than losing millions of dollars of material by people unloading it off of a truck en-route.
- anonzzzies 2y agoI saw this so many times. It is rather depressing. Even experienced devs hardly know enough about floats, rounding etc to implement these things, but they do. We were asked to troubleshoot a project for an online insurer ; the devs did two conversions; js and php. So the amount from the frontend ended on the server and got converted and got into the db as an entry. Definitely depressing how frontend numbers are converted and actually this means something to the end result. But the php conversion was also wrong, so it was often cents off. I believe people should never be allowed to have a 'senior developer' job again, but this is really quite commonplace. Most companies don't have enough revenue to notice or care, but given how often we see it, I would say it's actually normal.
- grishka 2y agoWhile I've never worked on financial systems myself, I was told many times that monetary amounts should always be stored and manipulated as integer amounts of smallest units of currency (cents). One reason being that integer math is always exact, while floating-point isn't. And when money is involved, you want your math to be exact so everything always adds up every step of the way. So I'm always calling it out when someone is using floats to store money.
- emptyfile 2y ago[dead]
- ta12653421 2y agowell, you could do this, but it would make world much more complex when working with the numbers in the code - todays highlevel languages like Java or C# have a "decimal" datatype which should be used for money/accounting, these types also offer several digits of accuracy, if required.
- __MatrixMan__ 2y ago> Not losing track of money is the bare minimum for fintech companies. The last fintech I worked for had a joke about how you weren't really an employee until your code had lost some money.
- naasking 2y agoEveryone keeps focusing on double entry book keeping, but that's a ledger that's more suited to manual book keeping. We're in the computer age, people should be using the richer accounting model of REA: https://en.wikipedia.org/wiki/Resources%2C_Events%2C_Agents https://en.wikipedia.org/wiki/Resources%2C_Events%2C_Agents You can see that this model has all of the features discussed in the article, and then some, and REA events map naturally to something like event sourcing. You can project a REA dataset into a double entry ledger, but you often can't go the other way around.
- MarkMarine 2y agoI read the source you sited but it seems like a foundational part of the model is basically double book accounting: “At the heart of each REA model there is usually a pair of events, linked by an exchange relationship, typically referred to as the "duality" relation. One of these events usually represents a resource being given away or lost, while the other represents a resource being received or gained.” This is what I see as the main difference between single book accounting and double book accounting, with REA having some OO things added to the model to more accurately represent business objects when a computer is used. What am I missing about REA that makes it better than double book as implemented in the way this post was talking about implementing it?
- naasking 2y agoDouble entry bookkeeping (DEB) records entries in ledgers. There are no ledgers in REA, therefore REA is not double-entry bookkeeping. You could argue that when representing both DEB and REA in an entity-relational model, they might have some similar looking tuples and relations, but that does not entail that they have the same data model. As I said in my initial post, REA is a richer data model that captures more information. You can reproduce the ledgers of DEB from a REA system, but you cannot go the other way in all cases.
- MarkMarine 2y agoCan you expand on why? Or link some more detailed blog post or writing so I can dig into it? I’m interested
- neuroelectron 2y agoI don't know what the fuck I just read here. I've worked on ledgers for years with massive codebases with millions of loc and I've never seen an error of "a few cents". Feels like I just read a alibi. Don't develop financial software from scratch.
- deleted 2y ago[deleted]
- 392 2y agoThe lesson here is not to never develop from scratch. In fact it may be faster and safer to do so than to vet all of the open source junk that modern ByteByteGo-system-designers think they need. TigerBeetle and Jepsen-proof-engineering are paths to dig down here, along with basic knowledge of computer number storage. The lesson for me here is that there is no substitute for knowing or caring about what you're doing. Dancing cents don't happen when eng cared about correctness in the first place. I feel like I just read a college freshman explaining how there's no possible way they could have passed their first exam. Better yet he's here to sell us on his thought leadership without ever explaining why he failed the first exam.
- ahi 2y agoI read the intro and decided I wouldn't learn much from someone willing and eager to admit he eats paint chips.
- rstuart4133 2y agoThat was my reaction too. It was like reading an engineering team saying their attempt to design a new lightweight mountain bike failed. It turned out saving weight by omitting brakes wasn't a good idea, and their attempt to fix it by riding beside each bike and manually slowing it down wasn't too popular either. Then they have the hubris to follow that up with, "you can avoid the same mistakes by reading what we have to say on bicycle design". The lessons they can take away have very little to do with engineering or FinTech. I'd file it under doing a bit of research before committing to any major task. Basic accounting principles are centuries old now. They could have learnt about them by buying a high school text book, reading it cover to cover and use doing the exercises. It would have taken them less than a week. Admittedly that only gives you the "how", not the "why". You realise much, much later that the engineering equivalent of double entry accounting is two systems design by different teams that are constantly comparing their outputs. By the time you've figured that out, it's caught so many errors you realise "holy shit, these systems are really easy to screw up, and are under constant attack by malicious actors". There is a hidden trap at every step - floating point being imprecise, currency rounding not being reversible, tax calculations being one way, ACID being a hard requirement. I'm being this mob screwed up tax calculations. Floating point throwing out 1 in 100 million transactions was one of the joys they never got to experience.
- charlie0 2y agoAs an SWE, I've seen how the sausage is made and is the reason why I'm very very careful when using fintechs for anything.
- alexey-salmin 2y ago> Instead of using negative numbers, Accounts have normal balance: normal credit balance literally means that they are normal when its associated entries with type credit have a total amount that outweighs its associated entries with type debit. The reverse is true for normal debit balance. I didn't understand this part, can someone give examples of good and bad approaches for both credit and debit accounts?
- j45 2y agoStartups could improve in 2 wasy: Perhaps popular culture should review the use of nosql databases, and then spending tremendous effort to try and make it into a relational database, while nosql databases can be setup to be eventually consistent. Money, and accurate accounting don't work too well when the inputs to a calculation of a balance are eventually consistent. So much work is avoided at times it seems to not learn SQL that it can rival or end up being more work once NOSQL leads you down the path of inevitable relational needs. In addition to this, maybe it's time to build honeypot ledgers with a prize and reward in it for anyone who can hack or undermine it, similar to vulnerability bounties. Run for long enough, it would determine at least that one side of security mistakes in startups being reduced. Run a sprint, with prizes and let them run like daily deal fantasy and watch things harden.
- yfw 2y agoGreat post!
- masto 2y agoOne of the things it took a little time to wrap my head around when I started working at Google was trading off reliability or correctness for scaling. I had previously built things like billing systems and small-scale OLTP web applications, where the concept of even asking the question of whether there could be any acceptable data loss or a nonzero error rate hadn't occurred to me. It was eye-opening to see, not so much that if you're doing millions of qps, some are going to fail, but more the difference in engineering attitude. Right this instant, there are probably thousands of people who opened their Gmail and it didn't load right or gave them a 500 error. Nobody is chasing down why that happened, because those users will just hit reload and go on with their day. Or from another perspective, if your storage has an impressive 99.99999% durability over a year, when you have two billion customers, 200 people had a really miserable day. It was a jarring transition from investigating every error in the logs to getting used to everything being a little bit broken all the time and always considering the cost before trying to do something about it.
- Scubabear68 2y agoThis all makes a lot of sense, but I have seen this a lot in the opposite direction. Specifically, people from social media companies with very squishy ideas around failures coming into financial applications. Generally does not go well.
- hedora 2y agoDurability levels that poor aren’t state of the art any more. The rule of thumb I’ve seen at most places (running at similar scale) is to target one data loss, fleet wide, per century. That usually increases costs by << 10%, but you have to have someone that understands combinatorics design your data placement algorithms. The copyset paper is a good place to start if you need to understand that stuff.
- Dylan16807 2y agoThat sounds a lot better than some number of nines standing by itself. 99.(9)x percent durability is almost meaningless without a description of what the unit of data is, what a loss looks like. There's too many orders of magnitude between a chunky file having an error, a transaction having an error, a block having an error, a bit having an error...
- PeterStuer 2y agoThis was many years ago. I has an injurie that prevented me from driving, so I asked if there was any project on the backburner I could do on my own in 3 weeks without too much interaction (this was long before easy remote work infra). Sure there was. A financial services company wanted to replace their repayment plan generator that ran on an aging AS/400 with someting running in .Net on Windows. I dug in an learned all about time value of money, numerical formats and precision, rounding strategies, day counting strategies for incomplete periods (did you know there are many dozens of those) etc. I made everyting as configurable as I could so we had the option to offer to other financial service clients by just setting up a different profile. Since I had no interaction with the client before the first presentation meeting, I put in what to me felt like the most plausible config (I had managed projects in the domain before so I was not completely clueless to the mindset). We had the meeting. I showed a few calculated plans which they compared on the spot to the AS/400 output. I deployed on a test VM for them so they could do more extensive testing. Code was accepted with 0 change requests and put into production shortly thereafter. Don't think they ever changed from the default settings.
- knorker 2y agoA related pet peeve of mine is UIs that round off your investment holdings or cash. Sometimes to 2 digits. Sometimes 3. Or 4. How many significant digits are there even in fractional SPY holdings? You just resort to looking in all the places (statements, transaction history, overview dashboard, …) and going with the one that shows the most digits, and assume that's all of them. Big and small companies do this. And when I've reported it, they don't care. They don't see the problem.
- knorker 2y agoIf the author is reading this: Please stop hiding the scroll bar. It's user hostile. I want to see if I have time to finish this article before I have to leave. And now I have to waste time copy-pasting the contents into a text file, just to see where I am. Edit: Actually, it's invisible only in Firefox. Chrome shows the scrollbar still. So this may be a bug in the author's CSS or something.
- michaelcampbell 2y agoOne of my $previousjob's managed to invent their own kind-of sort-of double entry accounting system, but not quite. So whenever anything went sideways (and we interacted with Stripe, so something always went sideways), it required a lot of manual intervention with changing of amounts in various tables. I pushed for offsetting entries instead, but was overruled. It was a _nightmare_. Thankfully, it is not $previousjob.
- artyom 2y agoThe number of engineers I've met that realized only too late that, by definition, floats and doubles are absolutely *not good* to deal with money is unbelievable. At this point it should be universal knowledge, but it isn't.
- fredtalty5 2y ago[dead]
- JimmyWilliams1 2y ago[dead]
- pclowes 2y agoI think “make it work, make it right, make it fast” is a solid approach. It appears the startup in question just never even did step one. A financial system that is imprecise does not work. Additionally that mantra is typically applied at the story/issue level in my experience as in: 1. Get the tests passing 2. Get the code clean 3. Identify scaling bottlenecks and remedy if necessary.
- p4bl0 2y agoInteresting article, thanks for sharing! I believe the things it explains are very important, and not only in fintech. A few years ago, even in the case of trying to keep track of a small organisation spendings and incomes in a spreadsheet I had some of the problems that are mentioned in the article and had to completely rethink and remake the spreadsheet in order to make it actually work. But apart from the technical points, another interesting thing in the article is its introduction and what it says there about money as a concept. Yes, money is debt, both philosophically and technically it is the right way to think about it. And I believe that's something the crypto-assets industry and enthusiasts as a whole fundamentally gets wrong (mostly because of the libertarian political point of view blockchain tech has been designed with).
- matheusmoreira 2y agoLearning and using the ledger-cli accounting tool taught me a lot about this. It's incredible how messy seemingly simple things can be and how much trouble a bunch of cents can cause. Seems to be the accounting version of off-by-one errors. It is very tempting to just write them off as losses and forget about them forever. Rounding in particular is a truly endless source of trouble and has caused me to chase after a lot of cents. Dividing up a large payment into multiple installments is the major cause of rounding in my use case. Life starts to suck the second things fail to be evenly divisible. I created an account to track gains and losses due to rounding and over time and it's adding up to quite the chunk of change. Hilariously, the payment systems would charge me incorrect rounded up amounts and then they would refund the difference to my credit card at some undefined time in the future. Tracking and correlating all these seemingly random one or two cent transactions has got to be one of the most annoying activities I've ever learned to put up with. Not only do I have to figure out why things aren't quite adding up, I have to patch things up in the future when they fix the mistake. Why can't these things just charge the correct amounts? For example, imagine splitting up $55.53 into four installments. That's 4x$13.8825. They could charge me 3x$13.88 + 1x$14.89. Instead they round it up to $55.56 and charge me 4x$13.89, then maybe they refund me $0.03 some unknown day in the future. It's like the systems go out of their way to be as annoying as possible. Some systems do this silly single cent refund dance in my credit card statement even though they print the exact same 3xN + 1xN+0.01 solution in the receipt. Makes absolutely no sense to me. It's getting to the point I'm trying to avoid this nonsense by structuring purchases so the final price is evenly divisible by some common factors. I never liked the .99 cents manipulation trick but I seriously hate it now.
- kwakubiney 2y agoAt $currentJob, we have decided to stick with Fineract for ledger maintenance and that helped us scale without having to deal with the nitty gritty details of accounting. If you don’t have the necessary expertise around you, offload that responsibility to a third party system that is maintained by those who do.
- wisdomalfred 2y ago[flagged]
- rolandthomas 2y ago[dead]