[{"data":1,"prerenderedAt":361},["ShallowReactive",2],{"project-38084098":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":28,"sentiment":29,"stance_mix":30,"scored_comments":35,"aspects":36,"strip":44,"post_text":45,"what":46,"said":80,"maker_in_thread":200,"shape":212,"grid":216,"attempts":323,"same_week":324,"maker_shows":251,"maker_hidden":353,"reader_version":354,"card":355},"38084098","postgresql-event-sourcing","Light implementation of Event Sourcing using PostgreSQL as event store","title","Show HN: Light implementation of Event Sourcing using PostgreSQL as event store","https:\u002F\u002Fgithub.com\u002Feugene-khyst\u002Fpostgresql-event-sourcing","github.com","eugene-khyst",1698757003,2023,231,47,228,3109,8,"notable","dev_tools","event sourcing reference implementation","library",[24,25,26,27],"event sourcing","postgresql","spring boot","transactional outbox","debated",0.029,{"positive":31,"neutral":32,"mixed":33,"critical":34},6,7,0,5,18,{"idea":37,"docs":39,"design":42,"execution":43},{"positive":33,"critical":38},3,{"positive":40,"critical":41},4,1,{"positive":41,"critical":33},{"positive":33,"critical":41},[41,33,41,33,33,33,33,33,33,33,34,34,33,33,38,38,41,34,33,33,33,33,33,34,33,33,41,33,38,33,33,38,33,38,38,38,33,33,41,34],"Hi everyone,\n\nIf you have a Java Spring Boot application with a PostgreSQL database, you can implement Event Sourcing without introducing new specialized databases or frameworks.\n\nIf you have an application dealing with an entity called Order, you should adopt Event Sourcing to keep track of all changes, and know how the Order got into the current state.\n\nEvent Sourcing gives you:\n\n1. the true history of the system (audit and traceability),\n\n2. the ability to put the system in any prior state (debugging),\n\n3. the ability to create read projections from events as needed to respond to new demand",{"problem":47,"audience":53,"pricing":60,"motivation":61,"time_to_build":60,"stack":65,"openness":78,"stage":79,"team_size":79},{"value":48,"source":49,"evidence":50},"Implementing event sourcing without adopting a specialized event store database or framework","maker",[51],{"id":52},"post",{"value":54,"source":49,"evidence":55},"Java Spring Boot developers with PostgreSQL databases",[56,57],{"id":52},{"id":58,"by":11,"text":59},"38095863","plpgsql is good language. But in my experience Java and .NET developers tend to choose solutions that do not use plpgsql, PL\u002FSQL, T-SQL. And these developers is the main audience…",null,{"value":62,"source":49,"evidence":63},"Lower the barrier to trying event sourcing without a new database or framework",[64],{"id":52},[66,70,74],{"value":67,"source":49,"evidence":68},"Java",[69],{"id":52},{"value":71,"source":49,"evidence":72},"Spring Boot",[73],{"id":52},{"value":75,"source":49,"evidence":76},"PostgreSQL",[77],{"id":52},"open_source","unknown",{"praise":81,"objections":105,"requests":120,"questions":134,"alternatives":149},[82,98],{"value":83,"source":84,"evidence":85},"Comprehensive, in-depth README covering PostgreSQL internals and gotchas","commenter",[86,90,94],{"id":87,"by":88,"text":89},"38085502","wvh","While I haven't kept up to date with Event Sourcing, the README referenced is a surprisingly in-depth tour of Postgresql functionality and internals, and typical relational…",{"id":91,"by":92,"text":93},"38085995","quercusa","Agreed - perhaps the most comprehensive README I've ever seen.",{"id":95,"by":96,"text":97},"38093147","NomDePlum","Have to say this is a great resource. I've been using it to discuss how my team could understand and build a similar implementation to this using Golang+Postgres. It provided a…",{"value":99,"source":84,"evidence":100},"Illustrations are outstanding",[101],{"id":102,"by":103,"text":104},"38086220","whalesalad","The illustrations are outstanding.",[106,113],{"value":107,"source":84,"evidence":108},"Event ID sequence ordering can cause lost events for subscribers",[109],{"id":110,"by":111,"text":112},"38087659","reese_john","Using only the event ID to track events processed by the subscription is unreliable and can result in lost events. The ID column of the ES_EVENT table is of type BIGSERIAL. It's…",{"value":114,"source":84,"evidence":115},"Missing license information",[116],{"id":117,"by":118,"text":119},"38086819","mdaniel","It appears to be missing any licensing information",[121,127],{"value":122,"source":49,"evidence":123},"Add a license",[124],{"id":125,"by":11,"text":126},"38087354","Thanks for noticing. I will add Apache License 2.0.",{"value":128,"source":84,"evidence":129},"Use readOnly transactions for read methods",[130],{"id":131,"by":132,"text":133},"38095180","koevet","I noticed that you use the @Transactional annotation on class definition. This will create a write transaction for every public method of the annotated class, including read only…",[135,142],{"value":136,"source":84,"evidence":137},"How is current state rolled up from events into a read model",[138],{"id":139,"by":140,"text":141},"38088198","lacrosse_tannin","How do you roll the history up into the current state? I get the idea, but where is the actual code or query that does this? Especially how do you make an up to date read model…",{"value":143,"source":84,"evidence":144},"How to handle events logged out of order",[145],{"id":146,"by":147,"text":148},"38090273","globular-toast","This seems as good a place to ask as any. I've become interested in event sourcing because of a problem it might help with. Essentially, we have a system where users can log…",[150,165,172,179,186,193],{"value":151,"source":84,"evidence":152},"Audit tables and temporal tables",[153,157,161],{"id":154,"by":155,"text":156},"38086715","mickeyp","Using audit tables is another approach that avoids rolling up the data periodically, and you avoid all the needless complexity this approach can introduce; particularly if you're…",{"id":158,"by":159,"text":160},"38087935","KronisLV","> You gain temporal querying with a history\u002Faudit table that mirrors the main one (or not -- if you prefer not to, and instead want to cram everything into a jsonb column). I…",{"id":162,"by":163,"text":164},"38089616","sa46","I love temporal tables. I built an implementation in Postgres [1] in a few hundred lines of PLPGSQL. We've run the implementation for several years across a few hundred tables…",{"value":166,"source":49,"evidence":167},"EventStoreDB",[168,171],{"id":169,"by":11,"text":170},"38095045","I can definitely recommend EventStoreDB. I used it in production and most colleagues like this DB. I have a sample Java Spring Boot + EventStoreDB project…",{"id":52},{"value":173,"source":84,"evidence":174},"Marten",[175],{"id":176,"by":177,"text":178},"38092493","jchannon","Check out Marten for a fully fleshed out implementation https:\u002F\u002Fgithub.com\u002FJasperFx\u002Fmarten",{"value":180,"source":84,"evidence":181},"Commanded",[182],{"id":183,"by":184,"text":185},"38085244","conradfr","This reminds me of Commanded[0] for elixir which also uses Postgresql by default. [0]https:\u002F\u002Fgithub.com\u002Fcommanded\u002Fcommanded",{"value":187,"source":84,"evidence":188},"message-db",[189],{"id":190,"by":191,"text":192},"38085358","Nelkins","In addition to the alternatives mentioned, here’s another Postgres-only ES implementation: https:\u002F\u002Fgithub.com\u002Fmessage-db\u002Fmessage-db",{"value":194,"source":84,"evidence":195},"Debezium transaction log tailing",[196],{"id":197,"by":198,"text":199},"38088688","marwis","> I actually think this dual use-case is something we can really improve upon. In some fever-dream what I think I want is some combination of Kafka (append-only event stream) and…",{"comments":201,"answered":38,"key":202},11,[203,206,209],{"id":204,"text":205},"38087186","No doubt audit tables are a popular alternative to event sourcing. But if the current state and changes history of the entity are stored in different tables, someone may say:…",{"id":207,"text":208},"38088813","Yes, Debezium is an implementation of the Transaction log tailing pattern an alternative to Transactional outbox pattern.",{"id":210,"text":211},"38088693","Thanks for sharing. > My linked code works with involving the MVCC snapshot's xip_list as well, to avoid this gotcha. I will definitely take a look. It would be great to fix this…",{"commenters":213,"max_depth":40,"maker_replies":201,"first_comment_mins":214,"lifespan_hours":215},28,82,30,[217,219,221,224,226,230,231,232,234,235,238,240,242,243,247,249,253,255,256,257,258,259,262,264,266,269,271,274,276,279,281,284,287,291,292,295,296,298,300,301,303,305,310,312,314,317,319],[154,33,41,218,155,33],"project\u002Fcritical\u002Fidea",[204,33,33,220,11,41],"project\u002Fpositive\u002Fidea",[222,33,41,218,223,33],"38088073","zbentley",[158,33,33,225,159,33],"other\u002Fneutral\u002Fnone",[227,33,33,228,229,33],"38088400","other\u002Fneutral\u002Fidea","zoogeny",[197,33,33,225,198,33],[207,33,33,225,11,41],[233,33,33,228,229,33],"38089043",[162,33,33,225,163,33],[236,33,33,225,237,33],"38090618","robocat",[239,33,33,225,163,33],"38090794",[87,41,34,241,88,33],"project\u002Fpositive\u002Fdocs",[91,41,34,241,92,33],[244,41,34,245,246,33],"38087645","maker\u002Fpositive\u002Fnone","brasetvik",[210,41,33,248,11,41],"commenter\u002Fneutral\u002Fnone",[250,251,33,225,252,33],"38092812",2,"lichtenberger",[190,38,38,254,191,33],"project\u002Fneutral\u002Fnone",[183,40,38,254,184,33],[176,34,41,218,177,33],[95,31,34,241,96,33],[146,32,33,228,147,33],[260,32,33,228,261,33],"38090635","dqv",[263,32,33,228,147,33],"38096268",[265,32,33,228,261,33],"38103071",[267,32,33,228,268,33],"38090651","svilen_dobrev",[270,32,33,228,147,33],"38096221",[272,32,33,228,273,33],"38091097","refset",[102,18,34,275,103,33],"project\u002Fpositive\u002Fdesign",[277,18,33,278,11,41],"38086481","project\u002Fneutral\u002Fdesign",[280,18,33,248,103,33],"38086668",[110,282,41,283,111,33],9,"project\u002Fcritical\u002Fexecution",[285,282,33,286,11,41],"38088586","project\u002Fneutral\u002Fexecution",[288,282,38,289,290,33],"38095149","maker\u002Fneutral\u002Fnone","nextaccountic",[58,282,33,254,11,41],[293,294,33,228,268,33],"38091246",10,[169,294,33,225,11,41],[139,201,38,297,140,33],"maker\u002Fneutral\u002Fexecution",[299,201,33,297,11,41],"38088889",[131,201,38,286,132,33],[302,201,33,286,11,41],"38095848",[304,201,38,289,140,33],"38099022",[306,307,38,308,309,33],"38086752",12,"project\u002Fneutral\u002Fidea","Salgat",[311,307,33,254,11,41],"38087328",[313,307,33,225,309,33],"38099891",[117,315,41,316,118,33],13,"project\u002Fcritical\u002Fdocs",[125,315,33,318,11,41],"project\u002Fneutral\u002Fdocs",[320,321,34,241,322,33],"38087230",14,"argulane",[],[325,330,335,340,344,349],{"id":326,"name":327,"points":328,"category":329},"38052344","OpenSign",545,"web_saas",{"id":331,"name":332,"points":333,"category":334},"38044782","WireHole",298,"infrastructure",{"id":336,"name":337,"points":338,"category":339},"38038239","ScratchDB",261,"data",{"id":341,"name":342,"points":343,"category":334},"38086598","MicroTCP",204,{"id":345,"name":346,"points":347,"category":348},"38093083","Halloween game (snail terminal demo)",173,"games",{"id":350,"name":351,"points":352,"category":339},"38057759","Open Australian Legal Corpus",172,false,"v2",{"id":356,"name":5,"line":6,"ai":353,"cat":20,"year":13,"points":14,"comments":15,"rec":28,"s":357,"top":18,"kw":358,"maker":11,"domain":10,"tier":19,"attempts":33,"strip":359,"url":9,"mix":360,"praise":83,"objection":107,"sub":21},38084098,0.03,[24,25,26,27],"1010000000550033150000050010300303330015",[31,32,33,34],1793991077213]