
Building a Blockchain-Integrated Backend Using Node.js, TypeScript, and AWS
Learn how to build a scalable blockchain-integrated backend using Node.js, TypeScript, Ethereum, and AWS. Explore smart contracts, secure transaction processing, asynchronous workers, Docker deployment, and cloud architecture for reliable decentralized applications.
1. Introduction
Blockchain technology is transforming how applications store, verify, and share information. While traditional databases provide fast and efficient data management, blockchain introduces transparency, immutability, and decentralized verification.
However, integrating blockchain into a real-world backend application introduces several challenges:
- Blockchain transactions take time to confirm.
- Transaction fees fluctuate depending on network conditions.
- Private keys must be securely managed.
- Blockchain networks may become temporarily unavailable.
- Applications must handle failed transactions and network interruptions.
Combining Node.js, TypeScript, Ethereum, and Amazon Web Services (AWS) provides a practical architecture for addressing these challenges.
In this article, we will explore how to design a blockchain-integrated backend that uses traditional databases for application data and blockchain for verifiable transaction history.
2. Understanding the Technology Stack
Before implementing the architecture, let's understand the technologies involved.
Node.js
Node.js is a JavaScript runtime commonly used for building scalable backend applications.
Its asynchronous programming model makes it suitable for handling API requests, database operations, and blockchain interactions.
TypeScript
TypeScript extends JavaScript with static typing.
It helps developers build maintainable applications by identifying many type-related errors during development.
Ethereum Blockchain
Ethereum is a decentralized blockchain platform that supports smart contracts.
Smart contracts are programs deployed on a blockchain that execute according to predefined rules.
We will use Ethereum to maintain an append-only history of application operations.
Amazon Web Services
AWS provides managed cloud infrastructure for deploying, operating, and scaling backend applications.
Our architecture uses several AWS services:
| AWS Service | Purpose |
|---|---|
| Amazon ECS with AWS Fargate | Run containerized backend services |
| Amazon RDS for PostgreSQL | Store application data |
| Amazon SQS | Queue blockchain transaction jobs |
| AWS Secrets Manager | Store sensitive configuration and signing keys |
| Amazon ECR | Store Docker images |
| Amazon CloudWatch | Monitor application logs and metrics |
3. Designing the System Architecture
Consider a task management application where users can create, update, and delete tasks.
The application stores task details in PostgreSQL, while a smart contract records a minimal history of important task operations.
The architecture follows this flow:
Client → Node.js API → PostgreSQL → Transactional Outbox → Amazon SQS → Blockchain Worker → Ethereum Smart Contract
Each component has a specific responsibility.
Node.js API: Handles incoming HTTP requests, authentication, validation, and business logic.
PostgreSQL: Stores task information and durable blockchain submission records.
Amazon SQS: Delivers asynchronous transaction jobs to background workers.
Blockchain Worker: Processes queued jobs, signs transactions, submits them to Ethereum, and monitors confirmations.
Ethereum Smart Contract: Stores a minimal, verifiable history of task operations.
The most important architectural decision is separating normal application operations from blockchain transaction processing.
Users should not have to wait for blockchain confirmation before receiving a response to a normal task operation.
4. Setting Up the Node.js and TypeScript Backend
First, create a Node.js project.
1
2
3
4
mkdir blockchain-backend
cd blockchain-backend
npm init -yInstall the required dependencies:
1
2
3
4
npm install express viem dotenv zod
npm install -D typescript tsx \
@types/node @types/expressInitialize TypeScript:
1
npx tsc --initCreate the following project structure:
1
2
3
4
5
6
7
8
9
10
11
12
13
blockchain-backend/
├── src/
│ ├── api/
│ ├── blockchain/
│ ├── config/
│ ├── database/
│ ├── queue/
│ ├── workers/
│ └── index.ts
├── contracts/
├── Dockerfile
├── package.json
└── tsconfig.jsonThis structure separates application responsibilities and makes the codebase easier to maintain.
5. Creating an Ethereum Smart Contract
We will create a simple Solidity smart contract that records task actions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract TaskHistory {
address public immutable writer;
enum Action {
Created,
Updated,
Deleted
}
struct TaskRecord {
bytes16 taskId;
Action action;
uint64 timestamp;
}
mapping(bytes16 => TaskRecord[]) private history;
event TaskActionRecorded(
bytes16 indexed taskId,
Action action,
uint64 timestamp
);
constructor(address authorizedWriter) {
require(
authorizedWriter != address(0),
"Invalid writer"
);
writer = authorizedWriter;
}
function recordAction(
bytes16 taskId,
Action action
) external {
require(msg.sender == writer, "Unauthorized");
require(taskId != bytes16(0), "Invalid task");
uint64 recordedAt = uint64(block.timestamp);
history[taskId].push(
TaskRecord(taskId, action, recordedAt)
);
emit TaskActionRecorded(
taskId,
action,
recordedAt
);
}
function getHistoryCount(
bytes16 taskId
) external view returns (uint256) {
return history[taskId].length;
}
}This smart contract provides three important features:
- Only the authorized writer can record task operations.
- Each task action is permanently appended to its history.
- An event is emitted whenever a new action is recorded.
The contract intentionally avoids storing names, email addresses, task descriptions, or other personal information.
Important: Task identifiers and transaction metadata are still publicly observable on Ethereum. Production applications should use privacy-safe identifiers that cannot easily be linked to individuals.
For production use, additional validation, bounded pagination, and comprehensive smart contract security testing are recommended.
6. Connecting Node.js to Ethereum
The
viem library provides TypeScript-friendly tools for interacting with Ethereum.Create a blockchain client:
1
2
3
4
5
6
7
8
9
import { createPublicClient, http } from "viem";
import { sepolia } from "viem/chains";
export const publicClient = createPublicClient({
chain: sepolia,
transport: http(
process.env.ETHEREUM_RPC_URL
),
});This client communicates with an Ethereum RPC endpoint.
For development and testing, we can use the Sepolia test network.
Sepolia allows developers to test smart contract interactions without spending real ETH.
A simple connection check:
1
2
3
4
const blockNumber =
await publicClient.getBlockNumber();
console.log("Current block:", blockNumber);This confirms that the application can communicate with the configured blockchain network.
In production, RPC failures should be handled with timeouts, retries, and appropriate monitoring.
7. Implementing Asynchronous Blockchain Processing
One of the biggest mistakes in blockchain-integrated applications is performing blockchain transactions directly inside HTTP request handlers.
Consider the following approach:
1
2
3
4
5
6
7
8
9
User creates task
↓
Save task
↓
Send blockchain transaction
↓
Wait for confirmation
↓
Return API responseThis approach introduces unnecessary delays.
Blockchain confirmation can take significantly longer than a normal database operation.
A better solution is asynchronous processing.
1
2
3
4
5
6
7
8
9
10
11
12
13
User creates task
↓
Save task and outbox event
↓
Return API response
↓
Publish event to Amazon SQS
↓
Background worker processes event
↓
Submit blockchain transaction
↓
Monitor confirmationWhy use Amazon SQS?
Amazon Simple Queue Service (SQS) provides managed message queuing.
It helps decouple the API from background processing.
Benefits include:
- Independent scaling of API and worker services.
- Retry handling for temporarily failed operations.
- Dead-letter queues for repeatedly failing messages.
- Improved resilience during blockchain RPC outages.
Ensuring reliable event delivery
Saving application data and publishing an SQS message are separate operations.
If the database update succeeds but message publishing fails, the blockchain event could be lost.
The Transactional Outbox Pattern addresses this problem.
Within a single PostgreSQL transaction:
- Save the task modification.
- Insert a corresponding event into an outbox table.
- Commit both changes together.
A separate publisher reads the outbox and sends events to SQS.
This ensures that a committed task operation has a durable record of the blockchain work that must be performed.
Because SQS standard queues can deliver messages more than once, workers must implement idempotency to prevent duplicate processing.
8. Managing Blockchain Transactions Safely
Blockchain transaction processing requires more than submitting a transaction.
A reliable worker should track each transaction through its lifecycle.
Common states include:
Pending: The operation is waiting to be submitted.
Submitted: The transaction has been broadcast to the blockchain network.
Confirmed: The transaction has been included in a block and has reached the application's required confirmation threshold.
Replaced: Another transaction using the same account nonce has replaced the original transaction.
Abandoned: The application has stopped automatic processing and requires investigation or a defined recovery procedure.
Transaction nonce management
Every Ethereum transaction from an externally owned account uses a nonce.
If multiple workers submit transactions using the same signing account, they must coordinate nonce allocation.
Without coordination, workers may accidentally submit conflicting transactions.
A production implementation should use durable nonce coordination or a controlled single-writer transaction submission service.
Blockchain reorganizations
A blockchain reorganization occurs when the network changes which blocks are considered canonical.
Applications should avoid treating initial block inclusion as permanent finality.
Instead, they should wait for an appropriate confirmation threshold and handle reorganizations when rebuilding transaction history.
9. Securing Private Keys with AWS Secrets Manager
Private keys are among the most sensitive assets in blockchain applications.
Anyone who obtains a signing private key may be able to submit transactions and control assets associated with that account.
Never store private keys in:
- Git repositories.
- Docker images.
- Application logs.
- Public configuration files.
- Database records that do not require them.
AWS Secrets Manager can securely store signing credentials.
The blockchain worker can retrieve the secret using an IAM role with narrowly scoped permissions.
Only the worker service should have access to the signing key.
For stronger protection, consider signing architectures backed by AWS KMS or specialized key-management systems, depending on the blockchain and signing requirements.
AWS Secrets Manager protects stored secrets but does not, by itself, prevent a compromised worker from accessing a key that the worker is authorized to retrieve.
10. Deploying the Application on AWS
After developing and testing the application locally, we can deploy the backend to AWS.
Step 1: Containerize the application
Create a Dockerfile for the Node.js application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM node:24-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV NODE_ENV=production
CMD ["node", "dist/index.js"]This is a simplified example. A production image should use a multi-stage build, a non-root user, and only the dependencies required at runtime.
Step 2: Push the Docker image to Amazon ECR
Amazon Elastic Container Registry stores Docker images.
After creating an ECR repository and authenticating Docker, tag and push the image:
1
2
3
4
5
docker tag blockchain-backend:latest \
<account-id>.dkr.ecr.<region>.amazonaws.com/blockchain-backend:latest
docker push \
<account-id>.dkr.ecr.<region>.amazonaws.com/blockchain-backend:latestReplace the placeholders with your AWS account ID and Region.
Step 3: Deploy with Amazon ECS and Fargate
Amazon ECS manages container workloads, while AWS Fargate provides serverless compute capacity for containers.
Create separate ECS services for:
- Node.js API
- Outbox publisher
- Blockchain transaction worker
Separating these services allows them to scale independently.
The API can scale based on incoming traffic, while workers can scale according to queue depth and transaction-processing requirements.
Step 4: Configure supporting services
Provision:
- Amazon RDS for PostgreSQL.
- Amazon SQS with an appropriate dead-letter queue.
- AWS Secrets Manager for sensitive credentials.
- Amazon CloudWatch for logs and metrics.
- An Application Load Balancer for public API traffic.
Keep PostgreSQL and workers in private subnets where possible.
Configure IAM permissions, security groups, outbound connectivity, and TLS appropriately.
Remember that AWS resources such as Fargate tasks, RDS databases, load balancers, and network infrastructure can generate charges even during testing.
11. Monitoring and Reliability
Deploying an application is only the beginning.
A production backend must be observable and recoverable.
Amazon CloudWatch can help monitor application behavior.
Useful metrics include:
- API request latency.
- API error rates.
- SQS queue depth.
- Age of the oldest queued message.
- Blockchain transaction submission failures.
- Pending transaction count.
- Blockchain confirmation latency.
- Worker restart frequency.
Developers should also configure alarms for abnormal conditions.
For example, if the blockchain worker stops processing messages, the SQS queue depth may continue increasing.
A CloudWatch alarm can help operators detect the issue before it becomes a major service disruption.
Testing failure scenarios
Before production deployment, test:
- Ethereum RPC endpoint unavailable.
- SQS message delivered more than once.
- Worker crashes after broadcasting a transaction.
- Transaction remains pending for an extended period.
- Signing credentials are unavailable.
- PostgreSQL temporarily loses connectivity.
- Blockchain reorganization affects a recorded transaction.
These scenarios help verify that the application can recover without losing committed business operations or producing duplicate blockchain records.
12. Best Practices
When building blockchain-integrated applications, follow these principles:
Keep sensitive data off-chain. Public blockchains are not appropriate for storing private application information.
Use asynchronous processing. Do not block ordinary API requests while waiting for blockchain confirmations.
Implement idempotency. Assume messages may be delivered more than once and workers may restart unexpectedly.
Protect signing credentials. Apply least-privilege IAM permissions and avoid exposing private keys.
Monitor transaction lifecycles. Track submission, confirmation, replacement, and failure states.
Design for blockchain outages. Temporary RPC failures should not unnecessarily prevent normal application operations.
Test recovery procedures. Verify that workers can safely resume processing after crashes and restarts.
Control cloud costs. Monitor AWS usage and remove unused development resources.
13. Conclusion
Building a blockchain-integrated backend requires more than connecting a Node.js application to a smart contract.
A reliable solution must combine traditional backend engineering principles with blockchain-specific transaction handling.
Node.js and TypeScript provide a maintainable foundation for backend development. PostgreSQL handles application data efficiently, while Ethereum provides a publicly verifiable record of selected operations.
AWS services such as Amazon ECS, Amazon SQS, Amazon RDS, AWS Secrets Manager, and Amazon CloudWatch provide the infrastructure needed to deploy, scale, secure, and monitor the application.
The most important lesson is that blockchain should complement the backend architecture rather than replace traditional databases or business logic.
By combining asynchronous processing, durable event storage, secure signing, transaction monitoring, and cloud infrastructure, developers can build blockchain-integrated applications that remain responsive and resilient even when blockchain networks experience delays or temporary failures.
This architecture provides a foundation for applications such as audit trails, supply-chain tracking, asset management, and other systems requiring verifiable records.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article