diff --git a/docs/src/encoder/tutorial001.py b/docs/src/encoder/tutorial001.py
new file mode 100644
index 000000000..11984dd96
--- /dev/null
+++ b/docs/src/encoder/tutorial001.py
@@ -0,0 +1,22 @@
+from datetime import datetime
+
+from fastapi import FastAPI
+from fastapi.encoders import jsonable_encoder
+from pydantic import BaseModel
+
+fake_db = {}
+
+
+class Item(BaseModel):
+    title: str
+    timestamp: datetime
+    description: str = None
+
+
+app = FastAPI()
+
+
+@app.put("/items/{id}")
+def update_item(id: str, item: Item):
+    json_compatible_item_data = jsonable_encoder(item)
+    fake_db[id] = json_compatible_item_data
diff --git a/docs/src/response_directly/tutorial001.py b/docs/src/response_directly/tutorial001.py
new file mode 100644
index 000000000..92ae0ca37
--- /dev/null
+++ b/docs/src/response_directly/tutorial001.py
@@ -0,0 +1,21 @@
+from datetime import datetime
+
+from fastapi import FastAPI
+from fastapi.encoders import jsonable_encoder
+from pydantic import BaseModel
+from starlette.responses import JSONResponse
+
+
+class Item(BaseModel):
+    title: str
+    timestamp: datetime
+    description: str = None
+
+
+app = FastAPI()
+
+
+@app.put("/items/{id}")
+def update_item(id: str, item: Item):
+    json_compatible_item_data = jsonable_encoder(item)
+    return JSONResponse(content=json_compatible_item_data)
diff --git a/docs/src/response_directly/tutorial002.py b/docs/src/response_directly/tutorial002.py
new file mode 100644
index 000000000..fe961335e
--- /dev/null
+++ b/docs/src/response_directly/tutorial002.py
@@ -0,0 +1,20 @@
+from fastapi import FastAPI
+from starlette.responses import Response
+
+app = FastAPI()
+
+
+@app.get("/legacy/")
+def get_legacy_data():
+    data = """
+    <?xml version="1.0"?>
+    <shampoo>
+    <Header>
+        Apply shampoo here.
+    <Header>
+    <Body>
+        You'll have to use soap here.
+    </Body>
+    </shampoo>
+    """
+    return Response(content=data, media_type="application/xml")
diff --git a/docs/tutorial/custom-response.md b/docs/tutorial/custom-response.md
index 0f0763992..600033f15 100644
--- a/docs/tutorial/custom-response.md
+++ b/docs/tutorial/custom-response.md
@@ -1,98 +1,88 @@
 !!! warning
     This is a rather advanced topic.
-    
+
     If you are starting with **FastAPI**, you might not need this.
 
 By default, **FastAPI** will return the responses using Starlette's `JSONResponse`.
 
-But you can override it.
+You can override it by returning a `Response` directly, <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">as seen in a previous section</a>.
 
-## Use `UJSONResponse`
+But if you return a `Response` directly, the data won't be automatically converted, and the documentation won't be automatically generated (for example, including the specific "media type", in the HTTP header `Content-Type`).
 
-For example, if you are squeezing performance, you can use `ujson` and set the response to be Starlette's `UJSONResponse`.
+But you can also declare the `Response` that you want to be used, in the *path operation decorator*.
 
-### Import `UJSONResponse`
+The contents that you return from your *path operation function* will be put inside of that `Response`.
 
-```Python hl_lines="2"
-{!./src/custom_response/tutorial001.py!}
-```
+And if that `Response` has a JSON media type (`application/json`), like is the case with the `JSONResponse` and `UJSONResponse`, the data you return will be automatically converted (and filtered) with any Pydantic `response_model` that you declared in the *path operation decorator*.
 
-!!! note
-    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
+## Use `UJSONResponse`
 
-### Make your path operation use it
+For example, if you are squeezing performance, you can install and use `ujson` and set the response to be Starlette's `UJSONResponse`.
 
-Make your path operation use `UJSONResponse` as the response class using the parameter `content_type`:
+Import the `Response` class (sub-class) you want to use and declare it in the *path operation decorator*.
 
-```Python hl_lines="7"
+```Python hl_lines="2 7"
 {!./src/custom_response/tutorial001.py!}
 ```
 
+!!! note
+    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
+
 !!! info
-    The parameter is called `content_type` because it will also be used to define the "media type" of the response.
+    The parameter `response_class` will also be used to define the "media type" of the response.
 
-    And will be documented as such in OpenAPI.
+    In this case, the HTTP header `Content-Type` will be set to `application/json`.
+
+    And it will be documented as such in OpenAPI.
 
 ## HTML Response
 
 To return a response with HTML directly from **FastAPI**, use `HTMLResponse`.
 
-### Import `HTMLResponse`
+* Import `HTMLResponse`.
+* Pass `HTMLResponse` as the parameter `content_type` of your path operation.
 
-```Python hl_lines="2"
+```Python hl_lines="2 7"
 {!./src/custom_response/tutorial002.py!}
 ```
 
 !!! note
     Notice that you import it directly from `starlette.responses`, not from `fastapi`.
 
