AWS Builder Center
Strong-consistency allocation on Amazon Aurora DSQL with Bedrock and Vercel

Strong-consistency allocation on Amazon Aurora DSQL with Bedrock and Vercel

Sanguine is a blood-unit reservation demo that uses Amazon Aurora DSQL to prevent the same scarce unit from being allocated twice under concurrent demand. The article walks through the database design, Bedrock-powered intake, Vercel API layer, and the surge test that keeps double-promised units at zero.

I created this article for the purposes of entering the H0 Hackathon. #H0Hackathon
Sanguine is a blood-unit reservation network whose core requirement is correctness under concurrency: the same physical unit must never be allocated to two hospitals.
This article walks through how I built that guarantee on Amazon Aurora DSQL, with Amazon Bedrock for natural-language intake and Vercel for the front end and API layer.

Why Amazon Aurora DSQL

I needed four things at once:
  • Strong consistency, so two transactions cannot both claim the same scarce unit
  • A relational model for blood units, requests, allocations, compatibility, and expiry
  • Distributed database infrastructure without managing a traditional cluster
  • A serverless-friendly workflow that could fit a hackathon timeline
Aurora DSQL was a strong fit because the product promise depends on the database itself.
The core requirement is simple:
A blood unit can be promised to one hospital, not two.
Aurora DSQL is strongly consistent and uses optimistic concurrency control. It also does not support sequences, foreign keys, or SELECT ... FOR UPDATE, so I designed the allocation path around those constraints.
Every claim routes through one authoritative blood_units row guarded by a version token, plus a primary key on allocations.unit_id as a storage-level safety net.
When concurrent claims collide, one transaction wins. The other receives a serialization failure, retries, and reroutes to the next compatible unit.

Connecting to Aurora DSQL from serverless functions

Sanguine uses Next.js API routes deployed on Vercel.
Each serverless function connects to Aurora DSQL using short-lived IAM authentication tokens generated with the AWS SDK, then talks to the database through pg.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { DsqlSigner } from "@aws-sdk/dsql-signer";
import { Pool } from "pg";

const signer = new DsqlSigner({
hostname: process.env.DSQL_ENDPOINT,
region: "us-east-1",
});

const pool = new Pool({
host: process.env.DSQL_ENDPOINT,
user: "admin",
database: "postgres",
password: async () => signer.getDbConnectAdminAuthToken(),
ssl: true,
});
That keeps database access token-based instead of relying on a long-lived static password inside the app.

The allocation model

The most important table is intentionally boring:
1
2
3
4
5
6
CREATE TABLE allocations (
unit_id uuid PRIMARY KEY,
request_id uuid NOT NULL,
status text NOT NULL DEFAULT 'held',
allocated_at timestamptz NOT NULL DEFAULT now()
);
The primary key on unit_id is the safety net.
Even if application logic has a bug, the same unit cannot be inserted twice into the confirmed allocation table.
The allocation flow uses FEFO: first-expiring, first-out. It searches for compatible, available, non-expired units, then attempts to hold the soonest-expiring eligible unit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
BEGIN;

SELECT id, version
FROM blood_units
WHERE blood_type = ANY (compatible_types(:type))
AND status = 'available'
AND expires_at > now()
ORDER BY expires_at ASC
LIMIT :n;

UPDATE blood_units
SET
status = 'held',
held_by_request = :request_id,
version = version + 1
WHERE id = :unit_id
AND version = :seen_version
AND status = 'available';

INSERT INTO allocations (unit_id, request_id)
VALUES (:unit_id, :request_id);

COMMIT;
If two facilities race for the same unit, only one transaction can safely commit. The losing request retries, sees that the unit is no longer available, and is rerouted to the next compatible unit.
That is the central behavior Sanguine exists to prove.

Amazon Bedrock for intake

The user-facing request form accepts plain English.
A coordinator can type something like:
We need 4 units of A negative within 72 hours.
Sanguine sends that request to Claude on Amazon Bedrock and asks for strict JSON containing the blood type, unit count, and deadline.
The AI helps with intake, but it does not own the safety guarantee. If the model is unavailable or the response cannot be parsed, the app falls back to a deterministic parser.
That split was important to me:
  • Bedrock improves the user experience
  • Aurora DSQL enforces the correctness guarantee

Well-Architected notes

Security: The application uses IAM-based authentication for Aurora DSQL and scoped permissions for database access and Bedrock invocation. Secrets are kept in environment variables, and database access uses short-lived auth tokens instead of a static password.
Reliability: Correctness is enforced at the database layer. The application can retry failed transactions, but the database prevents double allocation from being persisted.
Operational excellence: The stack keeps operations light: Vercel hosts the front end and API routes, Aurora DSQL handles the relational database layer, and Bedrock handles the natural-language intake step.
Cost awareness: The UI uses lightweight polling of an aggregate endpoint instead of WebSockets. For this demo, that gives the feeling of a live operations console without adding extra infrastructure.
Performance efficiency: Allocation queries are small, targeted, and based on indexed operational fields such as status, blood type, and expiry time.

Result

Under a simulated surge, the legacy path can double-promise a blood unit.
The Aurora DSQL-backed Sanguine path holds double-promised units at zero.
Every value shown in the demo comes from live transactions against the database.
Built for the H0 Hackathon with Amazon Aurora DSQL, Amazon Bedrock, and Vercel. #H0Hackathon
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article