Designing a Change History for a Business Web App
Choose events, actors, objects, results, and access rules so your team can trace business decisions without collecting unnecessary information.

A request changes from pending to approved. A week later, somebody asks who changed it and what supported the decision. If the application stores only the latest state, the team may have to search through incomplete conversations.
A change history can answer these questions when it follows the business process. Establish its purpose during web app planning: which events need tracing, who needs the information, and how those records support everyday work.
Start with operational questions
Collect real questions from users. When was a request returned? Who changed its owner? Why was an order cancelled? These questions provide a better starting point than wanting to record every activity without a defined purpose.
Choose events that change the meaning of the work. Opening a page and approving a request are different actions. Technical activity may be necessary for operating the system, but a business history does not need to display every network request behind the interface.
For each event, describe the decision its record can support. A cancellation record might tell an operator whether work should stop. If there is no clear reader or decision, reconsider why that information needs collecting.
Make each event understandable
Use consistent elements: event time, actor identity, object, action, result, and a reason when the process requires one. The OWASP logging guidance discusses event information and limits on sensitive data. Select what is needed rather than recording the maximum possible detail.
A fictional example: “Request PR-017 was returned by the reviewer on October 7 because its requirements were incomplete.” This identifies the object and action. A display name helps readers, while a stable account identifier helps the system retain the relationship when that name changes.
Distinguish event time from the time its record was received when those can differ. Define the time zone in the data contract and show a time users understand. Ambiguous ordering can make two actions appear contradictory even when they happened at different moments.
Choose which changes to show
For some fields, the previous and new values explain the change. Responsibility moving from team A to team B is one example. For other fields, recording that a change happened may be enough without copying the entire contents into the history.
Select fields deliberately. Do not automatically record passwords, tokens, or private document contents just because they belong to the updated object. Information needed on the main screen does not necessarily belong in a record accessible to more people.
If reasons use free text, explain their purpose to operators. Ask for work-related reasons rather than unnecessary personal information. Consider how to handle typing mistakes and inaccurate information without casually removing the trace of an earlier decision.
Distinguish an attempt from a successful result
A user may try to approve a request, only for the action to be rejected because its status has changed. If that attempt is recorded, its result must be clear. An entry saying “approved” without a result can incorrectly imply that a change succeeded.
Separate the main update from subsequent work. Approval may succeed while its notification remains pending. Operators need the correct business state; system maintainers may need notification-delivery details in a separate operational record.
Agree what happens if recording fails. Should the main action wait, or is there a suitable recovery mechanism? The answer follows the process risk. Do not conceal gaps behind an interface that appears complete without checking whether it actually is.
Design access and ways to investigate
Someone allowed to change an object may not be allowed to read the organisation’s entire history. Connect access to roles and data scope. Use an access-control matrix to discuss who may view, search, or export records.
Provide filters that answer the original questions: object, time range, action, or actor. Avoid an unexplained long list. When a user opens history from a request, make its relationship with that request apparent.
Decide who handles questions when a record looks inconsistent. A history that is easy to find but has no owner for follow-up can still leave work stalled. A clarification path belongs in the user experience as well as the storage design.
Decide retention and format changes
History has a lifecycle. NIST SP 800-92 provides context for log management; your application’s retention requirements still need decisions based on its use and the rules applying to the process.
Document who owns retention decisions, archive access, and permitted correction or deletion procedures. Avoid choosing a generic retention period without an operational reason. An archive that nobody can read no longer supports investigation.
When action names or data formats change, preserve the ability to interpret earlier records. Record a structure version if needed. Test examples from before and after the change so an interface update does not erase the meaning of the history.
Test one complete sequence of work
Use sample data: create a request, change its owner, return it for revision, and approve it. Check whether a reader can explain the sequence without a developer’s help. Add one rejected attempt to ensure it cannot be confused with success.
Also check different users’ access, searches, and any supported exports. Aim for a useful, understandable history with an appropriate scope. Bring this example when discussing a web app’s development or maintenance with Creatyf.


