Skip Navigation
Show nav
Heroku Dev Center Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
Heroku Dev Center Dev Center
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log in or Sign up
View categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Buildpacks
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
      • Working with Node.js
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • Working with PHP
      • PHP Behavior in Heroku
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Vector Database
    • Model Context Protocol
    • Working with AI
    • Heroku Inference
      • Inference Essentials
      • AI Models
      • Inference API
      • Heroku Inference Quick Start Guides
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
    • Heroku AppLink
      • Getting Started with Heroku AppLink
      • Working wtih Heroku AppLink
      • Heroku AppLink Reference
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
    • Other Salesforce Integrations
  • Security
  • Private Spaces
  • Routing in Private Spaces

Routing in Private Spaces

English — 日本語に切り替える

Last updated December 03, 2024

Table of Contents

  • Heroku error codes
  • Large cookie & header support
  • Response body size logging
  • Dyno connection reuse
  • Response body buffering
  • Maintenance mode & custom error pages
  • Content-Length & Content-Type headers
  • Query string logging
  • SNI servername & host header matching
  • SSL security
  • HTTP 1.0
  • Status Line
  • Supported HTTP Methods
  • Custom DNS Resolvers

The routers in Private Spaces have a slightly different behavior to the routers found in the Common Runtime. This article explains the differences. Please refer to HTTP Routing for an understanding of the shared routing behavior between Common Runtime and Private Spaces.

Heroku error codes

Among the Heroku error codes for the Common Runtime, Private Space routers support the following errors:

  • H10 - App crashed
  • H11 - Backlog too deep
  • H12 - Request timeout
  • H13 - Connection closed without response
  • H15 - Idle connection
  • H17 - Poorly formatted HTTP response
  • H18 - Server Request Interrupted
  • H19 - Backend connection timeout
  • H21 - Backend connection refused
  • H25 - HTTP Restriction: Oversized cookies
  • H25 - HTTP Restriction: Oversized header
  • H25 - HTTP Restriction: Oversized status line
  • H26 - Request Error: Unsupported expect header value
  • H26 - Request Error: Bad header
  • H27 - Client Request Interrupted
  • H28 - Client Connection Idle
  • H99 - Platform error

Large cookie & header support

Private Space routers support individual HTTP headers up to 512 KB in size.

Response body size logging

Private Space routers count only the size of the response body in the bytes field of app logs. The Heroku router for Common Runtime counts the status line, headers, and body size.

Dyno connection reuse

For applications that support persistent HTTP connections, Private Space routers might reuse connections to the dyno for multiple requests. These reused connections are independent of the connections between the client software and the Heroku platform.

Response body buffering

Private Space routers might buffer response bodies internally to avoid sending many small body fragments to the client. This improves performance for most applications, but it can have a detrimental effect on applications that require low-latency streaming. Small body fragments are buffered for a maximum of 10ms, but the client might observe larger buffering times due to networking characteristics.

Maintenance mode & custom error pages

Both Maintenance Mode and Custom Error Pages are supported in Private Spaces. Unlike the Common Runtime, however, at least one web dyno must be running for the Private Space routers to serve maintenance and custom error pages.

Content-Length & Content-Type headers

Unlike Common Runtime routing, which allows multiple Content-Length headers in a request as long as they contain the same value, Private Space routers serve a 400 Bad Response whenever multiple Content-Length headers are present.

Private Space routers also attempt to set a Content-Type header on requests when missing from the dyno’s response based on the MIME Sniffing Standard.

Query string logging

Log messages generated by the Private Spaces router contain query string parameters (also known as URL or Get parameters) in the path field. Some applications pass sensitive data using the query string. For example, OAuth applications typically use a query string parameter for passing temporary tokens between services. For applications that cannot log query string parameters due to compliance or security concerns, this behavior can be disabled by enabling the spaces-no-log-query feature via the Heroku CLI:

$ heroku features:enable spaces-no-log-query --app desolate-dawn-42

SNI servername & host header matching

Some clients and CDNs set a different value for the SNI servername than the request’s host header when connecting to a Heroku application. Heroku recommends Private Space applications set up a CNAME record for an application’s public DNS entry that points to the internal space name. This is typically a record for your www.example-app.com custom domain that points to a desolate-dawn-42.fathomless-ravine-43.herokuspace.com style record.

Mismatched servername and host header values are allowed, as long as both names are configured as domains for the same application. The desolate-dawn-42.fathomless-ravine-43.herokuspace.com style domains are configured and managed by Heroku.

Client support for SNI is required by default in Private Spaces. Please contact Heroku Support if your application needs to serve legacy clients that do not support SNI.

SSL security

Apps in Private Spaces have a choice of cipher suites used to negotiate TLS connections with clients.

Default

The default suite supports TLSv1.1 and TLSv1.2 (but not TLSv1.0). It provides good security and is compatible with a large range of browsers and clients.

To get the default TLS behavior, disable all TLS-related features:

$ heroku features:disable spaces-tls-modern --app desolate-dawn-42
$ heroku features:disable spaces-tls-legacy --app desolate-dawn-42
$ heroku features:disable spaces-strict-tls --app desolate-dawn-42

Cipher Suites

  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

Modern

The modern suite supports only TLSv1.2. It provides excellent security and works with relatively new browsers and mobile/IoT clients.

heroku features:disable spaces-strict-tls --app your-app
heroku features:enable spaces-tls-modern --app your-app

Cipher Suites

  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256

Legacy

The legacy suite supports TLSv1, TLSv1.1 and TLSv1.2.It should only be used if backwards compatibility with old clients is required.

heroku features:disable spaces-strict-tls --app your-app
heroku features:enable spaces-tls-legacy --app your-app

Cipher Suites

  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_GCM_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_GCM_SHA384
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_3DES_EDE_CBC_SHA

[Deprecated] Strict

With the spaces-strict-tls feature flag enabled, the Private Spaces routers supports TLS versions 1.1 and 1.2. This flag is deprecated and should only be used for backwards compatibility with previous Heroku TLS termination behavior.

heroku features:enable spaces-strict-tls --app your-app

Cipher Suites

  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
  • TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA

HTTP 1.0

Private Space routers convert HTTP 1.0 into HTTP 1.1 requests that are forwarded to dynos. HTTP 1.1 responses from dynos are sent to the client as HTTP 1.0 responses if the original request used HTTP 1.0.

Common Runtime routers convert HTTP 1.0 requests to HTTP 1.1 requests, but do not convert HTTP 1.1 responses back to HTTP 1.0 responses.

Status Line

Private Space routers treat the entire first line of the request (up to the first \n character) as the status line, regardless of the line ending in a CRLF (\r\n) as specified in the HTTP 1.1 RFC. It is typical for HTTP servers like Nginx to allow bare newlines in the end of the status line.

Supported HTTP Methods

Private Space routers supports any HTTP method (sometimes called a “verb”), even those not defined in an RFC.

Custom DNS Resolvers

Private Space apps support injecting a single DNS Resolver as the Dynos first DNS server target, followed by the standard Private Space DNS target. To use this feature you need to enable the spaces-extra-resolver flag on the desired apps and then configure the HEROKU_EXTRA_RESOLVER config var.

Example:

heroku labs:enable spaces-extra-resolver -a "$APP_NAME"
heroku config:set -a "$APP_NAME" HEROKU_EXTRA_RESOLVER=DNS-Server-IP

Keep reading

  • Private Spaces

Feedback

Log in to submit feedback.

Working with Private Spaces Shield Private Spaces

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices