Your Notion database has 2,000 tasks with custom fields like "Priority 🚀" and "Status (Updated)". Your GitHub project has completely different status names and no custom fields. Someone just renamed "Priority 🚀" to "Urgency Level" and broke everything.
Welcome to integration hell - where two perfectly functional systems become a nightmare when you try to connect them.
Why Webhooks Are Fucking Liars
Webhooks don't work. Period. That's the first thing you need to know. Notion says "real-time" - they mean "whenever we feel like it, maybe 30 seconds, probably never." GitHub's are worse - they just stop firing and don't tell you why.
Spent three days wondering why nothing was syncing before I realized their webhook endpoint was returning 404s and nobody bothered logging it.
Here's what will ruin your week (ask me how I know):
Webhook Listeners (That Mostly Don't Work)
- GitHub webhooks fire inconsistently when their servers are under load (they don't tell you this)
- Notion webhooks randomly stop working and you won't know until someone complains
- You'll need ngrok for testing because localhost webhooks are fantasy. Works fine on Linux, randomly explodes on Windows 11 with WSL2 for reasons that make no sense (something about network adapter conflicts)
- Pro tip: Always implement webhook signature verification or script kiddies will spam your endpoints with garbage
- ngrok tunnels die randomly and you won't notice until everything's broken for 20 minutes
2. Data Mapping That Doesn't Corrupt Everything
- Notion's "Person" field becomes a GitHub username - except when it doesn't because email matching fails
- Date fields use different timezones and ISO 8601 formats that will fuck you over
- Custom fields in GitHub Projects have weird restrictions Notion doesn't care about
- Status mapping breaks when someone adds "In Review 🔥" as a status
3. API Clients That Actually Work
- Notion's REST API rate limits you at 3 requests/second average (no burst allowance despite what people think)
- GitHub's GraphQL API costs more points than you think - that simple query just ate 50 points
- Both APIs lie about their error messages - "Bad Request" tells you nothing useful about what you actually fucked up
- You need the official Notion SDK because hand-rolling HTTP requests is masochism, but their SDK has weird peer dependency conflicts with newer Node versions
- Updated one npm package last month and suddenly nothing works. Turns out Notion's SDK doesn't play nice with Express 5.x. Spent 4 hours debugging before rolling back to Express 4.x like a caveman
4. State Tracking So You Don't Create Infinite Loops
Found out about infinite loops the hard way. Forgot to add a sync_source
field and watched one status change create hundreds of duplicate tickets. GitHub started rate limiting us, Notion started throwing errors, and our Slack channel exploded.
Add sync_source
and last_synced_at
fields or watch everything burn. Redis works for tracking sync state, but we're still getting random sync loops about once a month and nobody knows why. Circuit breakers helped when Notion went down, but sometimes they trip for no reason and stay tripped.
Log everything because you'll be debugging this shit at 3am with Linda from product asking why her tickets are wrong again.
What Actually Happens in Production
The integration works perfectly until sprint planning day. Then:
- Someone bulk-updates 200 tickets in Notion
- Your webhook endpoint gets hammered with requests
- GitHub's API starts throwing 429 errors
- Half the updates fail and now your data is inconsistent
- The PM starts asking why their tickets are wrong
- You question all your life choices
If you're lucky, changes sync in under 10 seconds. If you're unlucky, you restart everything and pray to the webhook gods.
Built this for our team because manually syncing tickets was driving everyone insane. Now we have an automated system that breaks in different ways every month, but at least our PM stops yelling at us about inconsistent ticket statuses.
Still breaks regularly. Sometimes webhooks just stop and we restart everything and pray. But it beats manual updates.
Don't build this. Seriously. But if you're going to ignore me anyway (and let's be honest, you probably will because developers are stubborn idiots who think they can do it better), here's what actually breaks and why most solutions don't work.
The next thing you'll try is third-party tools because building custom seems scary. That's cute. Let me tell you why those will disappoint you too.