Getting a job referral may seem simple, but managing referrals can become difficult when multiple candidates and employees are involved.
A candidate usually finds a suitable job, identifies someone working at the company, shares their profile, asks for a referral, and waits for a response. On the employee side, handling multiple referral requests can make it difficult to remember previous conversations, decisions, and interactions with the same candidate.
To solve this problem, I built ReferralHub, an application designed to manage the referral process in one place. Candidates can explore job opportunities, check how closely their profile matches a position, and submit referral requests. Employees can review those requests, examine candidate-job matches, and make referral decisions.
The most interesting part of the project was adding persistent memory so that the system could retain useful information from previous interactions.
What ReferralHub Does
ReferralHub has two main types of users: candidates and employees.
Candidates maintain profiles containing details such as their technical skills, experience, projects, preferred roles, and locations.
They can browse available jobs and view the requirements for each position.
For example, a job may require Java, SQL, Spring Boot, and REST APIs.
The system compares these requirements with the candidate's profile and calculates a match percentage. Candidates can also see which skills they already have and which required skills are missing.
If they are interested in the position, they can submit a referral request through the application.
Employees have a dashboard where they can view incoming referral requests, candidate-job matching information, and the current status of each request.
The basic workflow is simple. The more interesting problem is what happens when an employee needs information about a previous interaction with the same candidate.
Why a Database Alone Wasn't Enough
MySQL acts as the transactional database and stores structured application data such as users, candidate profiles, jobs, companies, and referral requests.
This works well when the application needs to answer questions about the current state.
For example:
"What is the candidate's current match percentage?"
or:
"What is the current status of this referral?"
However, some questions require historical context:
"Have this employee and candidate interacted before?"
"What happened during their previous interaction?"
Although these events could also be stored in a relational database, I wanted to introduce a dedicated memory layer that could retain contextual information and retrieve relevant memories when required.
That is where Hindsight comes into the architecture.
Adding Hindsight as a Memory Layer
I integrated Hindsight with the Spring Boot backend as a separate memory service.
The architecture keeps transactional information in MySQL while using Hindsight to store and retrieve contextual information.
The two systems have different responsibilities. MySQL handles the current and structured application state, while Hindsight handles relevant historical context.
I created a dedicated HindsightService in the backend to manage memory operations.
The retention process stores relevant information in the appropriate memory scope, while the recall process searches for previously stored context based on a query.
I also separated memory into different scopes, such as candidate, employee, and job context. This helps keep memories organized and makes retrieval more relevant.
The Before and After
The main difference becomes clear when comparing the referral workflow before and after introducing the memory layer.
Before Memory
Suppose an employee receives a referral request.
The application can provide information such as:
80% profile match
Matched skills
Missing skills
Current referral status
However, the application may not know whether the employee has previously interacted with that candidate.
The employee would have to rely on their own memory or search through previous conversations.
After Adding Memory
Now suppose the candidate has previously interacted with the same employee.
When the employee opens the referral request, the application can retrieve relevant information from Hindsight.
The employee can therefore access useful context from the previous interaction instead of starting from the current referral request alone.
This changes the type of questions the application can answer.
Instead of only answering:
"What is happening now?"
it can also help answer:
"What relevant information do we already have about this interaction?"
That is where the memory layer becomes valuable.
A Complete Referral Workflow
A typical ReferralHub workflow looks like this:
Discover Job
↓
Calculate Profile Match
↓
Request Referral
↓
Store Referral in MySQL
↓
Retain Relevant Context
↓
Employee Reviews Request
↓
Recall Previous Context
↓
Employee Makes Referral Decision
The candidate first logs in and views their profile.
They then select a job, and the system compares their skills with the job requirements.
For example:
AI Match: 70%
Matched:
Java
Missing:
Spring Boot
SQL
If the candidate wants to proceed, they submit a referral request.
The backend stores the referral information in MySQL and can also retain relevant contextual information through the Hindsight integration.
The employee can then review the request, examine the candidate's match information, and retrieve relevant historical context when needed.
Finally, the employee can decide whether to refer or decline the candidate.
Why I Kept MySQL and Hindsight Separate
One important architectural decision was to keep MySQL and Hindsight responsible for different types of information.
I did not want Hindsight to replace the application's transactional database.
For example, a referral request can have a well-defined status:
PENDING
REFERRED
DECLINED
This structured state belongs in MySQL.
Memory is different.
Information such as previous interactions, contextual details surrounding a decision, or information that may become useful later is better suited to a dedicated memory layer.
Therefore, the architecture follows this separation:
MySQL → Current and structured application state
Hindsight → Historical and contextual memory
This separation makes the responsibilities of each component easier to understand and maintain.
What I Learned
One of the biggest lessons from this project was that simply adding a memory system does not automatically make an application better.
Memory is useful when it solves a real problem within the workflow.
Referral systems are a good example because candidates and employees may interact multiple times, making historical context valuable.
Another important lesson was the importance of memory scope.
Candidate-related information, employee-related information, and job-related information may serve different purposes. Keeping these contexts separate can make memory retrieval more targeted.
I also found that demonstrating a clear before-and-after experience makes the value of memory easier to understand.
Instead of simply showing that a memory service has been integrated, it is more useful to demonstrate how the application behaves without historical context and how the experience changes when relevant context can be recalled.
The main takeaway is:
The purpose of memory is not simply to store more information. It is to make useful information available when it is needed.
What's Next
ReferralHub currently focuses on the core referral workflow: candidate profiles, job discovery, profile-job matching, referral requests, employee decisions, and contextual memory.
There are several ways the system could be extended.
For example, future versions could use repeated referral interactions to provide richer candidate context or help employees identify patterns across previous interactions.
The central idea remains the same:
A referral interaction shouldn't always have to start from scratch.
By combining a transactional database with a persistent memory layer, ReferralHub can maintain both the current state of a referral and the context surrounding previous interactions.
For me, the most interesting part of building the system was seeing how persistent memory can become useful when it actually changes what happens during the next interaction.
Top comments (0)