Giving Our HRMS Chatbot a Memory — Without Keeping It Forever

Imagine an employee asking the HRMS chatbot:
“How many leave days do I have?” Then the chatbot responds.
A few minutes later, they close the chatbot to check something else in the system.
When they open it again, they naturally expect the conversation to still be there.
But at the same time, do we really need to permanently store every chatbot
conversation in our database?
That question became an interesting design challenge while working on our HRMS
project.
Instead of creating a separate DynamoDB table just to store temporary chatbot
conversations, I implemented a browser session-based chat history system. The idea
was simple:
"Let the chatbot remember the conversation while the employee needs it — but
don't keep it forever."
If Chatbot Forgot Too Quickly
Our HRMS includes an AI-powered chatbot designed to help employees interact with
the system and get answers to HR-related questions and database related questions.
The chatbot could already send employee questions to our backend, process them
using Amazon Bedrock, and return an AI-generated response.
However, there was one usability problem.
Suppose an employee had a conversation like this:
Employee:
“How many annual leave days do I have?”
Chatbot:
“You have 12 annual leave days available.”
Then the employee closes the chatbot window.
When they open it again, the conversation is gone. From the employee's perspective,
this feels like the chatbot has completely forgotten what they were talking about. We
wanted to solve this problem, but another question came up:
"Should we create a database table to permanently store every chatbot message?"
For our use case, the answer was no.
Why We Didn't Need a Separate Chat History Table
A database is useful when information needs to be stored permanently and accessed
later.
For example, our HRMS stores important employee information, attendance records,
leave information, and other business data in persistent storage.
But chatbot conversations are different.
The chat history in our case is mainly useful for continuing a conversation during the
employee's current session. We didn't need employees to return several days later and
retrieve an old chatbot conversation.
Creating a separate DynamoDB table would therefore introduce additional complexity:
More database records to manage
Additional storage requirements
More read/write operations
Additional backend logic
More data that needs to be managed and eventually deleted
So instead of asking the database to remember something temporary, we decided to let
the browser handle the temporary memory.
That led us to use a sessionStorage.

A Temporary Memory Inside the Browser
Every modern browser provides a storage mechanism called sessionStorage. We used
it as a temporary notepad for the chatbot.
The concept is straightforward:
Employee
↓
Opens Chatbot
↓
useChatSession checks sessionStorage
↓
Previous messages found?
Yes → Load conversation
No → Show welcome message
↓
Employee sends message
↓
Save message to sessionStorage
↓
AI generates response
↓
Save bot response to sessionStorage
The important part is that the conversation doesn't need to travel to DynamoDB just to
be displayed again a few minutes later.
The browser can take care of it. This means the browser handles the temporary chat
history while the backend remains responsible for the actual AI processing.
Giving Each Employee Their Own Chat Session
There was another important requirement.
Imagine Ashan logs into the HRMS and has a conversation with the chatbot.
Later, another employee, Thulani, logs in using the same browser.
Thulani should never see Ashan's conversation.
To handle this, we used the employee's unique user ID as part of the storage key.
For example:
chatbot_session_ashan-123-abc
and
chatbot_session_thulani-456-xyz
These are two completely different storage keys.
So when Ashan opens the chatbot, the application looks for:
chatbot_session_ashan-123-abc
When Thulani opens it, the application looks for:
chatbot_session_thulani-456-xyz
This gives each employee an isolated client-side chat session.
How the Chat Session Works
The session management is handled through a custom React hook called
useChatSession.
When the chatbot opens, the hook checks whether a conversation already exists:
const storageKey = `${STORAGE_KEY_PREFIX}${userId}`;
const storedMessages = sessionStorage.getItem(storageKey);
if (storedMessages) {
const parsed = JSON.parse(storedMessages);
const hydrated = parsed.map((msg: any) => ({
...msg,
timestamp: new Date(msg.timestamp),
}));
If a conversation exists, it is loaded into the chatbot.
When the employee sends a message, the message is added to the chat and stored in
sessionStorage. Once the AI response is received from Amazon Bedrock, the chatbot
response is also added and stored.
The browser therefore maintains a structure similar to:
[
{
"text": "What is the leave policy?",
"sender": "user"
},
{
"text": "Our leave policy allows...",
"sender": "bot"
}
]
The employee's messages and the chatbot's responses are kept together in their
original order, So when the employee opens the chatbot again, the stored messages are
loaded and the conversation can continues from where they left off.
Giving Employees Control
We also added a Clear Chat option.
If an employee wants to start a completely new conversation, they can manually clear
their history.
The stored session is removed using:
sessionStorage.removeItem(storageKey);
The chatbot then returns to its initial welcome message.
So employees have two choices:
Continue chatting → Previous messages remain available.
Clear chat → Start a fresh conversation.
What Happens When the Employee Logs Out?
Logout acts as the end of the chatbot session.
When the employee logs out, the session storage is cleared before completing the logout process:
sessionStorage.clear();
await signOut();
Therefore, when the employee logs in again, the previous chatbot conversation is no
longer available.
This gives the chatbot a clear lifecycle:
Login
↓
Start conversation
↓
Close / reopen chatbot
↓
Continue conversation
↓
Clear manually or log out or close the tab
↓
Conversation removed
The browser tab's session also provides the natural boundary for temporary storage. ( If
user close tab it also lead to remove history)
Seeing the Chat History in the Browser
One useful part of implementing this feature was being able to inspect the stored
conversation directly.
In Chrome DevTools:
Application → Session Storage → HRMS Website
we can find a key such as:
chatbot_session_ashan-123-abc
Its value contains the conversation as JSON.
Why This Was the Right Choice for Our HRMS
The goal wasn't to build a permanent chatbot history system. We only needed
temporary conversational continuity.
Using sessionStorage allowed us to achieve that without introducing another database
table.
It gave us:
Better user experience — conversations remain when the chatbot is closed and reopened.
Less database complexity — no separate DynamoDB table for temporary messages.
Reduced backend operations — temporary history doesn't require database reads and writes.
User control — employees can clear their history whenever they want.
Session-based cleanup — conversations don't remain indefinitely.
User isolation — each employee has a separate storage key.
The Lesson Behind a Small Feature
This feature taught me an important lesson about software architecture:
Not every piece of data needs to be stored permanently.
When designing a system, it's easy to think that everything should go into the database.
But the right storage solution depends on how long the data needs to live and what
it is actually used for.
Our chatbot didn't need long-term memory. It only needed to remember the
conversation while the employee was using the system. So instead of adding another
database layer, we gave the chatbot a temporary memory inside the browser.
It was a relatively small contribution to our HRMS, but it improved the chatbot
experience while keeping the architecture simpler.
Sometimes, the best solution isn't the one that is more complex - it's the one that
focus about what we actually need.
