Set up PostShiba the right way.

Clusters, subdomains, tenants, suppressions, and keys, in the order that keeps mail flowing.

9 min read

PostShiba is email infrastructure for a SaaS platform that sends on its customers' domains. The setup that stays healthy is boring on purpose: one team, two cluster types, a sending subdomain per stream, and a tenant per customer. This lesson is that blueprint.

One team, two clusters

Create one team. Put every cluster, tenant, domain, and key under it. Splitting across teams makes suppressions, webhooks, and Network harder to see in one place.

A cluster is a named sending environment with its own hourly and 24-hour cap. Every send, SMTP credential, and delivery event belongs to one cluster. Customer clusters are shared-IP.

Create two clusters when you send both kinds of mail: one transactional, one bulk. The type is locked after create. Receipts and password resets go on transactional. Campaigns and newsletters go on bulk. Never mix them. A bulk cluster also adds one-click List-Unsubscribe when the message has a single recipient and you have not set your own header. Transactional clusters never get that header.

Until production approval, you can create one shared cluster and send to your team. Other sends return kyc_required. There is no published wait time. Size the first cluster for the busiest hour you actually have. You can resize later.

Sending domains that stay out of the way

Verify a sending subdomain per stream, not the root. Use mail.example.com for transactional mail and news.example.com for bulk. Once a host verifies, you can send from any address on it. There is nothing else to create.

Root MX stays with Google, Microsoft, or whoever hosts you@example.com. PostShiba does not touch that record. A sending subdomain keeps inbound mail working.

Publish the two records from Add a domain: the DKIM CNAME and the rp. return-path CNAME. Send waits on DKIM. Then add DMARC at p=none on the organizational domain and tighten it later, once rua reports look clean. Leave root SPF and MX alone. SPF is checked against the return-path host, which PostShiba answers through the rp. CNAME.

Tenants if you send for customers

The default tenant, slug default, is enough when you send as your own domains. Extra tenants are how a platform keeps customers apart.

Create one tenant per customer, with a slug you will recognize such as acme-florist. Each extra tenant has its own sending domains, SMTP credentials, inboxes, suppression list, and webhook endpoints. A domain belongs to one tenant. An SMTP credential can only send as its tenant's domains.

You can suspend one tenant, or one sending domain, and keep everyone else sending. That is the point. A complaint on acme.example should not pause mail.example.com.

Pass tenant on each send, or use that tenant's SMTP credential. REST sends without tenant use default. Creating tenants, domains, and credentials needs a Full access key. The app that sends needs only a Send only key, which works for every tenant. The multi-tenant guide has the routing table.

Suppressions and the firewall

Import your suppression list before the first send. Hard bounces, spam reports, unsubscribes, and manual rows from the old provider belong on the list on day one. Every bounce from an address you already knew was bad counts against a new IP and a new domain.

PostShiba adds rows on its own after that. A hard bounce, a spam report, or a one-click unsubscribe on a bulk cluster lands on the sending tenant's list. Plus tags are ignored when matching, so user+promo@example.com matches user@example.com. A send skips suppressed addresses and lists them in suppressed. If every recipient is suppressed, REST returns 403 suppressed.

Turn on the email firewall before you open the send path. Every check starts off. Enable temp mail at least. Add plus-addressing if you do not want user+tag recipients. Free-mailbox blocking is there when a product should not mail Gmail or Yahoo. Never-send-to and always-allow lists cover the rest. A blocked REST send returns 403 firewall. SMTP returns 550 firewall.

On bulk clusters, one-click unsubscribe suppresses the address on the sending tenant. Later sends from that tenant skip it.

Delivery webhooks

Subscribe to delivery webhooks before you send real traffic. PostShiba emits seven events: processed, delivered, deferred, bounce, dropped, spamreport, and unsubscribe. A new endpoint subscribes to all seven. Tick unsubscribe on any older endpoint that predates it.

For warm-up and incident response, the ones to act on first are bounce, spamreport, unsubscribe, and deferred. Those four tell you to hold a ramp, pause a tenant, or import a missing suppression. The event types page lists every field.

PostShiba does not emit open or click events. Endpoints accept those names for SendGrid compatibility and never send them.

Keys

Three access levels, each for a different place.

Key Where it lives What it can do
Send only The app that sends POST /api/v1/emails, the cluster POST /sends, and GET /api/v1/users/me. Nothing else.
Full access Your shell, setup scripts, CLI, and MCP The rest of the REST API: clusters, domains, tenants, Network, webhooks, suppressions.
Support The support team Look up a recipient, read analytics and status, and remove a suppression. Cannot send.

Create a Send only key per app and environment. Keep Full access keys off deployed servers. A leaked Send only key can still send as any verified domain, so delete it if it escapes. Never put either key in browser or mobile code. Create an API key walks through the dashboard.

SMTP and HTTP inject use cluster credentials, not API keys. Issue one SMTP user per tenant on a sending-ready cluster, and copy the password when you see it.

IPs and warm-up

Stay on shared IPs until volume is steady. Then buy dedicated IPs and put them in IP pools when a stream, a tier, or a customer needs a reputation of its own.

A new dedicated IP starts a 14-day warm-up when it first joins a cluster or a pool. It takes about 100 messages a day while warming. With Use the cluster's IPs while warming up on, the rest goes out on the cluster's shared IPs. Ramp per provider on the guide's schedule. Hold a provider when bounces rise above 2%, spam reports rise above 0.1%, or deferrals jump. Gmail and Yahoo act on spam reports at 0.3%.

A good first week

  1. Create the team, add a payment method, and request production approval.
  2. Create a transactional cluster. Create a bulk cluster only if you send campaigns.
  3. Add mail.example.com (and news.example.com if you have bulk). Publish DKIM and the rp. return-path. Confirm both verify.
  4. Publish v=DMARC1; p=none; on the organizational domain. Add rua if you have a mailbox for reports.
  5. If you send for customers, create one tenant per customer and add their sending domains under that tenant.
  6. Import the suppression list. Turn on the email firewall, starting with temp mail.
  7. Create a webhook endpoint and confirm it receives bounce, spamreport, unsubscribe, and deferred.
  8. Create a Send only key for the app and a Full access key for the shell. Issue SMTP credentials per tenant.
  9. Send a test to your team from each cluster. Stay on shared IPs.
  10. Read warm-up before you buy a dedicated IP. Do not buy one in the first week unless a recipient already needs a fixed address.

Tick the same steps below. The checklist stays in this browser.

Your setup checklist.

Work through these before you send to real inboxes.

0 of 11 done

That is the shape. One team. Clusters that never mix types. Subdomains that leave root MX alone. Tenants that isolate a customer. Suppressions and the firewall before the first send. Webhooks you actually read. Keys that match the job. Shared IPs until the volume is real, then a pool you warm on purpose.

Check what stuck.

A few questions. Two right marks the lesson done.

Why do transactional and bulk mail need separate clusters?
Why create one tenant per customer on a platform?
Which API key belongs in the app that sends mail?

Send from a domain you trust.

Start a PostShiba trial, verify your domain, and put this lesson to work.