Pipedream vs. a webhook relay you own: when trust gets expensive
Pipedream is genuinely good until your payload contains PHI or a signing secret. Here's where I draw the line.
Pipedream is one of those tools I recommend without hesitation — right up until I can't. The line isn't arbitrary. It's the moment a payload contains something I'm not allowed to hand to a third party, or the moment the business logic is complex enough that I'm fighting the platform instead of using it.
Let me walk through both sides honestly.
What Pipedream actually is (skip the landing page)
At its core, Pipedream gives you a public HTTPS endpoint that can receive a webhook, run JavaScript steps against the payload, and fan it out to other services — Slack, Postgres, an HTTP destination, whatever. The hosted runtime handles retries, logs every event, and lets you inspect payloads in a UI that's genuinely useful for debugging.
For the kind of work I do — stitching together a SaaS CRM with a client's ERP, or routing Shopify order events into a warehouse system — that's a lot of plumbing I don't have to build. I've used it to normalize payloads from a finicky real estate MLS feed before they hit a Laravel app, and it saved me probably two days of work.
The free tier is legitimately generous. Paid plans are reasonable. The developer experience is the best in this category — better than Zapier for anything code-adjacent, better than n8n if you don't want to host something yourself.
So what's the problem?
The trust surface is the whole point
Every webhook you route through Pipedream means Pipedream receives that payload. That's not a gotcha — it's the product. Their infrastructure decrypts TLS, your data sits in their event store (they call it the event log), and their workers execute your code against it.
For most business webhooks — a Stripe payment_intent.succeeded, a GitHub push event, a Shopify order — that's fine. The data is business-sensitive, not regulated.
The moment I'm looking at a webhook from an EHR system, a LIMS, or anything touching patient data, the calculus changes completely. HIPAA doesn't care that Pipedream has a BAA program. I care that a BAA program exists, and I've looked — as of the last time I checked, Pipedream does not offer Business Associate Agreements. That means PHI cannot legally flow through their platform. Full stop.
I ran into this with a biotech client last year. They wanted to use Pipedream to route instrument events from a lab system into their internal dashboard. Looked like a 20-minute setup. Then I read the payload schema. Patient sample identifiers. Covered under their compliance obligations. I had to walk it back.
What writing your own relay actually looks like
It's not that much code. Here's the core of what I use in Laravel:
// routes/api.php
Route::post('/relay/{source}', [WebhookRelayController::class, 'handle']);
<?php
namespace App\Http\Controllers;
use App\Jobs\DispatchWebhookEvent;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
class WebhookRelayController extends Controller
{
public function handle(Request $request, string $source): Response
{
$config = config("webhooks.sources.{$source}");
if (! $config) {
return response('Unknown source', 404);
}
if (! $this->verify($request, $config)) {
Log::warning('Webhook signature failure', ['source' => $source]);
return response('Forbidden', 403);
}
DispatchWebhookEvent::dispatch(
source: $source,
payload: $request->all(),
headers: $request->headers->all(),
);
return response('Accepted', 202);
}
private function verify(Request $request, array $config): bool
{
$strategy = $config['verify'] ?? 'none';
return match ($strategy) {
'hmac_sha256' => $this->verifyHmac(
$request,
$config['secret'],
$config['header'] ?? 'X-Signature-256',
$config['prefix'] ?? 'sha256='
),
'bearer' => hash_equals(
$config['token'],
$request->bearerToken() ?? ''
),
'none' => true,
default => false,
};
}
private function verifyHmac(
Request $request,
string $secret,
string $header,
string $prefix
): bool {
$signature = $request->header($header, '');
$expected = $prefix . hash_hmac('sha256', $request->getContent(), $secret);
return hash_equals($expected, $signature);
}
}
The job (DispatchWebhookEvent) puts it on a queue. A listener on the queue matches the source to a handler class, which does whatever the business logic requires. The whole thing is on infrastructure I control, behind a firewall I manage, logging to a system I own.
Signature verification runs before the payload is even deserialized. That's important — Stripe's signature header covers the raw body, and if you call $request->all() before you verify, you've already parsed JSON that might be spoofed.
The config file (config/webhooks.php) looks like this:
return [
'sources' => [
'stripe' => [
'verify' => 'hmac_sha256',
'secret' => env('STRIPE_WEBHOOK_SECRET'),
'header' => 'Stripe-Signature',
'prefix' => 't=', // Stripe uses a different format — handled in custom verifier
],
'labsystem' => [
'verify' => 'bearer',
'token' => env('LAB_WEBHOOK_TOKEN'),
],
],
];
(Stripe's signature format is actually more involved — it includes a timestamp and replay prevention. I have a StripeSignatureVerifier class that does it properly. The above is the simplified skeleton.)
This is maybe four hours of work including tests. It runs on the same managed VPS the app lives on. No third-party sees the payload.
The gotchas with Pipedream I've actually hit
Event log retention. Pipedream stores your events for inspection and replay. That's a feature. It's also your data sitting in their system. Know what you're storing.
Cold start latency on the free tier. Workers spin down. If you're routing time-sensitive webhooks — payment confirmations, inventory reservations — you'll see occasional multi-second delays. Not a dealbreaker, but I've had clients notice it.
Code steps are JavaScript only. If your normalization logic is already in PHP, you're rewriting it. Small thing, but it adds a maintenance surface.
Debugging requires their UI. When something goes wrong at 2am, you're logging into their dashboard. With your own relay, the logs are wherever you put them — Cloudwatch, Papertrail, your Laravel log file. I know where my logs are.
Vendor dependency for a critical path. Pipedream has had outages. Any SaaS has outages. If your webhook relay is Pipedream and Pipedream is down, you're not receiving webhooks. With a self-hosted relay on the same infra as your app, that failure mode collapses — both go down together, which is a different (and usually more acceptable) risk profile.
When I'd reach for Pipedream
- Internal tooling where payload sensitivity is low and iteration speed matters more than control.
- Prototyping an integration before committing to building it properly. Pipedream is excellent for proving out a data flow.
- Non-regulated clients where the integration is genuinely simple and I don't want to spin up infrastructure for a two-step webhook.
- Anything where fan-out to multiple destinations is the core requirement and I don't want to manage a queue.
I used it last quarter to route a furniture e-commerce client's Shopify events into a Slack channel and a Google Sheet for their ops team. Perfect use case. The data was order confirmations, nothing sensitive, and the whole thing took 30 minutes including testing.
When I wouldn't
- Any payload containing PHI, PII that's regulated, or credentials. Not negotiable.
- Production systems where the webhook is in a critical path (payment confirmation, order fulfillment triggers).
- Clients with compliance requirements — HIPAA, SOC 2, anything that requires me to enumerate data processors.
- When the transformation logic is complex enough that I'm writing 200 lines of JavaScript I'll have to maintain in a browser-based editor.
- When I need the audit log to live in my own system.
The thing I want to say plainly
Pipedream isn't a security risk in the abstract — it's a trust boundary you're drawing, consciously or not. Most developers use it without thinking about what they're signing up for, and for most webhooks that's fine. The problem is when the same workflow gets copy-pasted onto a more sensitive integration because it worked last time.
The cost of writing your own relay is genuinely low. A few hours, a queue, a controller. You already have the infrastructure if you're running a Laravel app. The thing Pipedream sells you is time-to-working, and that's a real value. Just be honest with yourself about when the time savings aren't worth what you're handing over.
I keep Pipedream in my toolkit. I just know exactly which shelf it goes on.
Need help shipping something like this? Get in touch.