-
-### Define your `content_type` class
-
-Pass `HTMLResponse` as the parameter `content_type` of your path operation:
-
-```Python hl_lines="7"
-{!./src/custom_response/tutorial002.py!}
-```
-
 !!! info
-    The parameter is called `content_type` because it will also be used to define the "media type" of the response.
+    The parameter `response_class` will also be used to define the "media type" of the response.
 
     In this case, the HTTP header `Content-Type` will be set to `text/html`.
 
     And it will be documented as such in OpenAPI.
 
-
 ### Return a Starlette `Response`
 
-You can also override the response directly in your path operation.
-
-If you return an object that is an instance of Starlette's `Response`, it will be used as the response directly.
+As seen in <a href="https://fastapi.tiangolo.com/tutorial/response-directly/" target="_blank">another section</a>, you can also override the response directly in your path operation, by returning it.
 
 The same example from above, returning an `HTMLResponse`, could look like:
 
-```Python hl_lines="7"
+```Python hl_lines="2 7 19"
 {!./src/custom_response/tutorial003.py!}
 ```
 
-!!! info
-    Of course, the `Content-Type` header will come from the the `Response` object your returned.
-
 !!! warning
-    A `Response` returned directly by your path operation function won't be documented in OpenAPI and won't be visible in the automatic interactive docs.
+    A `Response` returned directly by your path operation function won't be documented in OpenAPI (for example, the `Content-Type` won't be documented) and won't be visible in the automatic interactive docs.
 
+!!! info
+    Of course, the actual `Content-Type` header, status code, etc, will come from the `Response` object your returned.
 
 ### Document in OpenAPI and override `Response`
 
-If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `content_type` parameter AND return a `Response` object.
+If you want to override the response from inside of the function but at the same time document the "media type" in OpenAPI, you can use the `response_class` parameter AND return a `Response` object.
 
-The `content_type` class will then be used only to document the OpenAPI path operation, but your `Response` will be used as is.
+The `response_class` will then be used only to document the OpenAPI path operation, but your `Response` will be used as is.
 
 #### Return an `HTMLResponse` directly
 
 For example, it could be something like:
 
-```Python hl_lines="7 23"
+```Python hl_lines="7 23 21"
 {!./src/custom_response/tutorial004.py!}
 ```
 
@@ -100,16 +90,10 @@ In this example, the function `generate_html_response()` already generates a Sta
 
 By returning the result of calling `generate_html_response()`, you are already returning a `Response` that will override the default **FastAPI** behavior.
 
-#### Declare `HTMLResponse` as `content_type`
-
-But by declaring it also in the path operation decorator:
+But as you passed the `HTMLResponse` in the `response_class`, **FastAPI** will know how to document it in OpenAPI and the interactive docs as HTML with `text/html`:
 
-```Python hl_lines="21"
-{!./src/custom_response/tutorial004.py!}
-```
-
-#### OpenAPI knows how to document it
+<img src="/img/tutorial/custom-response/image01.png">
 
-...**FastAPI** will be able to document it in OpenAPI and in the interactive docs as HTML with `text/html`:
+## Additional documentation
 
