{"id":562,"date":"2026-11-14T01:46:48","date_gmt":"2026-11-14T07:16:48","guid":{"rendered":"https:\/\/photonconsole.com\/blog\/?p=562"},"modified":"2026-11-14T08:47:53","modified_gmt":"2026-11-14T14:17:53","slug":"migrating-from-postmark-streams-templates-and-cutover","status":"publish","type":"post","link":"https:\/\/photonconsole.com\/blog\/migrating-from-postmark-streams-templates-and-cutover\/","title":{"rendered":"Migrating from Postmark: Streams, Templates and Cutover"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The migration goes cleanly. Templates ported, credentials swapped, delivery rates holding. Nobody notices anything for about three weeks.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then a customer says they never received a password reset. Then another. You check, and your transactional mail is landing in spam at Gmail \u2014 not because anything broke, but because the monthly newsletter you now send down the same pipe has been quietly teaching Gmail that this sending identity is bulk mail.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Postmark was preventing that. Not as a feature you configured, but as an architecture it enforced. It is the one thing that does not survive the move unless you deliberately rebuild it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Answer: What Moves and What Rebuilds<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Asset<\/th><th>Moves or rebuilds<\/th><th>Effort<\/th><\/tr><\/thead><tbody><tr><td>SMTP credentials<\/td><td>Moves \u2014 four variables<\/td><td>Minutes<\/td><\/tr><tr><td>Templates<\/td><td>Export into your repository<\/td><td>Hours<\/td><\/tr><tr><td>Suppression data<\/td><td>Export per stream, import first<\/td><td>Before first send<\/td><\/tr><tr><td><code>MessageStream<\/code> references in code<\/td><td>Remove or remap<\/td><td>Hours<\/td><\/tr><tr><td>Webhooks<\/td><td>Remap payloads and verification<\/td><td>Hours<\/td><\/tr><tr><td><strong>Stream separation<\/strong><\/td><td><strong>Rebuild yourself, with subdomains<\/strong><\/td><td>The real work<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Everything above the last row is an afternoon. The last row is the migration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sequencing\u2014DNS TTL, SPF lookup limits, the percentage ramp, rollback \u2014 is covered in our guide to <a href=\"https:\/\/photonconsole.com\/blog\/migrate-email-provider-without-downtime\/\">migrating email providers without downtime<\/a>. Follow that ordering alongside this.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Postmark Was Doing For You<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity-1024x576.png\" alt=\"Postmark's separate transactional and broadcast IP pools with an enforced barrier between them, compared with a single shared sending identity after migration\" class=\"wp-image-564\" style=\"aspect-ratio:1.7777777777777777;width:1200px;height:auto\" srcset=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity-1024x576.png 1024w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity-300x169.png 300w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity-768x432.png 768w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity-1536x864.png 1536w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Before-and-After_-Shared-Sending-Identity.png 1672w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">Two reputations become one. That is the risk, and it is invisible for weeks.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Most providers treat separating transactional from marketing mail as a best practice you may choose to follow. Postmark treats it as a property of the system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Its <a href=\"https:\/\/postmarkapp.com\/message-streams\" target=\"_blank\" rel=\"noopener\">message streams documentation<\/a> states plainly that &#8220;transactional and broadcast traffic do not mix in Postmark, including IP ranges.&#8221; There is a dedicated transactional IP pool and a dedicated broadcast IP pool, and a message goes down one or the other depending on which stream you send it to.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So if you have been sending password resets through a transactional stream and a newsletter through a broadcast stream, those two have been running on separate sending infrastructure the whole time. One could have a bad month without touching the other.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Move to a provider that does not enforce that, send both through the same credentials, and the two reputations merge. Postmark&#8217;s own <a href=\"https:\/\/postmarkapp.com\/blog\/bulk-vs-transactional\" target=\"_blank\" rel=\"noopener\">write-up on the subject<\/a> describes the failure mode: when you use the same servers and address for both, filters such as Gmail&#8217;s may start classifying all of it as bulk. It also cites Google&#8217;s own guidance to separate mail by purpose as far as possible \u2014 advice <a href=\"https:\/\/support.google.com\/mail\/answer\/81126\" target=\"_blank\" rel=\"noopener\">Gmail publishes for all senders<\/a>, not just Postmark customers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Common Mistake<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Treating stream separation as a Postmark feature rather than an email architecture. It reads like vendor functionality, so it gets dropped from the migration plan along with the stream API \u2014 and because reputation damage accumulates over weeks rather than appearing on cutover day, the migration looks like a success right up until transactional deliverability starts sliding. By the time anyone connects the two, the newsletter has been training receivers on your sending identity for a month. Rebuild the separation before the first marketing send, not after you see a problem.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Streams Are Not Just a Routing Label<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before you can remove them from your code, it helps to know exactly what you have.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Stream type<\/th><th>What it carries<\/th><th>API value<\/th><\/tr><\/thead><tbody><tr><td>Transactional<\/td><td>One recipient, triggered by a user action<\/td><td><code>outbound<\/code><\/td><\/tr><tr><td>Broadcast<\/td><td>Many recipients, sent on your schedule; requires an opt-out link<\/td><td><code>broadcast<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Two details catch people out.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">First, <strong>the default transactional stream&#8217;s API value is <code>outbound<\/code>, not <code>transactional<\/code><\/strong>. If you are grepping for stream references by name, searching for &#8220;transactional&#8221; will miss most of them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Second, a Postmark server supports up to 10 streams. Accounts that have been running for a few years often have more than the two obvious ones \u2014 a separate stream for a legacy product, one somebody created for testing, one for a specific client. Enumerate them rather than assuming there are two.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick Fix<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finding Every Postmark Integration Point<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Grep for <code>MessageStream<\/code> \u2014 the field name is the most reliable marker<\/li>\n\n\n\n<li>Grep for <code>outbound<\/code> as a string literal; the default transactional stream uses it, not the word &#8220;transactional&#8221;<\/li>\n\n\n\n<li>List every stream on every server, not just the two you expect \u2014 up to 10 are possible<\/li>\n\n\n\n<li>Note which stream each code path sends to; that mapping becomes your subdomain plan<\/li>\n\n\n\n<li>Check your MX records \u2014 if Postmark also receives mail for you, that is a second migration<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Rebuilding the Separation Yourself<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img decoding=\"async\" width=\"1024\" height=\"576\" src=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations-1024x576.png\" alt=\"Transactional and marketing mail separated across two sending subdomains, each with its own SPF record, DKIM selector and reputation, both sending through one SMTP relay\" class=\"wp-image-565\" style=\"aspect-ratio:1.7777777777777777;width:1200px;height:auto\" srcset=\"https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations-1024x576.png 1024w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations-300x169.png 300w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations-768x432.png 768w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations-1536x864.png 1536w, https:\/\/photonconsole.com\/blog\/wp-content\/uploads\/2026\/11\/Two-Subdomains-Two-Reputations.png 1672w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">What the provider used to enforce, you now configure. Two subdomains, two reputations.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The useful thing is that Postmark has already written the specification for you. Its guidance ranks the options: different From addresses alone is &#8220;Good&#8221; and a last resort, different IPs is &#8220;Better&#8221;, and different From addresses, IPs and subdomains together is &#8220;Best&#8221;.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Separation level<\/th><th>What it means<\/th><th>Postmark&#8217;s rating<\/th><\/tr><\/thead><tbody><tr><td>Different From addresses only<\/td><td>Same infrastructure, different sender<\/td><td>Good \u2014 a last resort<\/td><\/tr><tr><td>Different sending IPs<\/td><td>Separate infrastructure, shared domain<\/td><td>Better<\/td><\/tr><tr><td><strong>Different From addresses, IPs and subdomains<\/strong><\/td><td>Fully independent sending identities<\/td><td><strong>Best<\/strong><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">That top tier is what you are reproducing. In practice it means two sending subdomains:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Two sending identities, two reputations\n\n  txn.yourdomain.com     password resets, receipts, alerts\n  news.yourdomain.com    newsletters, product announcements\n\n# Each gets its own SPF record and its own DKIM selector.\n# A bad week on news. does not touch txn.\n# Keep the root domain out of it entirely \u2014 if you ever\n# have to burn a sending reputation, burn a subdomain.<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Each subdomain publishes its own SPF and DKIM records, so each accumulates its own reputation. This is the part that is genuinely better than what you had: you now control the boundary rather than inheriting it, and you can add a third subdomain for a new mail category without asking anyone.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.photonconsole.com\/\">PhotonConsole<\/a> authenticates each subdomain independently, so <code>txn.<\/code> and <code>news.<\/code> are two sets of DNS records rather than two accounts or two bills.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Resist the temptation to use a different root domain for marketing mail. It looks like the cleanest possible separation and it is a trap \u2014 Postmark&#8217;s own guidance warns that an unrelated domain &#8220;could look like a phishing or spoofing attempt&#8221; to receivers, and it also means your marketing mail builds no reputation that benefits your brand. Subdomains of the domain you already send from give you the separation without the suspicion.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Authentication for Two Subdomains<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Each subdomain needs its own records. During the parallel run, the subdomain you are migrating authorises both providers:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># txn.yourdomain.com \u2014 during migration, both senders\nv=spf1 include:spf.mtasv.net include:relay.photonconsole.com ~all\n\n# news.yourdomain.com \u2014 new, so only one sender\nv=spf1 include:relay.photonconsole.com ~all\n\n# DKIM on independent selectors, so both sign in parallel\nphoton._domainkey.txn   CNAME  dkim.photonconsole.com<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Take Postmark&#8217;s exact include from your own account rather than from this article. Then count your lookups: exceeding the ten-term limit in <a href=\"https:\/\/www.rfc-editor.org\/rfc\/rfc7208.html\" target=\"_blank\" rel=\"noopener\">RFC 7208<\/a> returns a <code>permerror<\/code> that fails authentication for <em>both<\/em> providers at once \u2014 the one mistake in a migration that breaks the thing you were trying to protect. Our guide to <a href=\"https:\/\/photonconsole.com\/blog\/spf-dkim-dmarc-explained-simply\/\">SPF, DKIM and DMARC<\/a> covers alignment, and the free <a href=\"https:\/\/www.photonconsole.com\/email-deliverability-checker.php\">email deliverability checker<\/a> shows what each subdomain currently publishes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that a fresh subdomain starts with no reputation at all. That is not a problem, but it does mean the marketing subdomain needs its own warm-up rather than being switched on at full volume \u2014 which is a reason to migrate transactional mail first and marketing second.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Suppression Data<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Streams are the organizing unit for almost everything in Postmark, so export suppressions for every stream you send from rather than assuming a single account-wide list.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick Fix<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Exporting Suppressions Safely<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Export for every stream on every server \u2014 over-collecting costs nothing, missing a list costs deliverability<\/li>\n\n\n\n<li>Keep the export in your own storage, not only in the new provider; this is your data<\/li>\n\n\n\n<li>Import before the first production send, never after<\/li>\n\n\n\n<li>Keep transactional and marketing suppressions mapped to the right subdomain \u2014 an unsubscribe from the newsletter is not a reason to stop sending receipts<\/li>\n\n\n\n<li>Re-export on your final day; addresses that bounced during the ramp exist only in Postmark<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">That fourth point matters more here than in other migrations. Because your streams were separate, your suppression data is separate too, and flattening it into one list means a marketing unsubscribe can silently block a password reset. Keep the lists distinct in the same way you keep the subdomains distinct. Our guide to <a href=\"https:\/\/photonconsole.com\/blog\/how-to-reduce-email-bounce-rate-for-saas-applications-a-production-infrastructure-guide\/\">reducing bounce rate<\/a> explains why importing before the first send matters so much on a new sending identity.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Templates<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Export them into your repository rather than into another provider&#8217;s template store.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Postmark supports layouts that templates inherit from, so check whether yours use one \u2014 a template exported without its layout renders without the wrapper, which is easy to miss in a quick visual check because the content all appears to be there. Flatten the layout into each template, or reproduce the layout mechanism in whatever renders your mail now.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Templates under version control are reviewable, diffable and testable in CI, which also means the next migration is a configuration change rather than a project. PhotonConsole sends whatever HTML your application renders, so there is no second template store to keep in sync.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Then test every template against payloads with missing and null fields before sending one to a real recipient. Renderers differ in how they treat an undefined variable: some output nothing, some output the literal placeholder, and finding out which on a live password reset is an unpleasant way to learn.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">If Postmark Also Receives Your Mail<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Check your MX records before you plan anything. If they point at Postmark, inbound processing is live and it is a separate migration from sending \u2014 with its own cutover, its own testing, and its own failure mode, which is silent in both directions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The pattern for reimplementing inbound handling as application code is covered in our guide to <a href=\"https:\/\/photonconsole.com\/blog\/migrate-from-mailgun\/\">migrating from Mailgun<\/a>, where inbound routing is the central problem. The same approach applies: list the rules, express them as an ordered set with an explicit catch-all, and move inbound only after sending is settled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Validation and Cutover<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before moving production traffic, confirm three things with real sends:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Each subdomain authenticates independently.<\/strong> <a href=\"https:\/\/mxtoolbox.com\/\" target=\"_blank\" rel=\"noopener\">MXToolbox<\/a> confirms the records resolve; <a href=\"https:\/\/www.mail-tester.com\/\" target=\"_blank\" rel=\"noopener\">Mail Tester<\/a> scores an end-to-end send from each one separately.<\/li>\n\n\n\n<li><strong>Templates render correctly<\/strong>, including with missing variables and with the layout applied.<\/li>\n\n\n\n<li><strong>Webhook events parse<\/strong>, tested by triggering a real bounce to a known-invalid address.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Then migrate in this order, which is specific to Postmark and worth following:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Transactional first<\/strong>, ramped by percentage with Postmark still live. This is your highest-stakes mail, so it gets the full parallel-run treatment per <a href=\"https:\/\/photonconsole.com\/blog\/migrate-email-provider-without-downtime\/\">the migration guide<\/a>.<\/li>\n\n\n\n<li><strong>Marketing second, on its own subdomain<\/strong>, warmed up from low volume. It is lower-stakes and the subdomain is new, so it needs the ramp for a different reason.<\/li>\n\n\n\n<li><strong>Inbound last<\/strong>, if applicable, as a separate change.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Doing transactional first is the opposite of what feels safe \u2014 most people want to test on the mail that matters least. But marketing mail from a cold subdomain will have a rough first week regardless, and you do not want to be diagnosing that at the same time as a transactional cutover. Separate the two problems in time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Both providers stay live throughout, and PhotonConsole issues SMTP credentials on signup, so the transactional path can be live and testable the same day you start building subdomains. <a href=\"https:\/\/www.photonconsole.com\/pricing.php\">Pricing<\/a> includes 5,000 free emails a month, which covers the whole parallel-running phase without a second bill arriving mid-migration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pro Tips<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Grep for <code>outbound<\/code>, not &#8220;transactional&#8221;.<\/strong> The default stream&#8217;s API value is the word nobody expects.<\/li>\n\n\n\n<li><strong>Enumerate every stream.<\/strong> Up to 10 per server, and old accounts accumulate them.<\/li>\n\n\n\n<li><strong>Build the subdomains before you touch any code.<\/strong> DNS propagation is the slowest part and it costs nothing to start early.<\/li>\n\n\n\n<li><strong>Keep marketing and transactional suppressions separate.<\/strong> Flattening them lets an unsubscribe block a receipt.<\/li>\n\n\n\n<li><strong>Never send marketing mail from the root domain.<\/strong> If a reputation has to be burned, burn a subdomain.<\/li>\n\n\n\n<li><strong>Check for template layouts.<\/strong> A template exported without its layout looks almost right, which is the problem.<\/li>\n\n\n\n<li><strong>Transactional first, marketing second.<\/strong> Do not debug a cold subdomain and a cutover in the same week.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Related Reading<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/photonconsole.com\/blog\/migrate-email-provider-without-downtime\/\">Migrating email providers without downtime<\/a> \u2014 the sequence and timing this article defers to<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/postmark-pricing\/\">Postmark pricing explained<\/a> \u2014 if cost is what started this<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/migrate-from-mailgun\/\">Migrating from Mailgun<\/a> \u2014 where inbound routing is the hidden half<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/migrate-from-sendgrid\/\">Migrating away from SendGrid<\/a> \u2014 where templates and six suppression lists are the lock-in<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/migrate-from-amazon-ses\/\">Migrating from Amazon SES<\/a> \u2014 where the lock-in is AWS plumbing<\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/spf-dkim-dmarc-explained-simply\/\">SPF, DKIM and DMARC explained simply<\/a> \u2014 authenticating two subdomains properly<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently Asked Questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">What is the hardest part of leaving Postmark?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Rebuilding stream separation. Postmark keeps transactional and broadcast mail on separate IP pools automatically; most providers do not, so you reproduce that separation yourself using two sending subdomains.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What are Postmark message streams?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Routing targets that determine which sending infrastructure a message uses. Transactional streams carry single-recipient triggered mail; broadcast streams carry scheduled multi-recipient mail and require an opt-out link.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Does Postmark really keep the two types of mail separate?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. Postmark&#8217;s documentation states that transactional and broadcast traffic do not mix, including IP ranges, with a dedicated IP pool for each.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Why does my transactional deliverability drop weeks after migrating?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Because marketing and transactional mail now share one sending identity, and receivers gradually learn to treat the whole identity as bulk. The damage accumulates rather than appearing on cutover day.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What is the API value for Postmark&#8217;s default transactional stream?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>outbound<\/code>. Searching your codebase for &#8220;transactional&#8221; will miss most stream references.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How many message streams can a Postmark server have?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Up to 10. Enumerate them before migrating rather than assuming you have only transactional and broadcast.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Should I use a separate domain for marketing email instead of a subdomain?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">No. An unrelated domain can look like spoofing to receivers and builds no reputation for your brand. Use subdomains of the domain you already send from.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Should I migrate transactional or marketing email first?<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Transactional first, with a full parallel run. Marketing second on a fresh subdomain that needs its own warm-up, so you are not diagnosing two different problems at once.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Postmark migrations do not fail on cutover day. They fail three weeks later, which is far harder to diagnose.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The reason is that Postmark&#8217;s most valuable property is not a feature you would think to port. It is an architecture: transactional and broadcast mail on separate IP pools, enforced by the platform rather than configured by you. Drop it, and two reputations that were insulated from each other become one, and your newsletter starts deciding whether your password resets reach the inbox.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So the migration has one central task, and it is not the credential swap. Build two sending subdomains, authenticate each independently, keep their suppression lists distinct, and move transactional mail first with marketing following on its own warm-up. That reproduces what Postmark was doing \u2014 and puts the boundary under your control, where you can add a third category without asking a vendor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Everything else is a few hours: templates into version control, <code>MessageStream<\/code> references removed, webhooks remapped. A <a href=\"https:\/\/www.photonconsole.com\/relay.php\">reliable SMTP provider<\/a> handles the sending with standard SMTP and a flat per-thousand rate, and the separation ends up documented in your own DNS rather than assumed from a platform you no longer use.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Read More<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.photonconsole.com\/email-deliverability-checker.php\">Free Email Deliverability Checker<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/migrate-email-provider-without-downtime\/\">Migrating Email Providers Without Downtime<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/postmark-pricing\/\">Postmark Pricing Explained<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/spf-dkim-dmarc-explained-simply\/\">SPF, DKIM and DMARC Explained Simply<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/photonconsole.com\/blog\/smtp-configuration\/\">SMTP Configuration: Complete Setup Reference<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.photonconsole.com\/relay.php\">PhotonRelay: SMTP Relay Service<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.photonconsole.com\/pricing.php\">PhotonConsole Pricing<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The migration goes cleanly. Templates ported, credentials swapped, delivery rates holding. Nobody notices anything for about three weeks. Then a customer says they never received a password reset. Then another. You check, and your transactional mail is landing in spam at Gmail \u2014 not because anything broke, but because the monthly newsletter you now send [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":563,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31],"tags":[593],"class_list":["post-562","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-smpt-relay-service","tag-postmark-keeps-transactional-and-broadcast-mail-on-separate-ip-pools-most-providers-do-not-rebuilding-that-separation-is-the-whole-migration"],"_links":{"self":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/comments?post=562"}],"version-history":[{"count":1,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/562\/revisions"}],"predecessor-version":[{"id":566,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/posts\/562\/revisions\/566"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/media\/563"}],"wp:attachment":[{"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/media?parent=562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/categories?post=562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/photonconsole.com\/blog\/wp-json\/wp\/v2\/tags?post=562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}