Skip to content

History / Observability

Revisions

  • Rewrite five pages in plain English Observability, Extensions, Workflow modules in Quarkus and in Spring Boot, Renaming a BPMN process. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lxo4MXbp6VPoDkUrTBNXJ1

    @stephanpelikan stephanpelikan committed Oct 11, 2026
  • 459: the refusal of an unknown workflow reads the start row; no poll on top of a retry window Observability: the message of a refused delivery now follows the start row of the delivery log. Quarkus integration: a store adds no poll on top of the window an adapter names, as decision 42 says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lxo4MXbp6VPoDkUrTBNXJ1

    @stephanpelikan stephanpelikan committed Oct 10, 2026
  • VanillaBP owns four tables, and decision 16 says so (446) The housekeeping table came with the night window, so Home and the migration page count four now. Observability drops the number. The two links to decision 16 follow its new heading. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RVEfP4rFpf8XUVXB9CFuL7

    @stephanpelikan stephanpelikan committed Oct 6, 2026
  • A page for blocked outbox entries How to find a blocked entry, open it again or delete it, on the table and on the MongoDB collection, and what to check about a younger entry of the same key first. The ERROR of every dispatcher links here. The statements move from the two platform pages to this one, and the gruelbox store is linked to its own README section. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RVEfP4rFpf8XUVXB9CFuL7

    @stephanpelikan stephanpelikan committed Oct 6, 2026
  • 898: waiting for a read model uses no attempts An entry whose BPMS does not report its workflow yet uses none of block-after-attempts any more. It is blocked once vanillabp.outbox.wait-for-visibility-at-most passed since it was written, about four hours by default. The outbox sections of both platform pages, the migration page and the metrics table say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NGP1Z1mjfXKxCgHzecPvuX

    @stephanpelikan stephanpelikan committed Oct 4, 2026
  • The age a store cannot read is about a store which came from somewhere else "Every store VanillaBP ships" was true while gruelbox was in this repository. It ships from another one now, so the sentence names this platform instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    Claude committed Sep 28, 2026
  • The gruelbox store is named once, and it is named where it lives The store left adapter-platform-integration, so its documentation goes with it. What stays on the Spring Boot page is one section: what gruelbox was, where the artifact is now, and that an application which keeps it changes no configuration. The rows and paragraphs which described how that store differs from the ones VanillaBP writes itself are documented in its own repository. The migration page says the same thing from the version-1 side: entries move to VanillaBP's own table, and what is left in TXNO_OUTBOX is counted at every start. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    Claude committed Sep 28, 2026
  • docs: the block differs between Spring Boot and Quarkus Since the end of a Spring Boot start moved into the lifecycle, what the start of the workflow processing notices is a late finding there and part of the block on Quarkus. The Observability page now says so, so the difference is read rather than discovered by comparing two logs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    @stephanpelikan stephanpelikan committed Sep 27, 2026
  • docs: the counter for work which is not ours A new section says what happens when a BPMS hands this application a task of a workflow another application owns, with the counter to watch and why no delivery record is written. The meter table got its row, and the paragraph about a deleted workflow aggregate no longer names deletion as the only reading. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    @stephanpelikan stephanpelikan committed Sep 27, 2026
  • docs: the block survives a start which ends on something else Story 647 gave the collection of findings a second end. A start which ends on an exception of its own writes the block first, reasons not to start included, and throws nothing there. A finding which arrives after the block goes into the log where it was found, and a late reason not to start is written at error level. What Quarkus refuses while it builds is the one thing left which never reaches the block. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    Claude committed Sep 26, 2026
  • docs: the outbox house-keeps in a window at night, and one node does it Both platform pages get a section of their own about it: when the window is, how VanillaBP works out how much fits into it, that only one node house-keeps a store per night, and that a JVM standing on UTC has to name a time zone or it does not start. The three new meters are in the metrics table and in a section which says how to read them together, because the remainder alone says nothing. The page about running more than one node names the housekeeping as the one piece of work a single node does. The paragraph about the cost of a blocked entry is rewritten. The question which payloads are still needed is one statement in the database now, and on a relational outbox it is a lookup over a column rather than a scan of the table - only gruelbox keeps the scan, because it owns its table. The numbers are the ones measured on 2026-09-25. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    @claude claude committed Sep 25, 2026
  • docs: what a start says about itself A start collects what it notices and says it once, at its end, as one block between two rulers. Observability describes what the block looks like, how to read its headings and counts, what a start which has to be refused does, and that an application with nothing to notice gets nothing at all. Workflow-modules says what the two delivery keys really read, because vanillabp.delivery.retention was described as having no levels while a line below the application now ends the startup, and it points at the block. Workflow-tasks adds the two questions a held version now answers: a message or signal name no model of this deployment declares any more, and an iteration which names no item although a method serving that version reads it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0168Fox39crp8dfWkZ9W84Ub

    @stephanpelikan stephanpelikan committed Sep 25, 2026
  • docs: the MongoDB store dispatches on lanes too The pages still said that the MongoDB store keeps one dispatching thread and does not read `vanillabp.outbox.dispatch-threads`. It reads it since the store got the lanes, so both stores VanillaBP writes itself answer to that setting, and their dispatch threads stand next to their poller in a thread dump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYPiyZ32jQQhqYKx44cw23

    @stephanpelikan stephanpelikan committed Sep 24, 2026
  • docs: there are three tables VanillaBP owns The payload table came with the outbox, so the count on four pages was one short. Home, Quarkus-integration and Observability only count the tables, so they now count three. Migrating-from-version-1 names them, so it names the payload table as well. The Quarkus outbox section named the outbox table alone while the Spring Boot one names both, so a reader of that page could find only two of the three names. It now names the payload table too. The heading of decision 16 carries the same wrong number and is not touched here, because the links to its anchor would break with it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYPiyZ32jQQhqYKx44cw23

    @stephanpelikan stephanpelikan committed Sep 23, 2026
  • docs: the age of the oldest entry comes from the store both platforms run Gruelbox is the store which publishes no age, and it is the one an application opts into now rather than the default on Spring Boot with JPA. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYPiyZ32jQQhqYKx44cw23

    @stephanpelikan stephanpelikan committed Sep 21, 2026
  • docs: Spring Boot writes its outbox itself On a relational database both platforms now run the same store, so the Spring Boot page names the tables VanillaBP owns instead of gruelbox' one, and the table which says what each store does differently has the opted-in gruelbox in its last row. New on both platforms: the outbox dispatches several entries at once and the workflow aggregate decides which thread takes one. The Spring Boot page explains it, the Quarkus page and the observability page point at it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYPiyZ32jQQhqYKx44cw23

    @stephanpelikan stephanpelikan committed Sep 21, 2026
  • docs: the two numbers which say whether the outbox moves The metrics table gets vanillabp.outbox.oldest.pending.age and vanillabp.outbox.dispatch.lag, and the section about a sleeping outbox says which of them answers the case it describes: a backlog above zero which stands still used to need the count from a minute ago, and the age says it in one value. gruelbox is named as the one store which publishes no age. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RYPiyZ32jQQhqYKx44cw23

    @stephanpelikan stephanpelikan committed Sep 21, 2026
  • docs(outbox): the poll interval is a cap, not a rhythm The poller asks its store when the earliest entry it owes something to is due and sleeps until then, so an entry goes out at its due time whatever the interval says. Both platform pages said the opposite, in the property comment and next to the statement which reopens a blocked entry. What the interval still bounds is work a node wrote down before it went away, which is where the cluster page now says why no node wakes another and why a database notification was not the answer. Observability gains the other half: a sleeping poller takes the heartbeat away, so the page says which number tells a quiet system from a stalled one now, and where to look in a thread dump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Re2yjHbaFRvnHyW61E3sao

    @claude claude committed Sep 12, 2026
  • docs(outbox): a start which never happens is blocked and visible Observability gains vanillabp.outbox.blocked, the counter of entries a store gave up on. It needs a row of its own because vanillabp.outbox.pending falls at that very moment: a blocked entry stops waiting, so the gauge an operator watches moves as if the backlog had drained. Starting workflows now says that on a remote BPMS the start finishes after the caller's commit, that the second half can fail with nobody in the application listening, and where to look when it does. The retry curve stays on the platform pages, which the section links to. Both platform pages point the operations duty at the new counter and say which values the error of a blocked entry names. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Re2yjHbaFRvnHyW61E3sao

    @stephanpelikan stephanpelikan committed Sep 11, 2026
  • docs: the cache's own numbers have a name which says which cache One table became two. The first three meters hold whichever cache you use, because VanillaBP counts them around it. The other five belong to the in-memory default and now carry its name, vanillabp.inmemory.election.cache.*, so that a shared cache does not report a size of NaN and an eviction counter which can never leave zero. With such a cache the second table is simply absent, and ended.marks of the first answers the question the size of the marks answered before. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    @stephanpelikan stephanpelikan committed Sep 4, 2026
  • docs: document the discarded outbox counter Version 2.0 counts the schedules the outbox refuses, and the observability page is where an operator looks for what to alarm on. The row alone would not do here: the number says an operation did not happen, not whether that was correct, so the page has to carry the ambiguity and send the reader to the WARN and to the remedy on the correlation page rather than let the counter look like a defect report. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjxJNwTRcKzTmXCwLU7Wi4

    @stephanpelikan stephanpelikan committed Aug 31, 2026
  • docs: every page opens with what to do and carries a table of contents A reader who has never used VanillaBP met the reasoning for a rule before the rule itself, and had no way of telling how far to read before writing a first workflow. The pages now start with the sentence somebody can act on and keep the background where it belongs, further down. Nothing was deleted; what explains a rule moved behind it. Every page gained a numbered table of contents in the shape Home and the Spring Boot page already used, so a reader sees the sections and what each of them answers before scrolling. Where a first heading only repeated the title GitHub shows above the page, it is gone and the page starts with its first sentence. Home is now ordered the way a newcomer needs it, and what VanillaBP is sized for became a page of its own: it answers a question somebody asks before they start, not one they trip over in the middle of the introduction. The architecture picture from the repository's diagrams folder is embedded there, linking to its Excalidraw source. The horizontal rules of the workflow-module pages are gone, the heading is the separator everywhere else. Hints are written as sentences rather than marked with a label, headings sit at one depth per page, and the paragraphs written by hand over the last months were brought to the tone of the rest without changing a single statement they make. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    @stephanpelikan stephanpelikan committed Aug 31, 2026
  • docs: what the delivery record answered, and the push it answers now The observability page gains the counter of the elections the record answered, together with the reason nothing counts the ones which walked: a store which cannot be queried by a task answers nothing, and nothing looks exactly like a task no record was ever written for. A push into the scope of a task is routed from the record as well now, which the task page and the migration page both said was not the case. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XjxJNwTRcKzTmXCwLU7Wi4

    @stephanpelikan stephanpelikan committed Aug 31, 2026
  • docs(delivery): what a concurrent double delivery says, and where it is counted Two deliveries of one task running at the same time both run the handler, which the page Workflow-tasks already said. What it did not say is that you are told: the delivery which finds the record already written logs a WARNING with the task, the workflow, the adapter and the delivery key, and it is counted as `vanillabp.task.redeliveries.concurrent`. The bullet now names both and points at the lock length as the thing which prevents the case. Observability gets the meter in the table, next to its sibling `vanillabp.task.redeliveries.deduplicated`, and the paragraph about a stalled application says how the two differ: the deduplicated one is a repeat which arrived after the work was recorded, the concurrent one arrived too early for that and ran the method again.

    @stephanpelikan stephanpelikan committed Aug 30, 2026
  • docs: adapter-specific notes move to the adapter which owns them A platform page says what every BPMS has to deliver and where they differ; how one BPMS does it is that adapter's wiki. Several pages carried the second kind. Message correlation lost the Camunda 8 section about what a repetition costs. What stays is the rule underneath it: a BPMS may deduplicate on its own, in a window VanillaBP neither sets nor shortens, and whether that happens is on the adapter's wiki. The Camunda 8 wiki carries the detail now, including the log line naming both readings of a refusal. The model-side table keeps one clause per adapter instead of the recipe, the phase-one list keeps the comparison and leaves the reasoning to the Camunda 8 page, which gained the section explaining why the cluster is not asked, and the signal table says what a broadcast reaches rather than which client command sends it. Workflow tasks stops naming the Camunda 8 property behind an overdue task, the Camunda 7 wiring which completes a task too early, and the two version-tag attributes; in all three the message and the adapter's wiki say it. Workflow modules replaces the two bullets about what a BPMS says about a tenant with the rule and a pointer. BPMS migration replaces the Camunda-8 and Camunda-7 prerequisites of a side-by-side setup with what every BPMS is asked and links both. Observability drops two Camunda 8 examples which illustrated platform rules. Aggregate synchronisation keeps the comparison of what ignoring the recommendation costs but links the Camunda 7 page for the serialization format. The comparisons themselves stay, on purpose: which BPMS reports what, what identifies a delivery, what a model needs so it correlates. That is what a reader comes to the platform wiki for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CvgyhjwTEh834mwbptZZxh

    @stephanpelikan stephanpelikan committed Aug 28, 2026
  • docs: a rule says where its decision is written down Five decision logs hold 61 entries, the wikis linked none of them, and 22 of the 42 objections an outside review raised were already answered in one. A reader who wondered why a rule is what it is had no way there short of reading source repositories. So a rule carries a (why) link now, pointing at the numbered entry which decided it. Home says once what the links are and where the logs live, and the form is the same on every page of every wiki: an inline link at the end of the sentence stating the rule. Numbers are handed out once and never reused, so the links keep resolving. The rules the review named are linked first - the outbox on Camunda 7, probing per operation, the two retentions, sharing aggregate values, the Camunda 8 correlation key - and the remaining entries follow wherever a page states their rule. BPMS-adapters also says in one sentence what the module migration-adapter is, which it linked without explaining. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CvgyhjwTEh834mwbptZZxh

    @stephanpelikan stephanpelikan committed Aug 27, 2026
  • Observability: what a start costs, and what stays the same An operator gets the same promise one level up from the gauge cache: a start asks for numbers and asks as many of them on its thousandth boot as on its first, so the seconds a boot spends in VanillaBP today are the seconds it will spend in two years. The one number allowed to grow is the versions a BPMS holds, which grows with deployments rather than with workload, and 'outfaded-versions' is how it gets bounded. Story 138.

    @stephanpelikan stephanpelikan committed Aug 26, 2026
  • docs: looking at a metric is free, and why that needs saying Story 92 follow-up. A gauge is read on every collection and one of them counts rows in a database, so without holding a measurement a dashboard turns watching the outbox into load on it. New section plus the property which decides the window, and the closing section no longer claims the page adds no configuration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K7HLKaJvVpdCiSYxhwHJTc

    @stephanpelikan stephanpelikan committed Aug 20, 2026
  • docs: what an operator gets to see while VanillaBP delivers Story 92. New page listing every meter with the question it answers, the health endpoint per platform and the six MDC keys with a log pattern to paste. The metric which tells a quiet system from a stalled one comes first, because that is the one somebody looks for at three in the morning. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K7HLKaJvVpdCiSYxhwHJTc

    @stephanpelikan stephanpelikan committed Aug 20, 2026