PostHog Handbook Library / Engineering

5,189 words. Estimated reading time: 24 min.

# Support hero

Auto TL;DR

## At a Glance

This long page covers these main areas. The list is generated from the article headings, so it updates with every handbook rebuild.

1. When is my turn?
2. What if I'm scheduled for a week when I won't be available?
3. I can't assign tickets or make public replies
4. What do I do as Support Hero?
5. Shipping features
6. Fixing bugs
7. Papercuts
8. Responding to external PRs

Every week, one person in each engineering team is designated the Support Hero. If this is you this week, congratulations!

As Support Hero, your job is to investigate and resolve issues reported by customers. A single case of suspicious data or a show-stopping bug can really undermine one's confidence in a data product, so it's important that we get to the bottom of all issues.

One of the many awesome things about PostHog is that support is being dealt with by engineers and they ship fixes and improvements in real-time when you contact them. It is impossible to overstate how valuable it is for customers when they ask a question and get a shipped feature within a day.

You'll see some teams using a term of endearment for Support Hero, examples being "Infra Hero" or… "Luigi". Don't ask – we don't know.

Our Support Engineers, in the triage tickets for the , , , , , , , and teams, due to the high volume of tickets those teams get. They will resolve tickets if possible, and escalate to the engineering team responsible if they need further help.

### When is my turn?

Most engineering teams run a incident.io schedule, check out the escalation schedules.

The schedules consist of contiguous blocks, but that definitely doesn't mean working 24/7 – you should just work your normal hours.

### What if I'm scheduled for a week when I won't be available?

Swap with a teammate in advance! Find a volunteer by asking in Slack, then use incident.io schedule overrides. You can trade whole weeks, but also just specific days. Remember not to alter the rotation's core order, as that's an easy way to accidentally shift the schedule for everyone.

### I can't assign tickets or make public replies

Everyone has access to view tickets in Zendesk however if you do not reply to tickets often you may find you currently have Light agent permissions. The HogHero app in the right sidebar should allow you to upgrade your user for your support week by clicking Full⬆️ Image: image

### What do I do as Support Hero?

Each engineering team has its own list of tickets in Zendesk:

- Product Analytics
- Web Analytics
- Experiments
- Feature Flags
- Replay
- Surveys
- CDP
- Infrastructure
- Auth & Billing, handled by Growth

Your job is simple: ship features and fixes, resolve ticket after ticket from your team's list, and respond to open-source PRs assigned to your team.

There are four sources of tickets:

1. In-app bug reports/feedback/support tickets sent from the Support panel (The `Help` tab in the righthand sidebar.) They include a bunch of useful links, e.g. to the admin panel and to the relevant session recording.
2. Community questions asked on PostHog.com.
3. Slack threads that have been marked with the 🎫 reaction in customer support channels.
4. Reports in the `#papercuts` Slack channel that relate to your team's area.

#### Shipping features

Some tickets ask for new features. If the feature is useful for users matching our ICP, then decide whether to just build it. Otherwise, create a feature request issue in GitHub or +1 on an existing one – you can then send a link to the user, giving them a way of tracking progress. Also make sure to let the know, since they will track feature requests for paying customers.

Sometimes a feature already exists, but a user doesn't know about it or how to use it. In this case, you should either send them a link to the relevant docs page or update the docs to make it clearer.

#### Fixing bugs

Others tickets report bugs or suspected bugs. Get to the bottom of each one - you never know what you'll find. If the issue decidedly affects only that one user under one-in-a-million circumstances, it might not be worth fixing. But if it's far-reaching, a proper fix is in order. And then there are "bugs" which turn out to be pure cases of confusing UX. Try to improve these too.

If not much is happening, feel free to do feature work – but in the case of a backlog in Zendesk, drop other things and roll up your sleeves. When you're Support Hero, supporting users comes first.

It might be an intense week, but you're also going to solve so many real problems, and that feels great.

#### Papercuts

Check the `#papercuts` Slack channel during your rotation and pick up any reports that relate to your team's area. For each one, pick one of the following:

- Reply to the reporter acknowledging the papercut, then either get a fix shipped or open a GitHub issue to track it if it needs more scoping. How you get the fix out is up to you – prompting PostHog Code is often the fastest path, but feel free to fix it however you like.
- React with ❌ to reject the papercut (for example, if the behavior is intentional). A brief reply explaining why is appreciated.
- React with ✅ once you've shipped a fix or improvement.

