Access is invite-only during beta. Once invited, create a key to personalize these examples. Production sending requires a separate review.
Switching from Amazon SES
Keep your From domains and message content while replacing SES authentication, regional endpoints, event destinations, and optional receipt rules without duplicate production sends.
Keep HTTP or SMTP. Replace SES identities, IAM or SigV4, regional credentials, event destinations, and inbound routing.
Run both providers during migration
Run Amazon SES and PostShiba side by side, but route each new production message to exactly one provider. Use a stable cohort or deterministic feature flag. Record the provider before submission. Never send the same message through both.
One adjustable 30-day example is:
- Days 1-3: SES production traffic; controlled PostShiba tests.
- Days 4-10: 10% PostShiba.
- Days 11-17: 25% PostShiba.
- Days 18-24: 50% PostShiba.
- Days 25-30: 100% PostShiba.
Adjust the timing and percentages for your traffic. Advance only while send errors, delivery events, bounces, spam reports, and suppressions stay within your accepted ranges.
PostShiba uses shared IPs. The ramp tests the integration and establishes steady traffic. It does not warm a dedicated IP.
Keep SES credentials, event consumers, and DNS until rollback closes. The providers can coexist only when their DKIM selectors and return-path hostnames do not collide. If they collide, use a separate PostShiba sending subdomain during the ramp.
Cut over inbound mail separately. Equal-priority MX records cannot split traffic by percentage. Test with a hosted inbox or new subdomain, then switch MX.
Inventory and prerequisites
Before you change traffic:
- For each Region, record identities, sandbox status, endpoints, SMTP credentials, and feedback settings. Use Regions and Amazon SES.
- Find every
SendEmail,SendRawEmail, SESv2SendEmail, and SMTP caller. Record its IAM principal, From domain, and rollback owner. - Export configuration sets, message tags, SNS and EventBridge consumers, and CloudWatch alarms. See how configuration sets and tags enter an SES send.
- If you receive mail, export active receipt rules, conditions, AWS actions, and MX records. Check the SES receiving prerequisites.
- Confirm DNS control, choose test recipients, note DNS TTLs, and define the rollback window.
Map the concepts
| Amazon SES | PostShiba migration |
|---|---|
| AWS account and IAM principal | Team and team-locked API key |
| Region and API endpoint | Shared cluster and PostShiba REST endpoint |
| Email identity or exact From host | Verified sending domain for that exact host; any local part on it |
| Regional SMTP credential | Cluster credential scoped to a tenant |
| Configuration-set event destination | Webhook scoped to a team, cluster, or tenant; other behavior stays application-owned |
X-SES-MESSAGE-TAGS or API message tags |
unique_args or X-Capsule-Unique-Args as a JSON object |
| Regional sandbox | Team KYC gate |
| Receipt rule and AWS actions | Inbox with a signed webhook or polling handler |
Prepare PostShiba
- Create a shared cluster, then request KYC approval. Until approval, only members and live inboxes can receive. Other REST sends return
403withkyc_required. - Create an API key under API keys. Store it as a new secret and replace IAM or SigV4.
- If IAM roles separate customers, create matching tenants before their domains and SMTP credentials. Resolve the tenant on your server.
- Add each exact host used after
@, publish its DKIM and return-path CNAMEs, and verify them. Unlike an SES domain identity, verifyingexample.comdoes not verifymail.example.com. Email-only identities do not map. - For SMTP, issue a tenant credential. Use the cluster's returned
smtp_endpointon port 587 with STARTTLS andAUTH PLAIN. Replace regional credentials.AUTH LOGINfails. Otherwise use REST. - Export account-level hard bounces and complaints into the matching tenant suppressions. Keep list-specific preferences in your application.
Bring your suppressions
Import the SES account-level suppression list before you send. A missed row is a complaint on the new cluster.
Export suppressed destinations from the SES console or ListSuppressedDestinations. If IAM roles separate customers, import each list under the matching tenant.
Upload the CSV on Suppressions, or post the addresses:
Use a column named email, address, or recipient, or one address per line. Existing rows are skipped. Max 10,000 addresses per request. See Suppressions.
Move one outbound path
Replace structured SES SendEmail with POST /api/v1/emails and a Bearer token. Convert X-SES-MESSAGE-TAGS: order_id=ord_123, source=checkout to unique_args:
Expect 201, queued: true, and a message_id. Check the unique_args limits.
POST /api/v1/emails has no idempotency key. For ambiguous responses, use cluster-specific POST /sends with Idempotency-Key, or reconcile before retrying.
For SendRawEmail or SESv2 Raw, keep your MIME builder and use SMTP or HTTP inject. /api/v1/emails accepts structured fields, not raw RFC822.
Remove X-SES-CONFIGURATION-SET and configuration-set parameters. PostShiba has no per-message configuration-set selector. Route events with webhook scopes.
Move delivery events
Create a webhook scoped to the team, cluster, or tenant. Replace each SES destination with it. Forward events into AWS if needed.
PostShiba sends a JSON array with unique_args both flattened and nested. It emits processed, delivered, deferred, bounce, dropped, spamreport, and unsubscribe, but not open or click events.
Map SES Send to processed, Delivery to delivered, DeliveryDelay to deferred, Bounce to bounce, and Complaint to spamreport. Handle PostShiba dropped and unsubscribe as new branches.
Handle SES Reject and Rendering Failure replacements in the synchronous send path. PostShiba has no matching webhook.
Before parsing JSON, verify the raw body using X-Capsule-Timestamp, X-Capsule-Signature, and the endpoint secret. Follow the webhook verification guide.
Move inbound mail when used
Skip this step without an active SES receipt rule set.
Create a hosted or domain-bound inbox. Domain-bound addresses use {local-part}@{host}; the default host is inbound.your-domain. They do not have to replace local-part@your-domain. Change Reply-To, or keep SES.
Replace S3, SNS, and Lambda receipt-rule actions with a signed webhook or poller. Test a hosted inbox or new subdomain, then switch inbound.your-domain MX once. Verify the message, attachments, signature, and handler. Keep SES rules ready.
Cut over and roll back
- Confirm KYC approval,
sending_ready, and verified From domains. - Test a controlled recipient. Require
201for HTTP and a signeddeliveredevent with the sameorder_idfor HTTP or SMTP. - Treat each outbound stage as a gate. Stop when a check leaves its accepted range.
- Move inbound DNS only after its webhook passes. Retire SES event consumers after outbound finishes.
For outbound rollback, route only new, unsent messages to SES. Do not resend a PostShiba 201 while waiting for its delivery event. For inbound rollback, restore the SES MX and run both handlers through the DNS TTL. Remove SES resources only after rollback closes.
Final checklist
- Inventory covers every Region, identity, caller, configuration set, destination, and receipt rule.
- KYC, cluster readiness, credentials, and domain verification are complete.
- A controlled send returned
201and a verified delivery event withunique_args. - The migrated event path no longer depends on opens or clicks.
- Inbound mail passed through the new handler, with the SES MX recorded for rollback.
- The SES suppression list is imported per tenant.
- Each new production message routes to exactly one provider.
- SES credentials, event consumers, and DNS remain until rollback closes.