Consume Extracted Data
Once RAISE processes a resume, the extracted candidate profile is available in one or both
output destinations depending on your OUTPUT_TARGET configuration:
- SQS Output Queue (
CVExtractorQueue) — for event-driven downstream consumers - DynamoDB Table (
CVExtractorTable) — for direct querying and analysis
SQS Message Schema
Every message published to the output queue follows the CandidateProfileCreated schema.
See the Candidate Profile Schema page for the full field
reference. A representative example is shown below:
{
"id": "uuid",
"fileName": "resumes/john-doe.pdf",
"timestamp": "2026-03-15T10:00:00.000Z",
"analysisResult": {
"candidateProfile": {
"fullName": "Jane Doe",
"email": "jane.doe@example.com",
"phoneNumber": "+27 82 123 4567",
"location": "Cape Town, South Africa",
"professionalSummary": "...",
"workExperience": [
{
"companyName": "Acme Corp",
"position": "Software Engineer",
"startDate": "2020-01",
"endDate": "2024-12",
"isCurrentPosition": false,
"responsibilities": ["Built APIs", "Led team of 3"]
}
],
"education": [
{
"institution": "University of Cape Town",
"qualification": "BSc Computer Science",
"fieldOfStudy": "Computer Science",
"year": "2019"
}
],
"skills": [{ "skill": "TypeScript" }, { "skill": "AWS" }],
"certifications": [{ "certification": "AWS Solutions Architect", "year": "2022" }]
}
}
}
Consuming from SQS
- Node.js
- Python
- Java (Spring Boot)
- Go
- C#
import {
SQSClient,
ReceiveMessageCommand,
DeleteMessageCommand,
} from "@aws-sdk/client-sqs";
const client = new SQSClient({ region: "us-east-1" });
const queueUrl = "YOUR_OUTPUT_QUEUE_URL";
async function poll() {
while (true) {
const { Messages = [] } = await client.send(new ReceiveMessageCommand({
QueueUrl: queueUrl,
MaxNumberOfMessages: 10,
WaitTimeSeconds: 20, // long polling
}));
for (const message of Messages) {
const profile = JSON.parse(message.Body);
console.log("Received:", profile.analysisResult.candidateProfile.fullName);
// process the profile ...
await client.send(new DeleteMessageCommand({
QueueUrl: queueUrl,
ReceiptHandle: message.ReceiptHandle,
}));
}
}
}
poll();
import json
import boto3
sqs = boto3.client("sqs", region_name="us-east-1")
queue_url = "YOUR_OUTPUT_QUEUE_URL"
def poll():
while True:
response = sqs.receive_message(
QueueUrl=queue_url,
MaxNumberOfMessages=10,
WaitTimeSeconds=20, # long polling
)
for message in response.get("Messages", []):
profile = json.loads(message["Body"])
candidate = profile["analysisResult"]["candidateProfile"]
print(f"Received: {candidate['fullName']}")
# process the profile ...
sqs.delete_message(
QueueUrl=queue_url,
ReceiptHandle=message["ReceiptHandle"],
)
poll()
// pom.xml dependency:
// <artifactId>spring-cloud-starter-aws-messaging</artifactId>
import io.awspring.cloud.sqs.annotation.SqsListener;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
@Service
public class ResumeConsumerService {
private final ObjectMapper objectMapper;
public ResumeConsumerService(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@SqsListener("${raise.output-queue-url}")
public void onMessage(String body) throws Exception {
CandidateProfileCreated event = objectMapper.readValue(body, CandidateProfileCreated.class);
String name = event.getAnalysisResult().getCandidateProfile().getFullName();
System.out.println("Received: " + name);
// process the profile ...
}
}
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sqs"
)
type CandidateProfile struct {
FullName string `json:"fullName"`
Email string `json:"email"`
}
type Message struct {
AnalysisResult struct {
CandidateProfile CandidateProfile `json:"candidateProfile"`
} `json:"analysisResult"`
}
func main() {
cfg, _ := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-east-1"))
client := sqs.NewFromConfig(cfg)
queueURL := "YOUR_OUTPUT_QUEUE_URL"
for {
out, _ := client.ReceiveMessage(context.TODO(), &sqs.ReceiveMessageInput{
QueueUrl: &queueURL,
MaxNumberOfMessages: 10,
WaitTimeSeconds: 20,
})
for _, msg := range out.Messages {
var m Message
json.Unmarshal([]byte(*msg.Body), &m)
fmt.Println("Received:", m.AnalysisResult.CandidateProfile.FullName)
// process the profile ...
client.DeleteMessage(context.TODO(), &sqs.DeleteMessageInput{
QueueUrl: &queueURL,
ReceiptHandle: msg.ReceiptHandle,
})
}
}
}
using Amazon.SQS;
using Amazon.SQS.Model;
using System.Text.Json;
var client = new AmazonSQSClient(Amazon.RegionEndpoint.USEast1);
var queueUrl = "YOUR_OUTPUT_QUEUE_URL";
while (true)
{
var response = await client.ReceiveMessageAsync(new ReceiveMessageRequest
{
QueueUrl = queueUrl,
MaxNumberOfMessages = 10,
WaitTimeSeconds = 20,
});
foreach (var message in response.Messages)
{
var payload = JsonDocument.Parse(message.Body);
var name = payload.RootElement
.GetProperty("analysisResult")
.GetProperty("candidateProfile")
.GetProperty("fullName")
.GetString();
Console.WriteLine($"Received: {name}");
// process the profile ...
await client.DeleteMessageAsync(queueUrl, message.ReceiptHandle);
}
}
Reading from DynamoDB
If OUTPUT_TARGET is DYNAMODB or BOTH, extracted profiles are stored in CVExtractorTable
with id (UUID) as the partition key.
- Node.js
- Python
- Java
- Go
- C#
import { DynamoDBClient, ScanCommand, GetItemCommand } from "@aws-sdk/client-dynamodb";
import { unmarshall } from "@aws-sdk/util-dynamodb";
const client = new DynamoDBClient({ region: "us-east-1" });
const tableName = "YOUR_TABLE_NAME";
// Fetch a single profile by ID
async function getProfile(id) {
const { Item } = await client.send(new GetItemCommand({
TableName: tableName,
Key: { id: { S: id } },
}));
return Item ? unmarshall(Item) : null;
}
// Scan all profiles (use sparingly on large tables)
async function listProfiles() {
const { Items = [] } = await client.send(new ScanCommand({
TableName: tableName,
}));
return Items.map(unmarshall);
}
import boto3
from boto3.dynamodb.conditions import Key
dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
table = dynamodb.Table("YOUR_TABLE_NAME")
# Fetch a single profile by ID
def get_profile(profile_id):
response = table.get_item(Key={"id": profile_id})
return response.get("Item")
# Scan all profiles (use sparingly on large tables)
def list_profiles():
response = table.scan()
return response.get("Items", [])
DynamoDbClient dynamo = DynamoDbClient.builder().region(Region.US_EAST_1).build();
// Fetch a single profile by ID
Map<String, AttributeValue> key = Map.of(
"id", AttributeValue.fromS("YOUR_PROFILE_ID")
);
GetItemResponse response = dynamo.getItem(GetItemRequest.builder()
.tableName("YOUR_TABLE_NAME")
.key(key)
.build());
Map<String, AttributeValue> item = response.item();
String fullName = item.get("fullName").s();
System.out.println("Found: " + fullName);
cfg, _ := config.LoadDefaultConfig(context.TODO(), config.WithRegion("us-east-1"))
client := dynamodb.NewFromConfig(cfg)
out, _ := client.GetItem(context.TODO(), &dynamodb.GetItemInput{
TableName: aws.String("YOUR_TABLE_NAME"),
Key: map[string]types.AttributeValue{
"id": &types.AttributeValueMemberS{Value: "YOUR_PROFILE_ID"},
},
})
var profile map[string]interface{}
attributevalue.UnmarshalMap(out.Item, &profile)
fmt.Println("Found:", profile["fullName"])
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
var client = new AmazonDynamoDBClient(Amazon.RegionEndpoint.USEast1);
var response = await client.GetItemAsync(new GetItemRequest
{
TableName = "YOUR_TABLE_NAME",
Key = new Dictionary<string, AttributeValue>
{
{ "id", new AttributeValue { S = "YOUR_PROFILE_ID" } }
}
});
var fullName = response.Item["fullName"].S;
Console.WriteLine($"Found: {fullName}");