
Building a Risk-Controlled Crypto Arbitrage Platform on AWS EC
nstead of building a simple “buy low, sell high” bot, the goal is to create a risk-controlled platform that starts with market analysis and paper trading, while keeping live trading optional and locked behind explicit safety checks.
BB-Arbitrage: Building a Risk-Controlled Crypto Arbitrage Platform on AWS EC2
BB-Arbitrage : Crypto Arbitrage Plateform Architecture on AWS
A practical walkthrough for building, containerizing, deploying, and monitoring a crypto arbitrage platform on AWS.
Crypto arbitrage sounds simple: buy an asset where it is cheaper and sell it where it is more expensive.
But there is a problem.
A price difference that looks profitable on a screen does not automatically mean there is real profit after trading fees, slippage, liquidity, latency, minimum order requirements, and execution failures.
That is why I designed BB-Arbitrage differently. Instead of building a simple “buy low, sell high” bot, the goal is to create a risk-controlled platform that starts with market analysis and paper trading, while keeping live trading optional and locked behind explicit safety checks.
What BB-Arbitrage Is Designed to Do
BB-Arbitrage is a cloud-ready crypto arbitrage platform designed to:
- Collect real-time market data
- Detect price differences
- Calculate realistic expected profit
- Include fees and estimated slippage
- Check liquidity and exchange rules
- Reject opportunities below the configured threshold
- Simulate trades through paper trading
- Backtest strategies using historical data
- Track portfolio performance
- Monitor system health
- Provide optional spot-trading execution
- Maintain an audit trail
The objective is not to promise profits.
The objective is to build a reliable trading-engineering platform where risk controls have priority over trade frequency.
Why a Simple Arbitrage Bot Isn't Enough
Imagine two exchanges showing:
1
2
3
4
5
6
7
Exchange A
BTC/USDT Buy = $100,000
Exchange B
BTC/USDT Sell = $100,200
Gross spread = 0.20%At first glance, a 0.20% spread looks interesting.
But the gross spread is only the starting point.
A real system also needs to account for:
- Trading fees
- Bid/ask spread
- Slippage
- Liquidity
- Minimum order requirements
- Market-data latency
- Partial fills
- Network and execution costs
- Exchange/API failures
- Applicable taxes and other charges
For example:
1
2
Buy = $100,000
Sell = $100,250That is a 0.25% spread.
But after costs:
1
2
3
4
5
Trading fees -0.20%
Slippage -0.04%
Other costs -0.02%
--------------------------------
Expected net -0.01%The correct decision is:
1
DO NOT TRADEThis idea is central to BB-Arbitrage: an opportunity should be rejected when its expected economics do not satisfy the configured rules.
High-Level Architecture
The platform uses AWS EC2 and Docker as the initial deployment foundation.
The application is divided into several logical components:
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
Internet
|
v
+----------------+
| Nginx / ALB |
+--------+-------+
|
v
+----------------+
| Frontend |
| Next.js / TS |
+--------+-------+
|
v
+----------------+
| FastAPI |
| Backend |
+--------+-------+
|
+---------------+----------------+
| | |
v v v
Market Engine Risk Engine Paper Trading
| | |
+---------------+----------------+
|
v
+----------------+
| Arbitrage |
| Engine |
+--------+-------+
|
+------------+-------------+
| |
v v
Redis PostgreSQL
| |
+------------+-------------+
|
v
Amazon S3
Reports / Backups /
Historical DataAWS Services Used
The initial deployment intentionally keeps the AWS architecture relatively simple.
Amazon EC2
EC2 hosts:
- Docker
- FastAPI
- Next.js
- Redis
- Nginx
- Background workers
- Monitoring components where appropriate
Amazon S3
S3 is used for object storage rather than transactional database storage.
Possible uses include:
- Historical market-data files
- Backtesting datasets
- Generated reports
- Application exports
- Log archives
- Database backups
- Strategy-analysis reports
PostgreSQL
PostgreSQL stores transactional application data such as:
- Users
- Trades
- Orders
- Opportunities
- Portfolio data
- Risk events
- Audit logs
- Backtest metadata
For an MVP, PostgreSQL can run in Docker on EC2. A more production-oriented architecture can introduce Amazon RDS PostgreSQL later.
Redis
Redis handles:
- Real-time state
- Market-data caching
- Rate limiting
- Pub/sub
- WebSocket coordination
Redis should not be treated as the permanent transaction ledger.
CloudWatch
CloudWatch can be used for:
- EC2 monitoring
- Application logs
- System alerts
- CPU, memory, and disk monitoring
- Operational dashboards
Why Start With EC2?
For an early version, EC2 provides direct control over:
1
2
3
4
5
6
7
Docker
Networking
Nginx
Application processes
Background workers
Monitoring
DeploymentIt is also useful when learning and demonstrating AWS and DevOps skills.
The platform can later evolve toward:
1
2
3
4
5
6
7
ECS
RDS
ElastiCache
Secrets Manager
Application Load Balancer
CloudWatch
ECRThe important point is that there is no need to introduce every AWS service on day one.
Step 1 — Create the EC2 Instance
Create an EC2 instance in an AWS Region close to your target users and exchange infrastructure.
For the MVP, the markdown specifies a small general-purpose Linux instance using:
1
Ubuntu Server LTSConfigure the security group to allow:
1
2
3
SSH 22 Your IP only
HTTP 80 Internet
HTTPS 443 InternetDo not expose PostgreSQL or Redis publicly:
1
2
PostgreSQL 5432
Redis 6379These should remain private to the application host or network.
Step 2 — Connect to EC2 and Install Docker
Connect to the server:
1
ssh -i your-key.pem ubuntu@YOUR_EC2_PUBLIC_IPUpdate the system:
1
2
sudo apt update
sudo apt upgrade -yInstall Docker:
1
sudo apt install -y docker.io docker-compose-pluginEnable Docker:
1
2
sudo systemctl enable docker
sudo systemctl start dockerVerify the installation:
1
2
docker --version
docker compose versionStep 3 — Clone the Project
Clone the repository:
1
2
3
git clone https://github.com/bhupendrabhati/BB-Arbitrage.git
cd bb-arbitrageCreate the environment configuration:
1
cp .env.example .envDo not commit
.env to Git.Add:
1
.envto
.gitignore.Step 4 — Configure Environment Variables
The initial configuration is intentionally conservative:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
APP_ENV=production
TRADING_MODE=paper
INITIAL_CAPITAL_INR=100
MAX_TRADE_AMOUNT_INR=10
MAX_DAILY_LOSS_INR=2
MAX_OPEN_TRADES=1
MAX_TRADES_PER_DAY=5
MIN_NET_PROFIT_INR=0.10
MAX_SLIPPAGE_PERCENT=0.05
STALE_DATA_MS=500
LIVE_TRADING_ENABLED=falseThe important setting here is:
1
TRADING_MODE=paperand:
1
LIVE_TRADING_ENABLED=falseThe system starts without real-money execution.
Exchange credentials should remain outside source control. For production, the architecture recommends using AWS Secrets Manager rather than storing secrets directly in the repository or frontend.
Step 5 — Build and Start the Containers
Build the containers:
1
docker compose buildStart them:
1
docker compose up -dCheck their status:
1
docker compose psView logs:
1
docker compose logs -fStep 6 — Understand the Docker Compose Architecture
A simplified deployment can contain:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
services:
backend:
build: ./backend
depends_on:
- postgres
- redis
frontend:
build: ./frontend
postgres:
image: postgres:16
redis:
image: redis:7
nginx:
image: nginx:latestFor production, tested image versions should be pinned rather than relying on moving
latest tags.Step 7 — Put Nginx in Front
Nginx can provide:
1
2
3
4
5
HTTPS
Reverse Proxy
Frontend routing
API routing
Security headersThe routing model is:
1
2
3
4
5
6
7
https://your-domain.com
↓
Next.js
https://your-domain.com/api
↓
FastAPIUse HTTPS with a trusted certificate.
Step 8 — Connect a Domain
A domain can optionally be connected using:
1
2
3
Route 53
↓
EC2 / Load BalancerFor example:
1
app.example.comThe request flow becomes:
1
2
3
4
5
HTTPS
↓
Nginx
↓
Next.js / FastAPIStep 9 — Configure Amazon S3
Create an S3 bucket such as:
1
bb-arbitrage-dataUse prefixes:
1
2
3
4
5
historical/
backtests/
reports/
exports/
backups/Keep the bucket private.
Financial and trading data should not be publicly readable. IAM permissions should allow the application to access only the required bucket paths.
Step 10 — Upload Historical Data
For example:
1
2
aws s3 cp historical-data.csv \
s3://bb-arbitrage-data/historical/btc/The backtesting engine can then download datasets when required.
Step 11 — Store Backtest Reports
A typical report workflow is:
1
2
3
4
5
6
7
Backtest
↓
Generate JSON/CSV report
↓
Upload to S3
↓
Store S3 object reference in PostgreSQLThis gives the application a clean separation:
1
2
3
4
5
PostgreSQL
→ metadata
S3
→ large filesThe Trading Engine Behind the Deployment
Infrastructure is only one part of the project. The application itself contains several important components.
Market Data Engine
The market-data engine connects to supported exchanges and collects:
1
2
3
4
5
6
7
8
Exchange
Symbol
Bid
Ask
Bid Quantity
Ask Quantity
Timestamp
Sequence NumberWhere possible, WebSockets should be used for real-time market data.
The engine should also reject stale data.
For example:
1
2
3
4
5
6
7
Current time: 18:20:01.500
Market timestamp: 18:20:01.100
Data age: 400ms
If threshold = 500ms
→ Data is acceptableIf the data becomes too old:
1
2
3
STALE DATA
↓
NO TRADEArbitrage Engine
The arbitrage engine compares market conditions.
For example:
1
2
3
4
5
6
7
BTC/USDT
Exchange A
Ask = $100,000
Exchange B
Bid = $100,250The calculation follows:
1
2
3
4
5
6
7
8
9
10
11
Gross spread
↓
Trading fees
↓
Estimated slippage
↓
Liquidity
↓
Other configured costs
↓
Expected net profitOnly opportunities satisfying the configured rules proceed to the risk engine.
Risk Engine
The risk engine is one of the most important components.
Every trade must pass checks such as:
1
2
3
4
5
6
7
8
9
10
Capital limit
Trade-size limit
Daily loss limit
Open-position limit
Liquidity
Slippage
Data freshness
Exchange health
API health
Minimum order sizeThe initial example configuration is deliberately small:
1
2
3
4
5
INITIAL_CAPITAL_INR=100
MAX_TRADE_AMOUNT_INR=10
MAX_DAILY_LOSS_INR=2
MAX_OPEN_TRADES=1
MAX_TRADES_PER_DAY=5Paper Trading
Paper trading allows the platform to use real market data without risking real capital.
The simulator should model:
- Fees
- Slippage
- Order-book depth
- Partial fills
- Latency
- Failed orders
- Rejected orders
This matters because a naive paper-trading system can make results appear much better than they would be in real execution.
Backtesting
The backtesting engine evaluates strategies against historical data.
A report can include:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Initial Capital
Final Capital
Gross P&L
Fees
Slippage
Net P&L
Number of Trades
Winning Trades
Losing Trades
Win Rate
Maximum Drawdown
Profit Factor
Average Trade
Largest Win
Largest LossBacktesting must also avoid look-ahead bias. Historical simulations should never use information that would not have been available at the simulated trading time.
Live Trading Should Be Locked
Live trading is optional.
The platform should keep it:
1
LOCKEDuntil the required safety checks have been completed.
The proposed flow is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Automated tests passed
↓
Risk limits configured
↓
Kill switch tested
↓
API permissions verified
↓
Order reconciliation verified
↓
Paper trading validated
↓
User confirmation
↓
LIVE TRADING UNLOCKThe system must never implement withdrawal functionality, and exchange API keys should never have withdrawal permissions.
Monitoring the Platform
Infrastructure monitoring can be handled through CloudWatch.
Monitor:
1
2
3
4
5
6
7
CPU
Memory
Disk
Network
Application logs
Docker logs
System healthApplication metrics can also be exposed through Prometheus.
Useful metrics include:
1
2
3
4
5
6
7
8
9
10
market_data_latency
opportunities_detected
opportunities_rejected
trades_executed
trade_errors
api_latency
websocket_disconnects
pnl
drawdown
risk_eventsGrafana can then visualize these metrics.
Add a Health Endpoint
A simple application health endpoint can be:
1
GET /healthWith a response such as:
1
2
3
4
5
6
7
{
"status": "healthy",
"mode": "paper",
"database": "healthy",
"redis": "healthy",
"market_data": "healthy"
}Deeper health checks can also cover:
1
2
3
4
5
6
Database
Redis
Exchange connection
WebSocket
Disk
MemorySecurity Checklist Before Live Trading
Before considering live trading, verify:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[ ] HTTPS enabled
[ ] SSH restricted to known IPs
[ ] Database not publicly accessible
[ ] Redis not publicly accessible
[ ] Secrets not stored in Git
[ ] Secrets not logged
[ ] Exchange withdrawal permission disabled
[ ] Authentication enabled
[ ] Authorization enabled
[ ] Rate limiting enabled
[ ] Audit logging enabled
[ ] Kill switch tested
[ ] Order reconciliation tested
[ ] Backups configured
[ ] Monitoring enabled
[ ] Alerts configuredThis checklist is as important as the arbitrage logic itself.
Why the Kill Switch Matters
Imagine the exchange API begins returning incorrect information.
Without a kill switch:
1
2
3
4
5
6
7
Market data problem
↓
Bot continues
↓
Potential trades
↓
Unexpected lossesWith a kill switch:
1
2
3
4
5
6
7
Market/API anomaly
↓
Risk engine
↓
SAFE STOP
↓
No new tradesThe platform should prefer stopping over trading with uncertain information.
A Realistic Arbitrage Decision
Suppose the system sees:
1
2
3
4
5
Exchange A
BTC Buy = $100,000
Exchange B
BTC Sell = $100,300The gross spread is:
1
Gross spread = 0.30%After estimated costs:
1
2
3
4
5
Trading fees = 0.20%
Slippage = 0.05%
Other costs = 0.02%
--------------------------------
Expected net = 0.03%If the minimum required net profit is:
1
0.10%the system rejects the opportunity:
1
2
3
4
REJECTED
Reason:
NET PROFIT BELOW THRESHOLDThat is a feature, not a failure.
Starting With ₹100
The initial configuration can use:
1
2
3
Capital: ₹100
Maximum trade: ₹10
Maximum daily loss: ₹2But ₹100 should be treated as a learning and experimental amount, not guaranteed income-generating capital.
There is another important consideration: exchanges may impose minimum-order requirements. That means some ₹10 trades may simply be impossible.
The application must check exchange-specific minimum order rules before attempting execution.
If the minimum is not satisfied:
1
NO TRADESuggested Repository Structure
The proposed repository structure is:
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
bb-arbitrage/
├── backend/
│ ├── app/
│ │ ├── api/
│ │ ├── core/
│ │ ├── config/
│ │ ├── models/
│ │ ├── schemas/
│ │ ├── services/
│ │ ├── exchanges/
│ │ ├── market_data/
│ │ ├── arbitrage/
│ │ ├── risk/
│ │ ├── portfolio/
│ │ ├── paper_trading/
│ │ ├── live_trading/
│ │ ├── backtesting/
│ │ ├── accounting/
│ │ ├── notifications/
│ │ ├── monitoring/
│ │ ├── security/
│ │ └── main.py
│
│ └── tests/
│
├── frontend/
│ ├── app/
│ ├── components/
│ ├── hooks/
│ ├── lib/
│ ├── services/
│ └── types/
│
├── infra/
│ ├── docker/
│ ├── aws/
│ └── terraform/
│
├── docs/
│
├── scripts/
│
├── .github/
│ └── workflows/
│
├── docker-compose.yml
├── .env.example
├── README.md
├── ARCHITECTURE.md
└── SECURITY.mdWhat Could Come Next?
Once the MVP is stable, the platform can evolve with:
- More exchanges
- More trading pairs
- Advanced order-book analysis
- Better slippage models
- Historical data pipelines
- Strategy comparison
- Advanced performance analytics
- Telegram alerts
- Mobile-responsive dashboard
- Multi-user support
- Role-based access
- AWS ECS deployment
- RDS PostgreSQL
- ElastiCache Redis
- Secrets Manager
- Automated backups
- More sophisticated anomaly detection
AI can also be added as an analysis layer, but it should never override deterministic risk controls.
What Does Success Look Like?
Success is not:
1
₹100 → ₹1,00,000The first objective is:
1
2
3
4
5
6
7
8
9
10
11
12
13
Correct market data
↓
Correct arbitrage calculation
↓
Correct cost calculation
↓
Correct risk controls
↓
Realistic paper trading
↓
Reliable deployment
↓
Safe operationFinal Architecture
The finished platform can be visualized conceptually like this:
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
AWS CLOUD
┌───────────────────────────────────────────────┐
│ │
│ EC2 │
│ │
│ ┌─────────┐ ┌──────────────┐ │
│ │ Nginx │─────>│ Next.js │ │
│ └────┬────┘ └──────────────┘ │
│ │ │
│ v │
│ ┌──────────────┐ │
│ │ FastAPI │ │
│ └──────┬───────┘ │
│ │ │
│ ┌─────┼───────────────┐ │
│ │ │ │ │
│ v v v │
│ Redis PostgreSQL Arbitrage Engine │
│ │ │ │ │
│ │ │ ┌────┴────┐ │
│ │ │ │ Risk │ │
│ │ │ │ Engine │ │
│ │ │ └────┬────┘ │
│ │ │ │ │
│ │ │ Paper/Live │
│ │ │ │ │
│ └─────┴───────────────┘ │
│ │
│ AWS S3 │
│ Historical Data / Reports / Backups │
│ │
│ CloudWatch │
│ Logs / Monitoring │
│ │
└───────────────────────────────────────────────┘Conclusion
BB-Arbitrage is not designed as a shortcut to guaranteed crypto profits.
It is a serious engineering project that brings together:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Crypto Market Data
+
Arbitrage Logic
+
Risk Management
+
Paper Trading
+
Backtesting
+
Python/FastAPI
+
Next.js
+
Docker
+
AWS EC2
+
S3
+
Monitoring
+
DevOpsThe most important principle is simple:
When the system is uncertain, it should not trade.
That principle should remain at the center of BB-Arbitrage as the platform grows.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article