[{"data":1,"prerenderedAt":210},["ShallowReactive",2],{"case-study-en-ale-business-bookkeeping":3,"case-study-related-en-ale-business-bookkeeping":186},{"id":4,"title":5,"card":6,"diagrams":12,"extension":28,"eyebrow":29,"facts":30,"intro":40,"layout":41,"locale":60,"meta":61,"order":62,"results":63,"slug":76,"stem":77,"storySections":78,"techGroups":90,"__hash__":185},"caseStudies\u002Fcase-studies\u002Fen\u002Fale-business-bookkeeping.json","AWS architecture for chat-driven bookkeeping with an LLM harness",{"title":7,"badges":8,"thumb":11},"Chat-driven bookkeeping",[9,10],"LLM harness","Amazon Bedrock","\u002Fcase-studies\u002Fale-business-bookkeeping\u002Fsystem-architecture.webp",[13,16,20,24],{"src":11,"alt":14,"caption":15},"System architecture: Chat, finance API and LLM harness in one EU region","System architecture.",{"src":17,"alt":18,"caption":19},"\u002Fcase-studies\u002Fale-business-bookkeeping\u002Fllm-harness.webp","LLM harness: From a chat message to a correct booking","The LLM harness. The model never writes to the ledger directly.",{"src":21,"alt":22,"caption":23},"\u002Fcase-studies\u002Fale-business-bookkeeping\u002Finvoice-pipeline.webp","Invoice pipeline: Correct before it is sent, unchangeable after","Invoice pipeline, with the privacy and backup layer underneath.",{"src":25,"alt":26,"caption":27},"\u002Fcase-studies\u002Fale-business-bookkeeping\u002Fcore-stack.webp","Core stack","","json","Case study · ale.business",[31,34,37],{"label":32,"value":33},"Industry","Finance, bookkeeping",{"label":35,"value":36},"My role","Architecture, LLM harness, invoicing pipeline",{"label":38,"value":39},"Focus","Privacy, correctness, automation","Finance solutions for small businesses. Book expenses and send invoices by writing a chat message, with an LLM that proposes and deterministic code that decides.",[42,44,46,49,51,53,54,56,58],{"type":43},"header",{"type":45},"results",{"type":47,"index":48},"section",0,{"type":50,"index":48},"diagram",{"type":50,"index":52},1,{"type":47,"index":52},{"type":50,"index":55},2,{"type":57},"technology",{"type":50,"index":59},3,"en",{},4,[64,68,72],{"tag":65,"title":66,"body":67},"Automation","Bookkeeping from a chat message","Write what happened, attach the receipt. The harness turns it into a correct booking or asks back.",{"tag":69,"title":70,"body":71},"Correctness","Invoices sent correctly, automatically","Numbered, validated and archived before anything leaves the system.",{"tag":73,"title":74,"body":75},"Privacy","Financial data stays protected","EU region only, encrypted end to end, backed up and fully auditable.","ale-business-bookkeeping","case-studies\u002Fen\u002Fale-business-bookkeeping",[79,86],{"heading":80,"paragraphs":81},"The story",[82,83,84,85],"Bookkeeping is the part of running a business nobody wants to do. ale.business turns it into a conversation: write \"paid 49 € for software\" and attach the receipt, or ask for an invoice to a customer, and the system does the rest.","An LLM on its own is not good enough for finance. It can misread an amount, pick the wrong tax rate or invent an account. So I built a harness around it: Bedrock only returns a structured proposal, and Python code checks the schema, the double-entry balance, the tax rules and duplicates before anything is booked. Unclear cases go back to the user in the chat.","Invoices follow the same principle. Each one gets a gapless number, is validated for mandatory fields and totals, rendered as PDF and e-invoice, sent through SES and archived in S3 with Object Lock, so it can never be changed afterwards.","Because it is financial data, privacy shaped every decision: everything runs in the Frankfurt region, data is encrypted with KMS, backups are encrypted and stay in the EU, and CloudTrail records every access.",{"heading":87,"paragraphs":88},"Invoicing",[89],"An invoice is a legal document, so the pipeline treats it as one. If any check fails, nothing is sent and the user gets a concrete fix in the chat.",[91,118,140,168],{"title":92,"items":93},"Application",[94,100,106,110,114],{"name":95,"role":96,"icon":97,"icons":98},"Nuxt, Vue","chat and web app","\u002Ficons\u002Ftech\u002Fnuxt.svg",[97,99],"\u002Ficons\u002Ftech\u002Fvuejs.svg",{"name":101,"role":102,"icon":103,"icons":104},"Python, FastAPI","finance API, LLM harness","\u002Ficons\u002Ftech\u002Fpython.svg",[103,105],"\u002Ficons\u002Ftech\u002Ffastapi.svg",{"name":107,"role":108,"icon":109},"Amazon EC2","app and harness servers","\u002Ficons\u002Faws\u002FAmazon-EC2.svg",{"name":111,"role":112,"icon":113},"Amazon DynamoDB","append-only ledger, invoice numbers","\u002Ficons\u002Faws\u002FAmazon-DynamoDB.svg",{"name":115,"role":116,"icon":117},"Amazon S3","receipts, invoice archive with Object Lock","\u002Ficons\u002Faws\u002FAmazon-S3.svg",{"title":119,"items":120},"AI and automation",[121,124,128,132,136],{"name":10,"role":122,"icon":123},"LLM and guardrails in the EU region","\u002Ficons\u002Faws\u002FAmazon-Bedrock.svg",{"name":125,"role":126,"icon":127},"AWS Lambda","invoice worker","\u002Ficons\u002Faws\u002FAWS-Lambda.svg",{"name":129,"role":130,"icon":131},"Amazon EventBridge","recurring invoices, reminders","\u002Ficons\u002Faws\u002FAmazon-EventBridge.svg",{"name":133,"role":134,"icon":135},"Amazon SES","invoice delivery","\u002Ficons\u002Faws\u002FAmazon-SES.svg",{"name":137,"role":138,"icon":139},"API Gateway","WebSocket chat","\u002Ficons\u002Faws\u002FAmazon-API-Gateway.svg",{"title":141,"items":142},"Security and privacy",[143,147,151,157,164],{"name":144,"role":145,"icon":146},"Amazon Cognito","login, MFA, roles","\u002Ficons\u002Faws\u002FAmazon-Cognito.svg",{"name":148,"role":149,"icon":150},"AWS IAM","least-privilege roles","\u002Ficons\u002Faws\u002FAWS-IAM.svg",{"name":152,"role":153,"icon":154,"icons":155},"AWS KMS, Secrets Manager","encryption, credentials","\u002Ficons\u002Faws\u002FAWS-KMS.svg",[154,156],"\u002Ficons\u002Faws\u002FAWS-Secrets-Manager.svg",{"name":158,"role":159,"icon":160,"icons":161},"Amazon VPC, CloudFront, WAF","private network, edge, protection","\u002Ficons\u002Faws\u002FAmazon-VPC.svg",[160,162,163],"\u002Ficons\u002Faws\u002FAmazon-CloudFront.svg","\u002Ficons\u002Faws\u002FAWS-WAF.svg",{"name":165,"role":166,"icon":167},"AWS Backup","encrypted backups, EU only","\u002Ficons\u002Faws\u002FAWS-Backup.svg",{"title":169,"items":170},"Delivery and operations",[171,175,179],{"name":172,"role":173,"icon":174},"Docker","containers","\u002Ficons\u002Ftech\u002Fdocker.svg",{"name":176,"role":177,"icon":178},"GitHub Actions","CI\u002FCD","\u002Ficons\u002Ftech\u002Fgithubactions.svg",{"name":180,"role":181,"icon":182,"icons":183},"CloudWatch, CloudTrail","observability, audit trail","\u002Ficons\u002Faws\u002FAmazon-CloudWatch.svg",[182,184],"\u002Ficons\u002Faws\u002FAWS-CloudTrail.svg","HA7A0sy4Sysk6TOc_R5WoYF5elmuncqxk_Q-Qx5y26E",[187,195,203],{"slug":188,"card":189},"kv-cache-storage-tiering",{"title":190,"badges":191,"thumb":194},"KV cache storage tiering",[192,193],"vLLM","LMCache","\u002Fcase-studies\u002Fkv-cache-storage-tiering\u002Ftier-hierarchy.webp",{"slug":196,"card":197},"live-product-data-pipeline",{"title":198,"badges":199,"thumb":202},"Live product data pipeline",[200,201],"Kafka Streams","Amazon MSK","\u002Fcase-studies\u002Flive-product-data-pipeline\u002Fafter.webp",{"slug":204,"card":205},"product-classification",{"title":206,"badges":207,"thumb":209},"Product classification with MLOps",[10,208],"PyTorch","\u002Fcase-studies\u002Fproduct-classification\u002Ftraining-pipeline.webp",1790607906639]