Distributed Denial Of Service in Feathersjs with Dynamodb
Distributed Denial Of Service in Feathersjs with Dynamodb — how this specific combination creates or exposes the vulnerability
A DDoS concern in a FeathersJS application that uses DynamoDB typically arises from how unbounded requests interact with DynamoDB operations and service-side resource usage. FeathersJS is a framework that encourages REST and real-time behavior; without explicit safeguards, an endpoint can be invoked at high frequency, generating many concurrent DynamoDB requests. Each request may perform operations such as find, get, create, or patch that consume read/write capacity. If the provisioned capacity is exceeded, DynamoDB returns throttling responses; however, the application may retry aggressively, increasing load on both DynamoDB and the application runtime. This combination can amplify traffic and contribute to a denial-of-service condition for legitimate users.
FeathersJS hooks and services can also trigger additional processing, such as event emitters and external integrations, which consume CPU and memory on the host. Under sustained high request rates, this can exhaust local resources, making the service unresponsive even when DynamoDB continues to accept requests. Real-world attack patterns like HTTP floods or recursive query amplification—where one request triggers multiple DynamoDB operations—expose this risk. For example, an attacker may call a /messages endpoint with query parameters that cause inefficient scans or large result sets, increasing DynamoDB consumed read capacity units and server-side processing time.
Another specific concern involves DynamoDB features used within FeathersJS, such as DynamoDB Document Client or paginated queries. If pagination is not bounded, a client can request large pages that increase serialization and network work. Without proper validation and rate controls, these behaviors can degrade availability. Because DynamoDB is a managed service, the platform handles scaling, but application-level design in FeathersJS must avoid unbounded operations and ensure efficient access patterns to reduce DDoS surface.
Dynamodb-Specific Remediation in Feathersjs — concrete code fixes
Mitigation focuses on request validation, bounded queries, efficient access patterns, and operational safeguards. Use explicit filtering, limit page sizes, and enforce rate limits at the FeathersJS layer. Apply early validation in hooks to reject malformed or abusive requests before they reach DynamoDB.
Example: Safe paginated find with validation
const feathers = require('@feathersjs/feathers');
const express = require('@feathsjs/express');
const {DynamoDBDocumentClient, QueryCommand} = require('@aws-sdk/lib-dynamodb');
const {dynamodbClient} = require('./dynamodb-client'); // configured client
const app = feathers();
app.configure(express.rest());
// Safe service implementation
app.use('/items', {
async find(params) {
const {query} = params;
const limit = Math.min(query.limit ? Number(query.limit) : 10, 50); // enforce ceiling
const lastKey = query.lastKey ? JSON.parse(query.lastKey) : undefined;
const cmd = new QueryCommand({
TableName: process.env.ITEMS_TABLE,
KeyConditionExpression: 'ownerId = :owner',
ExpressionAttributeValues: {
':owner': params.account.id,
},
Limit: limit,
});
if (lastKey) {
cmd.input.ExclusiveStartKey = lastKey;
}
const data = await dynamodbClient.send(cmd);
return {
total: data.Count || data.Items.length,
limit,
skip: 0,
data: data.Items,
};
},
});
// Global hook to enforce rate and validate input
app.hooks({
before: {
all: [
(context) => {
if (context.params.query && context.params.query.limit && Number(context.params.query.limit) > 1000) {
throw new Error('Limit too high');
}
return context;
},
],
},
});
Example: Conditional writes to avoid hot partitions
app.use('/updates', {
async create(data, params) {
const item = {
id: data.id || uuidv4(),
ownerId: params.account.id,
status: 'pending',
createdAt: Date.now(),
};
// Use conditional write to prevent duplicate submissions that could amplify load
const cmd = new PutCommand({
TableName: process.env.UPDATES_TABLE,
Item: item,
ConditionExpression: 'attribute_not_exists(id)',
});
try {
await dynamodbClient.send(cmd);
return item;
} catch (err) {
if (err.name === 'ConditionalCheckFailedException') {
throw new Error('Duplicate submission');
}
throw err;
}
},
});
Operational recommendations
- Define maximum page and batch sizes in hooks and enforce them before calling DynamoDB.
- Use DynamoDB reserved capacity or auto scaling appropriately, and monitor consumed capacity to detect anomalies that may indicate abuse.
- Implement application-level rate limiting and consider token-bucket algorithms to smooth bursts.
- Ensure queries use partition keys efficiently; avoid scans that consume high read capacity.