Papercuts are also routed to the Signals inbox, so before you start work, check whether an auto-generated PR is already waiting – it may save you most of the effort.

#### Responding to external PRs

When capacity allows, the support hero serves as the first point of contact for external (open-source) PRs that affect your team's product. While we want to be good open-source citizens, customer support always takes priority — if you're dealing with a heavy support load, it's acceptable for PR reviews to be delayed or handled more briefly.

##### How external PRs are assigned

External PRs typically reach your team through one of two methods:

- CODEOWNERS automation: If your team has CODEOWNERS configured, PRs modifying your team's files will automatically be assigned to your team
- Manual assignment: For teams without CODEOWNERS set up, external PRs may be manually assigned to your team handle by other engineers who spot them

##### Best practices for handling external PRs

These are guidelines to aim for when you have bandwidth after handling customer support. Adapt them based on your workload:

###### Initial response (when possible)

- Acknowledge the PR with a thank you comment when you can
- Quick check: Are there obvious blockers like failed tests or merge conflicts? If so, politely ask the contributor to address them first
- If your support queue is overwhelming, it's okay to delay this or keep it brief

###### Review approach

- Be welcoming and constructive - contributors are volunteering their time
- Provide actionable feedback when you have time for a thorough review
- Consider the effort/reward tradeoff - some PRs may need more work than they're worth
- It's better to politely decline quickly than to let a PR sit without feedback for weeks

###### Communication tips

- Set realistic expectations based on your current workload
- Remember that external contributors can't ping us directly like teammates can
- If you know you won't get to a PR this week, a quick "Thanks for the contribution! Our team is currently focused on customer issues but we'll review this when we can" is better than silence

###### Common blockers to address upfront (when doing a full review)

