Rise’s webhook delivery system is designed for reliability and resilience. This guide explains how webhooks are delivered, what happens when deliveries fail, and how to optimize your endpoint for the best performance.
How webhook delivery works
When an event occurs in your Rise account, our system immediately begins the delivery process:
Event triggered
A payment, deposit, or other action occurs in your Rise account
Webhook queued
Event is added to the delivery queue for each subscribed webhook endpoint
HTTP POST sent
Webhook payload is delivered to your endpoint via HTTP POST request
Response evaluated
Your endpoint’s response determines whether delivery was successful
Success or retry
Successful deliveries are logged; failures trigger the retry mechanism
Delivery expectations
Response requirements
Your webhook endpoint should:
Respond quickly Return a response within 10 seconds to avoid timeout
Return 2xx status Any status code from 200-299 indicates successful delivery
Acknowledge receipt Send a simple response like {"received": true}
Handle duplicates Process the same event multiple times safely (idempotency)
What Rise considers successful
Rise considers a webhook delivery successful when:
Your endpoint returns HTTP status 200-299
The response is received within 10 seconds
The connection completes without network errors
What triggers a retry
Rise will retry webhook deliveries when:
Your endpoint returns HTTP status 400-599
The request times out after 10 seconds
Network connection fails or is refused
DNS resolution fails for your endpoint
Retry policy
Rise implements an exponential backoff retry strategy to handle temporary failures gracefully.
Retry schedule
When a delivery fails, Rise will retry according to this schedule:
When : After the initial failure
Wait time : 1 minute (60 seconds)
Purpose : Allow brief recovery time for temporary issues
When : After first retry fails
Wait time : 2 minutes (120 seconds)
Purpose : Handle longer recovery periods
When : After second retry fails
Wait time : 5 minutes (300 seconds)
Purpose : Maximum retry attempt with extended delay
Total retry period : Up to approximately 8 minutes and 20 seconds from the original event
Maximum attempts : 4 total (initial + 3 retries)
Retry timing : Rise waits exactly 10 seconds before initiating each retry attempt. This consistent delay applies to all retry attempts and helps ensure your endpoint has adequate time to recover from temporary issues.
Exponential backoff benefits
Reduces server load Gives your endpoint time to recover from issues
Handles temporary issues Network glitches, brief downtime, or deployments
Prevents cascading failures Avoids overwhelming already struggling endpoints
Maximizes delivery success Multiple attempts significantly increase reliability
Delivery status tracking
Every webhook delivery is tracked and recorded for monitoring and debugging.
Delivery states
Pending
Sending
Delivered
Failed
Retrying
Status : Queued for deliveryThe webhook event has been created and is waiting in the delivery queue. This is the initial state before any delivery attempts.
Status : Currently being deliveredRise is actively attempting to deliver the webhook to your endpoint. This state is usually very brief.
Status : Successfully receivedYour endpoint responded with a 2xx status code within the timeout period. The delivery is complete and successful.
Status : All retries exhaustedAll retry attempts have been exhausted and the webhook could not be delivered. Manual intervention may be required.
Status : Scheduled for retryA delivery attempt failed but the webhook is scheduled to be retried according to the retry policy.
Viewing delivery history
Access delivery history through your webhook details page in the Rise app:
Navigate to webhook settings
Go to the Developer section and click on Webhooks
Select your webhook
Click on the webhook you want to monitor
View delivery history
Click the “Delivery History” tab to see all delivery attempts
Filter and analyze
Use filters to focus on successful, failed, or pending deliveries
Optimizing your endpoint
Follow these practices to ensure reliable webhook delivery:
Response time optimization
Good practice
Bad practice
// Quick acknowledgment, async processing
app . post ( '/webhooks' , async ( req , res ) => {
try {
// Verify signature first with SDK
const event = validator . validateEvent ( req . body , req . headers [ 'x-rise-signature' ]);
// Acknowledge receipt immediately
res . status ( 200 ). json ({ received: true });
// Process event asynchronously
processWebhookAsync ( event );
} catch ( error ) {
res . status ( 400 ). send ( 'Verification failed' );
}
});
async function processWebhookAsync ( event ) {
// Queue for background processing
await jobQueue . add ( 'process-webhook' , event );
}
// Slow processing blocks response
app . post ( '/webhooks' , async ( req , res ) => {
try {
const event = validator . validateEvent ( req . body , req . headers [ 'x-rise-signature' ]);
// DON'T: Slow operations before responding
await updateDatabase ( event ); // 2-3 seconds
await sendEmailNotification ( event ); // 1-2 seconds
await callExternalAPI ( event ); // 3-5 seconds
res . status ( 200 ). json ({ received: true }); // Too late!
} catch ( error ) {
res . status ( 400 ). send ( 'Error' );
}
});
Idempotency handling
Design your webhook handlers to safely process duplicate events:
function handlePaymentEvent ( event ) {
const paymentId = event . payment . nanoid ;
// Check if already processed
const existingRecord = database . findPayment ( paymentId );
if ( existingRecord && existingRecord . webhookProcessed ) {
console . log ( `Payment ${ paymentId } already processed, skipping` );
return ; // Safe to ignore duplicate
}
// Process the payment
database . updatePayment ( paymentId , {
status: event . payment . status ,
webhookProcessed: true ,
processedAt: new Date ()
});
// Trigger business logic
if ( event . event_type === 'payment.sent' ) {
fulfillOrder ( event . payment . invoice_nanoid );
}
}
Error handling best practices
Recommended approach
What to avoid
app . post ( '/webhooks' , async ( req , res ) => {
try {
// Always verify first with SDK
const event = validator . validateEvent ( req . body , req . headers [ 'x-rise-signature' ]);
// Respond quickly
res . status ( 200 ). json ({ received: true });
// Handle processing errors gracefully
try {
await processWebhook ( event );
} catch ( processingError ) {
// Log error but don't fail the webhook
console . error ( 'Webhook processing error:' , processingError );
// Queue for retry or manual review
await errorQueue . add ( 'failed-webhook' , {
event: req . body ,
error: processingError . message ,
timestamp: new Date ()
});
}
} catch ( verificationError ) {
// Only fail webhook for verification errors
console . error ( 'Webhook verification failed:' , verificationError );
res . status ( 400 ). send ( 'Invalid signature' );
}
});
Track your webhook delivery metrics to maintain reliability:
Key metrics to monitor
Success rate Target : >99% first-attempt success ratePercentage of deliveries that succeed without requiring retries
Response time Target : <2 seconds averageHow quickly your endpoint responds to webhook requests
Retry rate Target : <5% of deliveriesPercentage of deliveries requiring retry attempts
Final failure rate Target : <0.1% of deliveriesPercentage of deliveries that ultimately fail after all retries
Delivery limits and quotas
Rise implements reasonable limits to ensure system stability:
Rate limits
Delivery rate Limit : Reasonable per-endpoint rateMaximum webhook deliveries per second per endpoint
Burst allowance Limit : Short burst capacityTemporary higher rate for event spikes
Cooldown period Limit : Recovery timeBrief pause between burst periods
Retry and storage limits
Maximum retries : 3 attempts per webhook delivery
Retry window : Approximately 8 minutes total retry period
Delivery history : 30 days of delivery records stored
Event retention : 7 days of event data available for redelivery
What’s next?
Now that you understand webhook delivery mechanics:
Performance tip : The fastest webhook is one that responds immediately and processes asynchronously. Your users will thank you for the responsiveness, and Rise will thank you for the reliability.