-<img src="/img/tutorial/custom-response/image01.png">
+You can also declare the media type and many other details in OpenAPI using `responses`: <a href="https://fastapi.tiangolo.com/tutorial/additional-responses/" target="_blank">Additional Responses in OpenAPI</a>.
diff --git a/docs/tutorial/encoder.md b/docs/tutorial/encoder.md
new file mode 100644
index 000000000..41893194e
--- /dev/null
+++ b/docs/tutorial/encoder.md
@@ -0,0 +1,32 @@
+There are some cases where you might need to convert a data type (like a Pydantic model) to something compatible with JSON (like a `dict`, `list`, etc).
+
+For example, if you need to store it in a database.
+
+For that, **FastAPI** provides a `jsonable_encoder()` function.
+
+## Using the `jsonable_encoder`
+
+Let's imagine that you have a database `fake_db` that only receives JSON compatible data.
+
+For example, it doesn't receive `datetime` objects, as those are not compatible with JSON.
+
+So, a `datetime` object would have to be converted to a `str` containing the data in <a href="https://en.wikipedia.org/wiki/ISO_8601" target="_blank">ISO format</a>.
+
+The same way, this database wouldn't receive a Pydantic model (an object with attributes), only a `dict`.
+
+You can use `jsonable_encoder` for that.
+
+It receives an object, like a Pydantic model, and returns a JSON compatible version:
+
+```Python hl_lines="4 21"
+{!./src/encoder/tutorial001.py!}
+```
+
+In this example, it would convert the Pydantic model to a `dict`, and the `datetime` to a `str`.
+
+The result of calling it is something that can be encoded with the Python standard <a href="https://docs.python.org/3/library/json.html#json.dumps" target="_blank">`json.dumps()`</a>.
+
+It doesn't return a large `str` containing the data in JSON format (as a string). It returns a Python standard data structure (e.g. a `dict`) with values and sub-values that are all compatible with JSON.
+
+!!! note
+    `jsonable_encoder` is actually used by **FastAPI** internally to convert data. But it is useful in many other scenarios.
diff --git a/docs/tutorial/response-directly.md b/docs/tutorial/response-directly.md
new file mode 100644
index 000000000..f622cab85
--- /dev/null
+++ b/docs/tutorial/response-directly.md
@@ -0,0 +1,63 @@
+When you create a **FastAPI** *path operation* you can normally return any data from it: a `dict`, a `list`, a Pydantic model, a database model, etc.
+
+By default, **FastAPI** would automatically convert that return value to JSON using the <a href="https://fastapi.tiangolo.com/tutorial/encoder/" target="_blank">`jsonable_encoder`</a>.
+
+Then, behind the scenes, it would put that JSON-compatible data (e.g. a `dict`) inside of a Starlette `JSONResponse` that would be used to send the response to the client.
+
+But you can return a `JSONResponse` directly from your *path operations*.
+
+It might be useful, for example, to return custom headers or cookies.
+
+## Starlette `Response`
+
+In fact, you can return any <a href="https://www.starlette.io/responses/" target="_blank">Starlette `Response`</a> or any sub-class of it.
+
+!!! tip
+    `JSONResponse` itself is a sub-class of `Response`.
+
+And when you return a Starlette `Response`, **FastAPI** will pass it directly.
+
+It won't do any data conversion with Pydantic models, it won't convert the contents to any type, etc.
+
+This gives you a lot of flexibility. You can return any data type, override any data declaration or validation, etc.
+
+## Using the `jsonable_encoder` in a `Response`
+
+Because **FastAPI** doesn't do any change to a `Response` you return, you have to make sure it's contents are ready for it.
+
+For example, you cannot put a Pydantic model in a `JSONResponse` without first converting it to a `dict` with all the data types (like `datetime`, `UUID`, etc) converted to JSON-compatible types.
+
+For those cases, you can use the `jsonable_encoder` to convert your data before passing it to a response:
+
+```Python hl_lines="4 6 20 21"
+{!./src/response_directly/tutorial001.py!}
+```
+
+!!! note
+    Notice that you import it directly from `starlette.responses`, not from `fastapi`.
+
+## Returning a custom `Response`
+
+The example above shows all the parts you need, but it's not very useful yet, as you could have just returned the `item` directly, and **FastAPI** would put it in a `JSONResponse` for you, converting it to a `dict`, etc. All that by default.
+
+Now, let's see how you could use that to return a custom response.
+
+Let's say you want to return a response that is not available in the default <a href="https://www.starlette.io/responses/" target="_blank">Starlette `Response`s</a>.
+
+Let's say that you want to return <a href="https://en.wikipedia.org/wiki/XML" target="_blank">XML</a>.
+
+You could put your XML content in a string, put it in a Starlette Response, and return it:
+
+```Python hl_lines="2 20"
+{!./src/response_directly/tutorial002.py!}
+```
+
+## Notes
+
+When you return a `Response` directly its data is not validated, converted (serialized), nor documented automatically.
+
+But you can still <a href="tutorial/additional-responses/" target="_blank">document it</a>.
+
+In the next sections you will see how to use/declare these custom `Response`s while still having automatic data conversion, documentation, etc.
+
+You will also see how to use them to set response Headers and Cookies.
diff --git a/mkdocs.yml b/mkdocs.yml
index 2ea289d8e..b53936384 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -44,7 +44,9 @@ nav:
         - Path Operation Configuration: 'tutorial/path-operation-configuration.md'
         - Path Operation Advanced Configuration: 'tutorial/path-operation-advanced-configuration.md'
         - Additional Status Codes: 'tutorial/additional-status-codes.md'
-        - Custom Response: 'tutorial/custom-response.md'
+        - JSON compatible encoder: 'tutorial/encoder.md'
+        - Return a Response directly: 'tutorial/response-directly.md'
+        - Custom Response Class: 'tutorial/custom-response.md'
         - Additional Responses in OpenAPI: 'tutorial/additional-responses.md'
         - Dependencies:
             - First Steps: 'tutorial/dependencies/first-steps.md'