- Ask contributors to respond to Greptile feedback before your review
- Require merge conflicts to be resolved before reviewing
- Ensure tests are passing (or understand why they're not)
- Check that the PR follows our existing code patterns and conventions

###### When to escalate or defer

- If the PR touches critical infrastructure or security-sensitive code
- If you're unsure about the product implications
- If your support load is too high to give it proper attention
- If a PR requires extensive back-and-forth that you don't have bandwidth for

###### Consider rewarding with merch

- A PR doesn't need to be merged to be reward-able
- Someone took time to care about PostHog and merch is a great way to say thank you

##### Managing expectations

The reality is that support hero weeks vary significantly in intensity across teams and time periods. Some weeks you might have capacity to thoroughly review several PRs; other weeks, you might barely have time to acknowledge them. That's okay. The goal is to engage with external contributions in good faith within your available bandwidth, not to maintain a perfect response rate at the expense of customer support or your well-being.

If you find yourself overwhelmed, remember:

- Customer issues come first
- A brief acknowledgment is better than nothing
- It's acceptable to hand off complex PRs to the next support hero
- Teams aren't expected to handle unlimited PRs

The key principle: We want to be responsive to our open-source community when we can, but not at the cost of our primary support responsibilities or team sustainability.

### What about SDK support?

The SDK Support Hero rotation is owned by the . See the dedicated SDK support rotation page for details on how the rotation works, including how to prioritize time and handle mobile SDK issues.

### Don't ask users to do work that you can do!

If folks are asking us for help, then we know the product already didn't meet their needs. Asking them to do leg-work that we could do is adding insult to injury.

For example don't ask them what version of posthog-js they're using or what their posthog config is when you can find out for yourself. Or visit their website and check the console instead of asking them if they had any errors.

If you do then have to ask them to do something, make sure you explain why you need it and what you're going to do with it.

### How do I communicate?

There are two valid modes (which overlap!)

1. excited, like a labrador puppy, to discover a new way to improve the product
2. clinical and clear

#### Excited like a labrador puppy

The first is great for when you're talking to someone with feedback or who doesn't seem frustrated. It's important because every single support interaction is an opportunity to ship a fix or an improvement. And the excitement is how we show enough interest to properly hear the feedback.

example: "You can't do that right now, but it sounds super useful. Out of interest what does it unlock for you?"

#### Clinical and clear

The second is great for when the issue is tricky or the customer seems frustrated. Sometimes this goes as far as communicating in bullet points instead of paragraphs. When something isn't working the person might (quite rightly) have low tolerance for a support interaction.

example: "Ah, I see what you mean, that's not ideal! Sorry. I'll dig in to that now and let you know what I find by the end of tomorrow."

#### General tone

As an engineer, when answering a question, your first instinct is to give them an answer as quickly as possible. That means we often forget pleasantries, or will ignore a question until we've found the answer. So, the following guidelines:

- Always respond to a question within a reasonable timeframe during your working day. Our SLAs are explained here, but you should always try to respond to tickets quickly.
- If you're ready to look into the issue, and you think it might take a while/require a fix, just mention that and say you'll get back to them
- If you have no idea how to answer or fix their issue, @mention someone who does
- They need to know we've understood them. And have a clear picture of what their onward journey is. Are they waiting for us? How Long? Or - are we waiting for them? what for?
- Start your response with `Hey [insert name], ...` and make sure you're polite, not everyone you talk to is an engineer and as accepting of terse messages
- If they expressed frustration, acknowledging it ("Sorry for the confusion", "Apologies for the trouble" etc.) can earn goodwill quickly.
- Be sure to thank them for reporting problems, giving feedback, creating issues, PRs, etc.
- Even if you're using the support portal think about whether they'll see the message in Slack or email. A Slack message that reads like an email seems weirdly formal.
- Follow up!
- Housekeeping. Once a customer issue/question has been addressed, close the ticket in Zendesk (mark it `Solved`) to make it easy to identify outstanding conversations.
- If a user has been particularly helpful, such as raising a security or bug report, feel free to offer a small credit for the merch store.

If you have any questions about how or when to communicate with users, you can always ask the for help.

### How do I prioritize?

As a business we need to ensure we are focusing support on our paying customers, as such this is the prioritization order you should apply as Support Hero. At the end of your rotation you need to ensure that any items in 1-5 are resolved or passed to the next Support Hero _as a minimum_.

1. Any requests where you are tagged by the Customer Success team in a dedicated Slack channel, as there will be some urgency needed.
2. `Open`, `escalated` Zendesk tickets for your team that have `Sales/CS Top 20`\* priority.
3. `Open`, `escalated` Zendesk tickets for your team that have `High` priority.
4. `Open`, `escalated` Zendesk tickets for your team that have `Normal` priority.
5. `New` and `Open`\\ (non-escalated) Zendesk tickets for your team that are nearing breach or have breached SLAs
6. `Open` Zendesk tickets for your team that have low priority.

\* Try to be especially responsive to any customers marked as `Sales/CS Top 20`. This set of customers is regularly reviewed by the sales team, and this priority is applied to those customers we'd like to have an especially fantastic support experience.

\\ Due to the way we're using Pylon, "new" tickets from high prio customer Slack channels only appear as `New` in Zendesk for a few seconds, then a webhook updates the ticket and quickly changes it to `Open`.

#### What if I need to confirm priority by checking a customer's MRR?

You've got a couple of options. By order of quickness:

1. Use the VIP Lookup Bot:

In any Slack channel, type `@VIP Lookup Bot [Customer]` (without the brackets.) 'Customer' can be the organization name (case-sensitive), or their organization ID. It does work, but the results take up to 30s to load.

1. In Zendesk:

Click the org name near the upper-left of the ticket. The left sidebar opens. There you'll see which plan they're on. If they've already paid some bills, you'll also see MRR there.

#### How will I know if a ticket is nearing a breach of our SLA targets?

Alerts are posted to Slack for every team which has a "group" in Zendesk. The alerts are posted to the `support-` channel for the team (or the `team-` channel for the team if the team has no `support-` channel.)

Alerts are posted for a ticket 3 hours before it breaches the next SLA. If the ticket remains untouched an hour later, another alert will be posted at 2 hours before it breaches an SLA, and again 1 hour before it breaches an SLA. The maximum number of alerts that will be posted for a single ticket is 3. (You can remove the `sla-warning` tags from a ticket if you want the alerts to be sent again for that ticket.)

### How should I handle self-hosted setups?

It's fine to politely direct users to the docs for self-serve open-source support and ask them to file a GitHub issue if they believe something is broken in the docs or deployment setup. We do not otherwise provide support for self-hosted PostHog.

### How should I handle organization ownership transfers?

In case a user requests for organization permissions to be altered (e.g. the only member with owner membership left the company) follow these steps:

1. The ticket should be assigned ideally to Platform features
2. Ask the user to get the current owner to log in and update ownership.
3. If the owner left and they can get access to the current owner’s email, ask them do a password reset and then login as the owner and perform the action themselves.
4. If not, we should email the account owner’s email to see if we get a bounce back. Also check how long it is since they logged in.
5. If accessing the current owner's email is not an option, we should have the person requesting access verify their domain ownership by providing a TXT record example for posthog verification.
6. Once verified, membership can be updated for the request.
7. Note, if they’re on a paid plan we might also need to switch the contact on Stripe via a separate request to billing @posthog.com

### How should I handle 2FA removal?

1. Send the following email to the account owner:

    Subject: Confirmation Required: Removal of 2FA on your PostHog Account

    Hi [name],

    According to ticket #XXXX, you mentioned wanting to remove the current 2FA method. Could you please confirm this by replying to this email?

    If you haven't requested this change, please let me know immediately.

    Best,
    [your name]

1. After the user responded and confirmed the change, delete their TOTP device (EU link).

### How do I use Zendesk?

We use Zendesk Support as our internal platform to manage support tickets. This ensures that we don't miss anyone, especially when their request is passed from one person to another at PostHog, or if they message us over the weekend.

Zendesk allows us to manage all our customer conversations in one place and reply through Slack or email.

Zendesk is populated with new tickets when issues are sent via the in-app Support panel (the `Help` tab in the righthand sidebar), from people outside the PostHog GitHub organization adding issues to the `posthog` and `posthog.com` repos, and new community questions. High priority customers also have Slack channels they can post support questions in. We can create Zendesk tickets from Slack questions via Pylon.

The Zendesk tickets will include links to the GitHub issue, Slack thread, or the community question so we can answer in the appropriate platform. After replying to a community question, make an `internal note` on the Zendesk ticket confirming that you've replied outside of Zendesk, and set the ticket status accordingly when submitting the internal note.

#### Accessing Zendesk

You can access the app via posthoghelp.zendesk.com.

The first time you sign into Zendesk, please make sure you include your name and profile picture so our users know who they are chatting with!

#### Using Zendesk

You’ll spend most of your time in the Views panel, where you’ll find all tickets divided into different lists depending on who they are assigned to, and whether they have been solved or not.

Tips:

- Err on the side of Solving tickets (see below) if you expect no further input from the customer, as a lot of them don't reply to confirm that the problem has been solved.
- Provide actionable information as an _Internal Note_ on the Zendesk ticket (e.g. partial investigation, notes for escalating or transferring to a different team, etc.). Do not use internal notes to communicate internally about a ticket, it is far too easy to miss these notes (see below!).
- Use _side conversations_ from Zendesk to Slack to communicate about a ticket internally. Slack is our primary communication tool and therefore it's much easier to have a discussion in Slack than through Zendesk internal notes. Side conversations can be started from the right hand side panel in Zendesk:

Image: Opening side conversations

#### Creating tickets on behalf of users or from existing tickets

Sometimes users will contact us over Twitter, or email, asking support questions. Sometimes they will respond to old, solved ticket threads with new problems, or tickets will spiral into multiple issues. In both situations it's best to create a new ticket for the user so we can apply the correct SLAs and keep issues distinct for easy assignment.

You can ask a user to create a new ticket themselves, but it's best if we do it for them. The easiest way to do this correctly is to login to PostHog as the user, and then create a fresh ticket on their behalf using the information you have. This will ensure the correct tags, SLAs, and so on are automatically applied.

If the user raised the issue in a public forum, such as Twitter, it can be a good idea to tell them you've opened a ticket on their behalf. If the user was replying to an old, already solved ticket, you should mark the old issue to `Closed`.

##### Avoiding duplication of effort in Zendesk

Each team handles Zendesk queues (views) in slightly different ways. Check in with your team about whether or not to assign tickets to yourself, or keep them assigned to the team/group level. Support team folks, who work on tickets from multiple queues, often assign tickets to themselves, (and when escalating, will assign the ticket back to the team/group.)

For unassigned tickets, keep an eye out for whether someone else is already viewing a ticket (will appear in the upper-left of a ticket you're viewing, with their name, avatar and `also viewing`.) Use those as clues to avoid working on a ticket that someone is already working on (and communicate with each other when in doubt. Err on the side of making sure the ticket gets responded to within SLA/response target times.)

Also, avoid cherry-picking tickets. Pick the ticket that is closest to breaching our response targets.

##### Ticket Status

When responding to a ticket you should also choose an appropriate status according to the following:

- New - A newly created ticket, you shouldn't need to use this when responding (Note: Some tickets, such as tickets created via Slack, are changed from `New` to `Open` by automated internal notes added just after the ticket is created.)
- Open - The ticket is still awaiting a response/further investigation from someone in PostHog (if you've worked on the ticket and expect someone else to work on it next, make sure the other person/team knows about it by leaving an internal note on the ticket.)
- On-Hold - (_pauses the SLA timer_) Use this one sparingly, GitHub is better for tracking open bugs, feature requests, and technical debt, and `On-Hold` tickets are too easily overlooked. If you do need to put a ticket `On-Hold`, reply to the ticket to let the customer know. (If you've opened a bug ticket or feature request, `On-Hold` isn't needed, see `Solved` below.)
- Pending - (_pauses the SLA timer_) Use this for most replies to customers. Even if you think the issue is solved, the user may disagree, so `Solved` may not spark joy. When a user doesn't reply to a `Pending` ticket within 7 days, the ticket is auto-solved.
- Solved - (_stops the SLA timer_) The user has replied to confirm that the ticket is resolved, or you've created a bug report or feature request and shared the link with the user so they can follow it for updates.

##### Temp orgs for free email users

To reduce some unintended consequences of Zendesk's unavoidable use of email address domain names to associate users with organizations, we have Zendesk orgs for common free email providers.

An example of these orgs: `Gmail user - please assign to correct org`

When we get a ticket from a user with an `@gmail.com` address who has not already been manually assigned to an existing Zendesk org, that user will be assigned to the `Gmail user - ...` org (unless their PostHog org doesn't exist in Zendesk yet, in which case the correct org will be created in Zendesk.)

When you see a user assigned to a free email org on a ticket, and it is not a 'community question' ticket, please assign the user to their correct org, which is found on the `Admin` info line in the body of the ticket:

1. Click on the user's name, to the right of the org name
2. Click in the `Org.` field to change the org name
3. Click anywhere outside the field to save the change

Tickets which have been set to Pending will auto-solve after 7 days. Customers can also respond within 20 days to a Solved ticket to re-open it. After 20 days, responses will create a follow-up ticket with a link to the original ticket.

Tickets that have been `Solved` will receive a CSAT survey the next day.

##### Content Warnings

We have a clear definition of who we do business with which means that customers who track adult or other potentially offensive content aren't automatically excluded. To avoid team members inadvertently seeing anything offensive when impersonating a customer we will automatically tag tickets from Organizations known to have this type of content with a `content_warning` tag.

This looks at the Content Warning field on the Zendesk Organization, and adds the tag if there is text in that field. If you see this tag on a ticket and want to understand more then click on the Organization name in the top left corner of the Zendesk UI and scroll down the list of fields on the left.

If you do discover any potentially offensive content in a customer account then please update this field on the Zendesk Organization so that other team members are aware of the content.

#### Pylon to create Zendesk tickets from Slack posts

We use Pylon to create Zendesk tickets from Slack posts. To do so, add the `:ticket:` (🎫) emoji reaction to the post that you want to create a Zendesk ticket from.

Adding the `:ticket:` emoji reaction will cause Pylon to add a couple of replies in a thread under the post. The last of those replies includes options for the Zendesk ticket you're creating: Use the `Group` menu to send the ticket to the appropriate team, and the `Severity` menu to set the severity flag on the Zendesk ticket, then hit the `Submit` button.

Zendesk tickets created this way will normally be marked as high priority tickets. You can respond to them either in Zendesk or Slack, as there is a two-way sync.

#### Adding new teams to Zendesk.

When we've added a new team, or 🪓 split an existing team into two or more, we'll need to get them set up in Zendesk. Here's an overview of the steps:

- Create a new group in Zendesk
- Add team members to the group
- Add triggers to the `Routing for internal teams` category (Tip: Clone an existing trigger, rename it, and tweak it)
- Add views (Tip: Clone an existing view, rename it, and tweak it.)
- Add Slack notification triggers (Tip: Clone an existing trigger, yada, yada)
- Add SLA breach alerts
- Create a webhook endpoint in slack
- Create a Slack app
- Enable incoming webhooks
- Create a webhook to the channel, copy the url
- Create a webhook in zendesk (Tip: Refer to existing webhooks for common settings)
- Choose "Trigger or automation"
- Paste the endpoint url you copied from the Slack app

(Note: The built-in tool for testing webhooks in ZD has been flakey while the UI has been changing lately. Failed tests don't always mean the hook won't work. 🫤)

- Create an automation in zendesk (Tip: Clone an existing automation, blah, blah, blah)
- If you've split a team, sort the tickets to the new groups as needed, then disable the triggers, automations, and views related to the old team.
- Carry on

#### Community questions

At the end of every page in the docs and handbook is a form where visitors can ask questions about the content of that page. (These questions also appear in the relevant category in the PostHog community.)

Community questions appear in Zendesk and tickets are closed automatically if an answer is picked as a solution on the website. Ideally, the original poster is the one who marks a response as the solution. If they don't, feel free to close the ticket in Zendesk once you've replied.

### How do I answer community questions?

When a question is posted, it'll appear in Zendesk with a direct link to the question. A notification is also sent to the #community-questions channel in Slack. (You can also receive notifications about specific topics in your own small team's Slack channel. Ask the Website & Docs team for help in setting this up if you like.)

You can answer a question directly on the page where it was asked. When a reply is posted, the person who asked the question will receive an email notification. (Important: Don't reply to community questions directly from Zendesk.)

The first time you answer a question, you'll need to create a community account. (You'll be prompted to do this after answering a question, as posting/responding requires authentication.)

Ask in #team-website-and-docs to be upgraded to a moderator. This will also give you access to moderator controls available for each question.

_Note: The PostHog.com community currently uses a separate authentication system from PostHog Cloud. There are plans to support other types of authentication so a visitor doesn't have to create a separate account for asking questions._

### How do I handle a bug report or feature request?

For feature requests from low priority users, give them this link and suggest they open a feature request.

For bug reports from normal and high priority users (assuming you've confirmed it's a bug, and that there's not already an open bug report):

1. Open a bug report on our GitHub repo
2. Be sure to include a link to the insight (or other), below the repo steps
3. Include "From: `https://URL_for_Zendesk_ticket`" in the `additional info` section of the bug comment (where the URL is for the Zendesk ticket where the customer reported the bug)
4. Reply to the user to thank\* them for alerting us to the bug. Let them know you've opened a bug report and provide a link to it.
5. Let them know they can follow the bug report on GitHub for updates.
6. When sending the reply, change the ticket from `Open` to `Pending`
7. In Slack, go to the team channel for the team that handles the feature that the bug report applies to (e.g. `#team-product-analytics`) and alert them with a post like "New bug report from a high priority customer: `https://github.com/PostHog/posthog/issues/nnnnnn`"

`*` consider sparking additional joy with a credit for merch

Steps for feature requests from normal and high priority users are pretty much the same, but use this form instead. If you find that there's already a matching feature request open, reply with a link to the feature request, and let them know they can upvote it by adding a "`+1`" comment.

### How do I handle user requests to delete groups/organizations?

> _WARNING:_ Do NOT click the `DELETE` button! That will delete the entire project!

> Just use the `Save` button after clicking the `delete` checkbox for the group.

1. Visit the Django Admin page for the project at `https://us.posthog.com/admin/posthog/team/:project_id/change/` (Make sure you use the project ID for the project where the group/org is found)
2. In the lower part of the page, find `GROUP TYPE MAPPINGS` and click on `SHOW`
3. In the righthand column, check the box for the group(s) to be deleted
4. Click the `SAVE` button. (Do NOT use the `DELETE` button!)
5. Reply to the user to confirm

Canonical URL: https://posthog.com/handbook/engineering/operations/support-hero

GitHub source: contents/handbook/engineering/operations/support-hero.md

Content hash: `cbc8ecf8f0fd2b8e`

Static reader notes

- `MDX_COMPONENT_STATIC_ADAPTER`: Adapted interactive MDX components for static reading: SmallTeam.