From d8714e64e400ef873c2adc4d929a07d7890727b9 Mon Sep 17 00:00:00 2001
From: Miek Gieben <miek@miek.nl>
Date: Thu, 14 Sep 2017 09:36:06 +0100
Subject: [PATCH] Remove the word middleware (#1067)

* Rename middleware to plugin

first pass; mostly used 'sed', few spots where I manually changed
text.

This still builds a coredns binary.

* fmt error

* Rename AddMiddleware to AddPlugin

* Readd AddMiddleware to remain backwards compat
---
 .travis.yml                                   |  2 +-
 Makefile                                      | 12 +--
 README.md                                     |  8 +-
 core/coredns.go                               | 46 +++++-----
 core/dnsserver/address.go                     |  4 +-
 core/dnsserver/config.go                      | 17 ++--
 core/dnsserver/register.go                    | 30 ++++---
 core/dnsserver/server-grpc.go                 |  4 +-
 core/dnsserver/server-tls.go                  |  4 +-
 core/dnsserver/server.go                      | 42 ++++-----
 core/dnsserver/zdirectives.go                 |  6 +-
 core/zmiddleware.go                           | 36 --------
 core/zplugin.go                               | 36 ++++++++
 directives_generate.go                        | 24 +++---
 middleware/kubernetes/handler.go              | 86 -------------------
 middleware/middleware_test.go                 |  1 -
 middleware/secondary/secondary.go             | 10 ---
 middleware/test/doc.go                        |  2 -
 middleware.cfg => plugin.cfg                  | 18 ++--
 middleware.md => plugin.md                    | 60 ++++++-------
 {middleware => plugin}/auto/README.md         |  4 +-
 {middleware => plugin}/auto/auto.go           | 18 ++--
 {middleware => plugin}/auto/regexp.go         |  0
 {middleware => plugin}/auto/regexp_test.go    |  0
 {middleware => plugin}/auto/setup.go          | 16 ++--
 {middleware => plugin}/auto/setup_test.go     |  0
 {middleware => plugin}/auto/walk.go           |  2 +-
 {middleware => plugin}/auto/walk_test.go      |  0
 {middleware => plugin}/auto/watcher_test.go   |  0
 {middleware => plugin}/auto/zone.go           |  2 +-
 {middleware => plugin}/autopath/README.md     | 10 +--
 {middleware => plugin}/autopath/autopath.go   | 30 +++----
 .../autopath/autopath_test.go                 |  8 +-
 {middleware => plugin}/autopath/cname.go      |  0
 {middleware => plugin}/autopath/setup.go      | 18 ++--
 {middleware => plugin}/autopath/setup_test.go |  4 +-
 {middleware => plugin}/backend.go             |  4 +-
 {middleware => plugin}/backend_lookup.go      |  6 +-
 {middleware => plugin}/bind/README.md         |  0
 {middleware => plugin}/bind/bind.go           |  0
 {middleware => plugin}/bind/bind_test.go      |  0
 {middleware => plugin}/bind/setup.go          |  6 +-
 {middleware => plugin}/cache/README.md        |  0
 {middleware => plugin}/cache/cache.go         | 10 +--
 {middleware => plugin}/cache/cache_test.go    | 14 +--
 {middleware => plugin}/cache/freq/freq.go     |  0
 .../cache/freq/freq_test.go                   |  0
 {middleware => plugin}/cache/handler.go       | 18 ++--
 {middleware => plugin}/cache/item.go          |  4 +-
 {middleware => plugin}/cache/prefech_test.go  | 12 +--
 {middleware => plugin}/cache/setup.go         | 10 +--
 {middleware => plugin}/cache/setup_test.go    |  0
 {middleware => plugin}/chaos/README.md        |  4 +-
 {middleware => plugin}/chaos/chaos.go         | 10 +--
 {middleware => plugin}/chaos/chaos_test.go    |  8 +-
 {middleware => plugin}/chaos/setup.go         |  6 +-
 {middleware => plugin}/chaos/setup_test.go    |  0
 {middleware => plugin}/debug/README.md        |  2 +-
 {middleware => plugin}/debug/debug.go         |  4 +-
 {middleware => plugin}/debug/debug_test.go    |  0
 {middleware => plugin}/dnssec/README.md       |  6 +-
 {middleware => plugin}/dnssec/black_lies.go   |  0
 .../dnssec/black_lies_test.go                 |  2 +-
 {middleware => plugin}/dnssec/cache.go        |  0
 {middleware => plugin}/dnssec/cache_test.go   |  4 +-
 {middleware => plugin}/dnssec/dnskey.go       |  0
 {middleware => plugin}/dnssec/dnssec.go       | 14 +--
 {middleware => plugin}/dnssec/dnssec_test.go  |  4 +-
 {middleware => plugin}/dnssec/handler.go      | 18 ++--
 {middleware => plugin}/dnssec/handler_test.go |  8 +-
 .../dnssec/responsewriter.go                  |  4 +-
 {middleware => plugin}/dnssec/rrsig.go        |  0
 {middleware => plugin}/dnssec/setup.go        | 12 +--
 {middleware => plugin}/dnssec/setup_test.go   |  0
 {middleware => plugin}/dnstap/README.md       |  0
 {middleware => plugin}/dnstap/handler.go      | 14 +--
 {middleware => plugin}/dnstap/handler_test.go |  4 +-
 {middleware => plugin}/dnstap/msg/msg.go      |  2 +-
 {middleware => plugin}/dnstap/msg/msg_test.go |  2 +-
 {middleware => plugin}/dnstap/msg/wrapper.go  |  0
 {middleware => plugin}/dnstap/out/socket.go   |  0
 .../dnstap/out/socket_test.go                 |  0
 {middleware => plugin}/dnstap/out/tcp.go      |  0
 {middleware => plugin}/dnstap/out/tcp_test.go |  0
 {middleware => plugin}/dnstap/setup.go        | 12 +--
 {middleware => plugin}/dnstap/setup_test.go   |  0
 {middleware => plugin}/dnstap/taprw/writer.go |  2 +-
 .../dnstap/taprw/writer_test.go               |  6 +-
 {middleware => plugin}/dnstap/test/helpers.go |  2 +-
 {middleware => plugin}/erratic/README.md      |  6 +-
 {middleware => plugin}/erratic/autopath.go    |  2 +-
 {middleware => plugin}/erratic/erratic.go     |  6 +-
 .../erratic/erratic_test.go                   |  4 +-
 {middleware => plugin}/erratic/setup.go       |  6 +-
 {middleware => plugin}/erratic/setup_test.go  |  0
 {middleware => plugin}/errors/README.md       |  0
 {middleware => plugin}/errors/errors.go       | 12 +--
 {middleware => plugin}/errors/errors_test.go  | 12 +--
 {middleware => plugin}/errors/setup.go        |  6 +-
 {middleware => plugin}/errors/setup_test.go   |  0
 {middleware => plugin}/etcd/README.md         |  8 +-
 {middleware => plugin}/etcd/cname_test.go     |  6 +-
 {middleware => plugin}/etcd/etcd.go           | 20 ++---
 {middleware => plugin}/etcd/group_test.go     |  6 +-
 {middleware => plugin}/etcd/handler.go        | 42 ++++-----
 {middleware => plugin}/etcd/lookup_test.go    | 12 +--
 {middleware => plugin}/etcd/msg/path.go       |  2 +-
 {middleware => plugin}/etcd/msg/path_test.go  |  0
 {middleware => plugin}/etcd/msg/service.go    |  0
 .../etcd/msg/service_test.go                  |  0
 {middleware => plugin}/etcd/msg/type.go       |  0
 {middleware => plugin}/etcd/msg/type_test.go  |  0
 {middleware => plugin}/etcd/multi_test.go     |  6 +-
 {middleware => plugin}/etcd/other_test.go     |  6 +-
 {middleware => plugin}/etcd/setup.go          | 16 ++--
 {middleware => plugin}/etcd/setup_test.go     |  0
 {middleware => plugin}/etcd/stub.go           |  6 +-
 {middleware => plugin}/etcd/stub_handler.go   |  2 +-
 {middleware => plugin}/etcd/stub_test.go      |  6 +-
 {middleware => plugin}/federation/README.md   |  4 +-
 .../federation/federation.go                  | 34 ++++----
 .../federation/federation_test.go             |  6 +-
 .../federation/kubernetes_api_test.go         |  2 +-
 {middleware => plugin}/federation/setup.go    | 12 +--
 .../federation/setup_test.go                  |  0
 {middleware => plugin}/file/README.md         |  4 +-
 {middleware => plugin}/file/closest.go        |  2 +-
 {middleware => plugin}/file/closest_test.go   |  0
 {middleware => plugin}/file/cname_test.go     |  6 +-
 .../file/delegation_test.go                   |  4 +-
 {middleware => plugin}/file/dname.go          |  2 +-
 {middleware => plugin}/file/dname_test.go     |  4 +-
 {middleware => plugin}/file/dnssec_test.go    |  4 +-
 {middleware => plugin}/file/dnssex_test.go    |  0
 {middleware => plugin}/file/ds_test.go        |  4 +-
 {middleware => plugin}/file/ent_test.go       |  4 +-
 {middleware => plugin}/file/example_org.go    |  0
 {middleware => plugin}/file/file.go           | 12 +--
 {middleware => plugin}/file/file_test.go      |  0
 {middleware => plugin}/file/glue_test.go      |  4 +-
 {middleware => plugin}/file/include_test.go   |  2 +-
 {middleware => plugin}/file/lookup.go         |  2 +-
 {middleware => plugin}/file/lookup_test.go    |  4 +-
 {middleware => plugin}/file/notify.go         |  2 +-
 {middleware => plugin}/file/nsec3_test.go     |  0
 {middleware => plugin}/file/reload.go         |  0
 {middleware => plugin}/file/reload_test.go    |  2 +-
 {middleware => plugin}/file/secondary.go      |  0
 {middleware => plugin}/file/secondary_test.go |  2 +-
 {middleware => plugin}/file/setup.go          | 12 +--
 {middleware => plugin}/file/setup_test.go     |  2 +-
 {middleware => plugin}/file/tree/all.go       |  0
 {middleware => plugin}/file/tree/elem.go      |  0
 {middleware => plugin}/file/tree/less.go      |  0
 {middleware => plugin}/file/tree/less_test.go |  0
 {middleware => plugin}/file/tree/print.go     |  0
 {middleware => plugin}/file/tree/tree.go      |  0
 {middleware => plugin}/file/wildcard.go       |  0
 {middleware => plugin}/file/wildcard_test.go  |  4 +-
 {middleware => plugin}/file/xfr.go            |  8 +-
 {middleware => plugin}/file/xfr_test.go       |  0
 {middleware => plugin}/file/zone.go           |  4 +-
 {middleware => plugin}/file/zone_test.go      |  0
 {middleware => plugin}/health/README.md       |  4 +-
 {middleware => plugin}/health/health.go       |  4 +-
 {middleware => plugin}/health/health_test.go  |  2 +-
 {middleware => plugin}/health/healther.go     | 14 +--
 {middleware => plugin}/health/setup.go        |  6 +-
 {middleware => plugin}/health/setup_test.go   |  0
 {middleware => plugin}/hosts/README.md        |  8 +-
 {middleware => plugin}/hosts/hosts.go         | 20 ++---
 {middleware => plugin}/hosts/hosts_test.go    |  4 +-
 {middleware => plugin}/hosts/hostsfile.go     |  6 +-
 .../hosts/hostsfile_test.go                   |  0
 {middleware => plugin}/hosts/setup.go         |  8 +-
 {middleware => plugin}/hosts/setup_test.go    |  0
 .../kubernetes/DEV-README.md                  |  0
 {middleware => plugin}/kubernetes/README.md   | 18 ++--
 {middleware => plugin}/kubernetes/apiproxy.go |  2 +-
 {middleware => plugin}/kubernetes/autopath.go |  6 +-
 .../kubernetes/controller.go                  |  0
 .../kubernetes/federation.go                  |  6 +-
 plugin/kubernetes/handler.go                  | 86 +++++++++++++++++++
 .../kubernetes/handler_pod_disabled_test.go   |  4 +-
 .../kubernetes/handler_pod_insecure_test.go   |  4 +-
 .../kubernetes/handler_pod_verified_test.go   |  4 +-
 .../kubernetes/handler_test.go                |  4 +-
 .../kubernetes/kubernetes.go                  | 18 ++--
 .../kubernetes/kubernetes_apex_test.go        |  4 +-
 .../kubernetes/kubernetes_test.go             |  4 +-
 {middleware => plugin}/kubernetes/local.go    |  0
 {middleware => plugin}/kubernetes/ns.go       |  0
 {middleware => plugin}/kubernetes/ns_test.go  |  0
 {middleware => plugin}/kubernetes/parse.go    |  4 +-
 .../kubernetes/parse_test.go                  |  0
 {middleware => plugin}/kubernetes/reverse.go  |  8 +-
 .../kubernetes/reverse_test.go                |  4 +-
 {middleware => plugin}/kubernetes/setup.go    | 18 ++--
 .../kubernetes/setup_reverse_test.go          |  0
 .../kubernetes/setup_test.go                  |  0
 .../kubernetes/setup_ttl_test.go              |  0
 {middleware => plugin}/loadbalance/README.md  |  0
 {middleware => plugin}/loadbalance/handler.go | 12 +--
 .../loadbalance/loadbalance.go                |  0
 .../loadbalance/loadbalance_test.go           | 10 +--
 {middleware => plugin}/loadbalance/setup.go   |  4 +-
 {middleware => plugin}/log/README.md          |  0
 {middleware => plugin}/log/log.go             | 28 +++---
 {middleware => plugin}/log/log_test.go        |  6 +-
 {middleware => plugin}/log/setup.go           | 10 +--
 {middleware => plugin}/log/setup_test.go      |  2 +-
 {middleware => plugin}/metrics/README.md      |  2 +-
 {middleware => plugin}/metrics/handler.go     | 12 +--
 {middleware => plugin}/metrics/metrics.go     |  8 +-
 .../metrics/metrics_test.go                   | 10 +--
 {middleware => plugin}/metrics/setup.go       |  8 +-
 {middleware => plugin}/metrics/setup_test.go  |  0
 {middleware => plugin}/metrics/test/scrape.go |  0
 {middleware => plugin}/metrics/vars/report.go |  0
 {middleware => plugin}/metrics/vars/vars.go   | 16 ++--
 {middleware => plugin}/normalize.go           |  2 +-
 {middleware => plugin}/normalize_test.go      |  2 +-
 {middleware => plugin}/pkg/cache/cache.go     |  0
 .../pkg/cache/cache_test.go                   |  0
 .../pkg/cache/shard_test.go                   |  0
 .../pkg/dnsrecorder/recorder.go               |  0
 .../pkg/dnsrecorder/recorder_test.go          |  0
 {middleware => plugin}/pkg/dnsutil/cname.go   |  0
 .../pkg/dnsutil/cname_test.go                 |  0
 {middleware => plugin}/pkg/dnsutil/dedup.go   |  0
 {middleware => plugin}/pkg/dnsutil/doc.go     |  0
 {middleware => plugin}/pkg/dnsutil/host.go    |  0
 .../pkg/dnsutil/host_test.go                  |  0
 {middleware => plugin}/pkg/dnsutil/join.go    |  0
 .../pkg/dnsutil/join_test.go                  |  0
 {middleware => plugin}/pkg/dnsutil/reverse.go |  0
 .../pkg/dnsutil/reverse_test.go               |  0
 {middleware => plugin}/pkg/dnsutil/zone.go    |  0
 .../pkg/dnsutil/zone_test.go                  |  0
 {middleware => plugin}/pkg/edns/edns.go       |  2 +-
 {middleware => plugin}/pkg/edns/edns_test.go  |  0
 .../pkg/healthcheck/healthcheck.go            |  0
 .../pkg/healthcheck/policy.go                 |  0
 .../pkg/healthcheck/policy_test.go            |  0
 .../pkg/nonwriter/nonwriter.go                |  0
 .../pkg/nonwriter/nonwriter_test.go           |  0
 {middleware => plugin}/pkg/rcode/rcode.go     |  0
 .../pkg/rcode/rcode_test.go                   |  0
 .../pkg/replacer/replacer.go                  |  2 +-
 .../pkg/replacer/replacer_test.go             |  4 +-
 .../pkg/response/classify.go                  |  0
 {middleware => plugin}/pkg/response/typify.go |  0
 .../pkg/response/typify_test.go               |  2 +-
 .../pkg/singleflight/singleflight.go          |  0
 .../pkg/singleflight/singleflight_test.go     |  0
 {middleware => plugin}/pkg/tls/tls.go         |  0
 {middleware => plugin}/pkg/tls/tls_test.go    |  2 +-
 {middleware => plugin}/pkg/trace/trace.go     |  4 +-
 middleware/middleware.go => plugin/plugin.go  | 22 ++---
 plugin/plugin_test.go                         |  1 +
 {middleware => plugin}/pprof/README.md        |  0
 {middleware => plugin}/pprof/pprof.go         |  0
 {middleware => plugin}/pprof/setup.go         |  8 +-
 {middleware => plugin}/pprof/setup_test.go    |  0
 {middleware => plugin}/proxy/README.md        |  6 +-
 {middleware => plugin}/proxy/dns.go           |  0
 {middleware => plugin}/proxy/dnstap_test.go   |  6 +-
 {middleware => plugin}/proxy/exchanger.go     |  0
 {middleware => plugin}/proxy/google.go        |  2 +-
 {middleware => plugin}/proxy/google_rr.go     |  0
 {middleware => plugin}/proxy/google_test.go   |  0
 {middleware => plugin}/proxy/grpc.go          |  4 +-
 {middleware => plugin}/proxy/grpc_test.go     |  2 +-
 {middleware => plugin}/proxy/lookup.go        |  4 +-
 {middleware => plugin}/proxy/metrics.go       |  6 +-
 {middleware => plugin}/proxy/proxy.go         | 24 +++---
 {middleware => plugin}/proxy/proxy_test.go    |  0
 {middleware => plugin}/proxy/response.go      |  0
 {middleware => plugin}/proxy/setup.go         |  6 +-
 {middleware => plugin}/proxy/upstream.go      | 16 ++--
 {middleware => plugin}/proxy/upstream_test.go |  2 +-
 {middleware => plugin}/reverse/README.md      |  4 +-
 {middleware => plugin}/reverse/network.go     |  0
 .../reverse/network_test.go                   |  0
 {middleware => plugin}/reverse/reverse.go     | 10 +--
 .../reverse/reverse_test.go                   |  8 +-
 {middleware => plugin}/reverse/setup.go       |  8 +-
 {middleware => plugin}/reverse/setup_test.go  |  0
 {middleware => plugin}/rewrite/README.md      |  0
 {middleware => plugin}/rewrite/class.go       |  0
 {middleware => plugin}/rewrite/condition.go   |  2 +-
 .../rewrite/condition_test.go                 |  0
 {middleware => plugin}/rewrite/edns0.go       |  2 +-
 {middleware => plugin}/rewrite/name.go        |  4 +-
 {middleware => plugin}/rewrite/reverter.go    |  0
 {middleware => plugin}/rewrite/rewrite.go     | 14 +--
 .../rewrite/rewrite_test.go                   | 16 ++--
 {middleware => plugin}/rewrite/setup.go       |  6 +-
 {middleware => plugin}/rewrite/setup_test.go  |  0
 .../rewrite/testdata/testdir/empty            |  0
 .../rewrite/testdata/testfile                 |  0
 {middleware => plugin}/rewrite/type.go        |  2 +-
 {middleware => plugin}/root/README.md         |  2 +-
 {middleware => plugin}/root/root.go           |  6 +-
 {middleware => plugin}/root/root_test.go      |  0
 {middleware => plugin}/secondary/README.md    |  0
 plugin/secondary/secondary.go                 | 10 +++
 {middleware => plugin}/secondary/setup.go     | 14 +--
 .../secondary/setup_test.go                   |  0
 plugin/test/doc.go                            |  2 +
 {middleware => plugin}/test/file.go           |  0
 {middleware => plugin}/test/file_test.go      |  0
 {middleware => plugin}/test/helpers.go        |  2 +-
 {middleware => plugin}/test/responsewriter.go |  0
 {middleware => plugin}/test/server.go         |  0
 {middleware => plugin}/tls/README.md          |  4 +-
 {middleware => plugin}/tls/tls.go             | 10 +--
 {middleware => plugin}/tls/tls_test.go        |  0
 {middleware => plugin}/trace/README.md        |  2 +-
 {middleware => plugin}/trace/setup.go         |  6 +-
 {middleware => plugin}/trace/setup_test.go    |  0
 {middleware => plugin}/trace/trace.go         | 10 +--
 {middleware => plugin}/trace/trace_test.go    |  4 +-
 {middleware => plugin}/whoami/README.md       |  8 +-
 {middleware => plugin}/whoami/setup.go        |  6 +-
 {middleware => plugin}/whoami/setup_test.go   |  0
 {middleware => plugin}/whoami/whoami.go       |  6 +-
 {middleware => plugin}/whoami/whoami_test.go  |  4 +-
 request/request.go                            |  6 +-
 request/request_test.go                       |  2 +-
 test/auto_test.go                             |  4 +-
 test/cache_test.go                            |  4 +-
 test/ds_file_test.go                          |  4 +-
 test/etcd_cache_test.go                       |  6 +-
 test/etcd_test.go                             | 12 +--
 test/external_test.go                         |  6 +-
 test/file_cname_proxy_test.go                 |  4 +-
 test/file_reload_test.go                      |  4 +-
 test/file_srv_additional_test.go              |  4 +-
 test/kubernetes_api_fallthrough_test.go       |  2 +-
 test/kubernetes_fallthrough_test.go           |  2 +-
 test/kubernetes_nsexposed_test.go             |  2 +-
 test/kubernetes_pods_test.go                  |  2 +-
 test/kubernetes_test.go                       |  2 +-
 test/metrics_test.go                          |  8 +-
 test/middleware_dnssec_test.go                |  2 +-
 test/middleware_test.go                       |  2 +-
 test/proxy_health_test.go                     |  4 +-
 test/proxy_http_health_test.go                |  4 +-
 test/proxy_test.go                            |  4 +-
 test/readme_test.go                           |  4 +-
 test/reverse_test.go                          |  4 +-
 test/secondary_test.go                        |  4 +-
 test/wildcard_test.go                         |  4 +-
 354 files changed, 974 insertions(+), 969 deletions(-)
 delete mode 100644 core/zmiddleware.go
 create mode 100644 core/zplugin.go
 delete mode 100644 middleware/kubernetes/handler.go
 delete mode 100644 middleware/middleware_test.go
 delete mode 100644 middleware/secondary/secondary.go
 delete mode 100644 middleware/test/doc.go
 rename middleware.cfg => plugin.cfg (66%)
 rename middleware.md => plugin.md (60%)
 rename {middleware => plugin}/auto/README.md (92%)
 rename {middleware => plugin}/auto/auto.go (80%)
 rename {middleware => plugin}/auto/regexp.go (100%)
 rename {middleware => plugin}/auto/regexp_test.go (100%)
 rename {middleware => plugin}/auto/setup.go (87%)
 rename {middleware => plugin}/auto/setup_test.go (100%)
 rename {middleware => plugin}/auto/walk.go (97%)
 rename {middleware => plugin}/auto/walk_test.go (100%)
 rename {middleware => plugin}/auto/watcher_test.go (100%)
 rename {middleware => plugin}/auto/zone.go (97%)
 rename {middleware => plugin}/autopath/README.md (69%)
 rename {middleware => plugin}/autopath/autopath.go (83%)
 rename {middleware => plugin}/autopath/autopath_test.go (95%)
 rename {middleware => plugin}/autopath/cname.go (100%)
 rename {middleware => plugin}/autopath/setup.go (76%)
 rename {middleware => plugin}/autopath/setup_test.go (95%)
 rename {middleware => plugin}/backend.go (94%)
 rename {middleware => plugin}/backend_lookup.go (98%)
 rename {middleware => plugin}/bind/README.md (100%)
 rename {middleware => plugin}/bind/bind.go (100%)
 rename {middleware => plugin}/bind/bind_test.go (100%)
 rename {middleware => plugin}/bind/setup.go (62%)
 rename {middleware => plugin}/cache/README.md (100%)
 rename {middleware => plugin}/cache/cache.go (93%)
 rename {middleware => plugin}/cache/cache_test.go (94%)
 rename {middleware => plugin}/cache/freq/freq.go (100%)
 rename {middleware => plugin}/cache/freq/freq_test.go (100%)
 rename {middleware => plugin}/cache/handler.go (87%)
 rename {middleware => plugin}/cache/item.go (95%)
 rename {middleware => plugin}/cache/prefech_test.go (74%)
 rename {middleware => plugin}/cache/setup.go (93%)
 rename {middleware => plugin}/cache/setup_test.go (100%)
 rename {middleware => plugin}/chaos/README.md (82%)
 rename {middleware => plugin}/chaos/chaos.go (82%)
 rename {middleware => plugin}/chaos/chaos_test.go (90%)
 rename {middleware => plugin}/chaos/setup.go (85%)
 rename {middleware => plugin}/chaos/setup_test.go (100%)
 rename {middleware => plugin}/debug/README.md (73%)
 rename {middleware => plugin}/debug/debug.go (80%)
 rename {middleware => plugin}/debug/debug_test.go (100%)
 rename {middleware => plugin}/dnssec/README.md (91%)
 rename {middleware => plugin}/dnssec/black_lies.go (100%)
 rename {middleware => plugin}/dnssec/black_lies_test.go (96%)
 rename {middleware => plugin}/dnssec/cache.go (100%)
 rename {middleware => plugin}/dnssec/cache_test.go (87%)
 rename {middleware => plugin}/dnssec/dnskey.go (100%)
 rename {middleware => plugin}/dnssec/dnssec.go (88%)
 rename {middleware => plugin}/dnssec/dnssec_test.go (98%)
 rename {middleware => plugin}/dnssec/handler.go (81%)
 rename {middleware => plugin}/dnssec/handler_test.go (95%)
 rename {middleware => plugin}/dnssec/responsewriter.go (92%)
 rename {middleware => plugin}/dnssec/rrsig.go (100%)
 rename {middleware => plugin}/dnssec/setup.go (88%)
 rename {middleware => plugin}/dnssec/setup_test.go (100%)
 rename {middleware => plugin}/dnstap/README.md (100%)
 rename {middleware => plugin}/dnstap/handler.go (78%)
 rename {middleware => plugin}/dnstap/handler_test.go (92%)
 rename {middleware => plugin}/dnstap/msg/msg.go (97%)
 rename {middleware => plugin}/dnstap/msg/msg_test.go (95%)
 rename {middleware => plugin}/dnstap/msg/wrapper.go (100%)
 rename {middleware => plugin}/dnstap/out/socket.go (100%)
 rename {middleware => plugin}/dnstap/out/socket_test.go (100%)
 rename {middleware => plugin}/dnstap/out/tcp.go (100%)
 rename {middleware => plugin}/dnstap/out/tcp_test.go (100%)
 rename {middleware => plugin}/dnstap/setup.go (84%)
 rename {middleware => plugin}/dnstap/setup_test.go (100%)
 rename {middleware => plugin}/dnstap/taprw/writer.go (97%)
 rename {middleware => plugin}/dnstap/taprw/writer_test.go (90%)
 rename {middleware => plugin}/dnstap/test/helpers.go (96%)
 rename {middleware => plugin}/erratic/README.md (78%)
 rename {middleware => plugin}/erratic/autopath.go (70%)
 rename {middleware => plugin}/erratic/erratic.go (88%)
 rename {middleware => plugin}/erratic/erratic_test.go (94%)
 rename {middleware => plugin}/erratic/setup.go (92%)
 rename {middleware => plugin}/erratic/setup_test.go (100%)
 rename {middleware => plugin}/errors/README.md (100%)
 rename {middleware => plugin}/errors/errors.go (83%)
 rename {middleware => plugin}/errors/errors_test.go (80%)
 rename {middleware => plugin}/errors/setup.go (82%)
 rename {middleware => plugin}/errors/setup_test.go (100%)
 rename {middleware => plugin}/etcd/README.md (92%)
 rename {middleware => plugin}/etcd/cname_test.go (93%)
 rename {middleware => plugin}/etcd/etcd.go (87%)
 rename {middleware => plugin}/etcd/group_test.go (91%)
 rename {middleware => plugin}/etcd/handler.go (56%)
 rename {middleware => plugin}/etcd/lookup_test.go (96%)
 rename {middleware => plugin}/etcd/msg/path.go (96%)
 rename {middleware => plugin}/etcd/msg/path_test.go (100%)
 rename {middleware => plugin}/etcd/msg/service.go (100%)
 rename {middleware => plugin}/etcd/msg/service_test.go (100%)
 rename {middleware => plugin}/etcd/msg/type.go (100%)
 rename {middleware => plugin}/etcd/msg/type_test.go (100%)
 rename {middleware => plugin}/etcd/multi_test.go (90%)
 rename {middleware => plugin}/etcd/other_test.go (96%)
 rename {middleware => plugin}/etcd/setup.go (86%)
 rename {middleware => plugin}/etcd/setup_test.go (100%)
 rename {middleware => plugin}/etcd/stub.go (93%)
 rename {middleware => plugin}/etcd/stub_handler.go (97%)
 rename {middleware => plugin}/etcd/stub_test.go (93%)
 rename {middleware => plugin}/federation/README.md (91%)
 rename {middleware => plugin}/federation/federation.go (77%)
 rename {middleware => plugin}/federation/federation_test.go (92%)
 rename {middleware => plugin}/federation/kubernetes_api_test.go (97%)
 rename {middleware => plugin}/federation/setup.go (80%)
 rename {middleware => plugin}/federation/setup_test.go (100%)
 rename {middleware => plugin}/file/README.md (94%)
 rename {middleware => plugin}/file/closest.go (89%)
 rename {middleware => plugin}/file/closest_test.go (100%)
 rename {middleware => plugin}/file/cname_test.go (95%)
 rename {middleware => plugin}/file/delegation_test.go (98%)
 rename {middleware => plugin}/file/dname.go (95%)
 rename {middleware => plugin}/file/dname_test.go (98%)
 rename {middleware => plugin}/file/dnssec_test.go (99%)
 rename {middleware => plugin}/file/dnssex_test.go (100%)
 rename {middleware => plugin}/file/ds_test.go (95%)
 rename {middleware => plugin}/file/ent_test.go (98%)
 rename {middleware => plugin}/file/example_org.go (100%)
 rename {middleware => plugin}/file/file.go (91%)
 rename {middleware => plugin}/file/file_test.go (100%)
 rename {middleware => plugin}/file/glue_test.go (98%)
 rename {middleware => plugin}/file/include_test.go (93%)
 rename {middleware => plugin}/file/lookup.go (99%)
 rename {middleware => plugin}/file/lookup_test.go (98%)
 rename {middleware => plugin}/file/notify.go (97%)
 rename {middleware => plugin}/file/nsec3_test.go (100%)
 rename {middleware => plugin}/file/reload.go (100%)
 rename {middleware => plugin}/file/reload_test.go (97%)
 rename {middleware => plugin}/file/secondary.go (100%)
 rename {middleware => plugin}/file/secondary_test.go (98%)
 rename {middleware => plugin}/file/setup.go (90%)
 rename {middleware => plugin}/file/setup_test.go (97%)
 rename {middleware => plugin}/file/tree/all.go (100%)
 rename {middleware => plugin}/file/tree/elem.go (100%)
 rename {middleware => plugin}/file/tree/less.go (100%)
 rename {middleware => plugin}/file/tree/less_test.go (100%)
 rename {middleware => plugin}/file/tree/print.go (100%)
 rename {middleware => plugin}/file/tree/tree.go (100%)
 rename {middleware => plugin}/file/wildcard.go (100%)
 rename {middleware => plugin}/file/wildcard_test.go (98%)
 rename {middleware => plugin}/file/xfr.go (83%)
 rename {middleware => plugin}/file/xfr_test.go (100%)
 rename {middleware => plugin}/file/zone.go (97%)
 rename {middleware => plugin}/file/zone_test.go (100%)
 rename {middleware => plugin}/health/README.md (71%)
 rename {middleware => plugin}/health/health.go (84%)
 rename {middleware => plugin}/health/health_test.go (95%)
 rename {middleware => plugin}/health/healther.go (58%)
 rename {middleware => plugin}/health/setup.go (85%)
 rename {middleware => plugin}/health/setup_test.go (100%)
 rename {middleware => plugin}/hosts/README.md (77%)
 rename {middleware => plugin}/hosts/hosts.go (85%)
 rename {middleware => plugin}/hosts/hosts_test.go (93%)
 rename {middleware => plugin}/hosts/hostsfile.go (96%)
 rename {middleware => plugin}/hosts/hostsfile_test.go (100%)
 rename {middleware => plugin}/hosts/setup.go (86%)
 rename {middleware => plugin}/hosts/setup_test.go (100%)
 rename {middleware => plugin}/kubernetes/DEV-README.md (100%)
 rename {middleware => plugin}/kubernetes/README.md (87%)
 rename {middleware => plugin}/kubernetes/apiproxy.go (96%)
 rename {middleware => plugin}/kubernetes/autopath.go (86%)
 rename {middleware => plugin}/kubernetes/controller.go (100%)
 rename {middleware => plugin}/kubernetes/federation.go (86%)
 create mode 100644 plugin/kubernetes/handler.go
 rename {middleware => plugin}/kubernetes/handler_pod_disabled_test.go (92%)
 rename {middleware => plugin}/kubernetes/handler_pod_insecure_test.go (91%)
 rename {middleware => plugin}/kubernetes/handler_pod_verified_test.go (92%)
 rename {middleware => plugin}/kubernetes/handler_test.go (98%)
 rename {middleware => plugin}/kubernetes/kubernetes.go (96%)
 rename {middleware => plugin}/kubernetes/kubernetes_apex_test.go (93%)
 rename {middleware => plugin}/kubernetes/kubernetes_test.go (98%)
 rename {middleware => plugin}/kubernetes/local.go (100%)
 rename {middleware => plugin}/kubernetes/ns.go (100%)
 rename {middleware => plugin}/kubernetes/ns_test.go (100%)
 rename {middleware => plugin}/kubernetes/parse.go (95%)
 rename {middleware => plugin}/kubernetes/parse_test.go (100%)
 rename {middleware => plugin}/kubernetes/reverse.go (88%)
 rename {middleware => plugin}/kubernetes/reverse_test.go (96%)
 rename {middleware => plugin}/kubernetes/setup.go (90%)
 rename {middleware => plugin}/kubernetes/setup_reverse_test.go (100%)
 rename {middleware => plugin}/kubernetes/setup_test.go (100%)
 rename {middleware => plugin}/kubernetes/setup_ttl_test.go (100%)
 rename {middleware => plugin}/loadbalance/README.md (100%)
 rename {middleware => plugin}/loadbalance/handler.go (50%)
 rename {middleware => plugin}/loadbalance/loadbalance.go (100%)
 rename {middleware => plugin}/loadbalance/loadbalance_test.go (94%)
 rename {middleware => plugin}/loadbalance/setup.go (74%)
 rename {middleware => plugin}/log/README.md (100%)
 rename {middleware => plugin}/log/log.go (74%)
 rename {middleware => plugin}/log/log_test.go (92%)
 rename {middleware => plugin}/log/setup.go (87%)
 rename {middleware => plugin}/log/setup_test.go (98%)
 rename {middleware => plugin}/metrics/README.md (94%)
 rename {middleware => plugin}/metrics/handler.go (66%)
 rename {middleware => plugin}/metrics/metrics.go (90%)
 rename {middleware => plugin}/metrics/metrics_test.go (88%)
 rename {middleware => plugin}/metrics/setup.go (88%)
 rename {middleware => plugin}/metrics/setup_test.go (100%)
 rename {middleware => plugin}/metrics/test/scrape.go (100%)
 rename {middleware => plugin}/metrics/vars/report.go (100%)
 rename {middleware => plugin}/metrics/vars/vars.go (88%)
 rename {middleware => plugin}/normalize.go (99%)
 rename {middleware => plugin}/normalize_test.go (99%)
 rename {middleware => plugin}/pkg/cache/cache.go (100%)
 rename {middleware => plugin}/pkg/cache/cache_test.go (100%)
 rename {middleware => plugin}/pkg/cache/shard_test.go (100%)
 rename {middleware => plugin}/pkg/dnsrecorder/recorder.go (100%)
 rename {middleware => plugin}/pkg/dnsrecorder/recorder_test.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/cname.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/cname_test.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/dedup.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/doc.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/host.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/host_test.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/join.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/join_test.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/reverse.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/reverse_test.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/zone.go (100%)
 rename {middleware => plugin}/pkg/dnsutil/zone_test.go (100%)
 rename {middleware => plugin}/pkg/edns/edns.go (92%)
 rename {middleware => plugin}/pkg/edns/edns_test.go (100%)
 rename {middleware => plugin}/pkg/healthcheck/healthcheck.go (100%)
 rename {middleware => plugin}/pkg/healthcheck/policy.go (100%)
 rename {middleware => plugin}/pkg/healthcheck/policy_test.go (100%)
 rename {middleware => plugin}/pkg/nonwriter/nonwriter.go (100%)
 rename {middleware => plugin}/pkg/nonwriter/nonwriter_test.go (100%)
 rename {middleware => plugin}/pkg/rcode/rcode.go (100%)
 rename {middleware => plugin}/pkg/rcode/rcode_test.go (100%)
 rename {middleware => plugin}/pkg/replacer/replacer.go (98%)
 rename {middleware => plugin}/pkg/replacer/replacer_test.go (93%)
 rename {middleware => plugin}/pkg/response/classify.go (100%)
 rename {middleware => plugin}/pkg/response/typify.go (100%)
 rename {middleware => plugin}/pkg/response/typify_test.go (98%)
 rename {middleware => plugin}/pkg/singleflight/singleflight.go (100%)
 rename {middleware => plugin}/pkg/singleflight/singleflight_test.go (100%)
 rename {middleware => plugin}/pkg/tls/tls.go (100%)
 rename {middleware => plugin}/pkg/tls/tls_test.go (97%)
 rename {middleware => plugin}/pkg/trace/trace.go (72%)
 rename middleware/middleware.go => plugin/plugin.go (83%)
 create mode 100644 plugin/plugin_test.go
 rename {middleware => plugin}/pprof/README.md (100%)
 rename {middleware => plugin}/pprof/pprof.go (100%)
 rename {middleware => plugin}/pprof/setup.go (75%)
 rename {middleware => plugin}/pprof/setup_test.go (100%)
 rename {middleware => plugin}/proxy/README.md (97%)
 rename {middleware => plugin}/proxy/dns.go (100%)
 rename {middleware => plugin}/proxy/dnstap_test.go (90%)
 rename {middleware => plugin}/proxy/exchanger.go (100%)
 rename {middleware => plugin}/proxy/google.go (98%)
 rename {middleware => plugin}/proxy/google_rr.go (100%)
 rename {middleware => plugin}/proxy/google_test.go (100%)
 rename {middleware => plugin}/proxy/grpc.go (94%)
 rename {middleware => plugin}/proxy/grpc_test.go (96%)
 rename {middleware => plugin}/proxy/lookup.go (95%)
 rename {middleware => plugin}/proxy/metrics.go (85%)
 rename {middleware => plugin}/proxy/proxy.go (87%)
 rename {middleware => plugin}/proxy/proxy_test.go (100%)
 rename {middleware => plugin}/proxy/response.go (100%)
 rename {middleware => plugin}/proxy/setup.go (81%)
 rename {middleware => plugin}/proxy/upstream.go (91%)
 rename {middleware => plugin}/proxy/upstream_test.go (99%)
 rename {middleware => plugin}/reverse/README.md (94%)
 rename {middleware => plugin}/reverse/network.go (100%)
 rename {middleware => plugin}/reverse/network_test.go (100%)
 rename {middleware => plugin}/reverse/reverse.go (89%)
 rename {middleware => plugin}/reverse/reverse_test.go (89%)
 rename {middleware => plugin}/reverse/setup.go (93%)
 rename {middleware => plugin}/reverse/setup_test.go (100%)
 rename {middleware => plugin}/rewrite/README.md (100%)
 rename {middleware => plugin}/rewrite/class.go (100%)
 rename {middleware => plugin}/rewrite/condition.go (98%)
 rename {middleware => plugin}/rewrite/condition_test.go (100%)
 rename {middleware => plugin}/rewrite/edns0.go (99%)
 rename {middleware => plugin}/rewrite/name.go (74%)
 rename {middleware => plugin}/rewrite/reverter.go (100%)
 rename {middleware => plugin}/rewrite/rewrite.go (81%)
 rename {middleware => plugin}/rewrite/rewrite_test.go (97%)
 rename {middleware => plugin}/rewrite/setup.go (78%)
 rename {middleware => plugin}/rewrite/setup_test.go (100%)
 rename {middleware => plugin}/rewrite/testdata/testdir/empty (100%)
 rename {middleware => plugin}/rewrite/testdata/testfile (100%)
 rename {middleware => plugin}/rewrite/type.go (90%)
 rename {middleware => plugin}/root/README.md (81%)
 rename {middleware => plugin}/root/root.go (77%)
 rename {middleware => plugin}/root/root_test.go (100%)
 rename {middleware => plugin}/secondary/README.md (100%)
 create mode 100644 plugin/secondary/secondary.go
 rename {middleware => plugin}/secondary/setup.go (84%)
 rename {middleware => plugin}/secondary/setup_test.go (100%)
 create mode 100644 plugin/test/doc.go
 rename {middleware => plugin}/test/file.go (100%)
 rename {middleware => plugin}/test/file_test.go (100%)
 rename {middleware => plugin}/test/helpers.go (99%)
 rename {middleware => plugin}/test/responsewriter.go (100%)
 rename {middleware => plugin}/test/server.go (100%)
 rename {middleware => plugin}/tls/README.md (87%)
 rename {middleware => plugin}/tls/tls.go (65%)
 rename {middleware => plugin}/tls/tls_test.go (100%)
 rename {middleware => plugin}/trace/README.md (98%)
 rename {middleware => plugin}/trace/setup.go (92%)
 rename {middleware => plugin}/trace/setup_test.go (100%)
 rename {middleware => plugin}/trace/trace.go (87%)
 rename {middleware => plugin}/trace/trace_test.go (82%)
 rename {middleware => plugin}/whoami/README.md (79%)
 rename {middleware => plugin}/whoami/setup.go (65%)
 rename {middleware => plugin}/whoami/setup_test.go (100%)
 rename {middleware => plugin}/whoami/whoami.go (83%)
 rename {middleware => plugin}/whoami/whoami_test.go (92%)

diff --git a/.travis.yml b/.travis.yml
index 2b935135d..9458eb6cc 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,7 +18,7 @@ env:
   - TEST_TYPE=coverage ETCD_VERSION=2.3.1 K8S_VERSION=1.5.0 KUBECTL="docker exec hyperkube /hyperkube kubectl"
   - TEST_TYPE=integration ETCD_VERSION=2.3.1 K8S_VERSION=1.5.0 KUBECTL="docker exec hyperkube /hyperkube kubectl"
   - TEST_TYPE=core ETCD_VERSION=2.3.1 K8S_VERSION=1.5.0 KUBECTL="docker exec hyperkube /hyperkube kubectl"
-  - TEST_TYPE=middleware ETCD_VERSION=2.3.1 K8S_VERSION=1.5.0 KUBECTL="docker exec hyperkube /hyperkube kubectl"
+  - TEST_TYPE=plugin ETCD_VERSION=2.3.1 K8S_VERSION=1.5.0 KUBECTL="docker exec hyperkube /hyperkube kubectl"
 
 # In the Travis VM-based build environment, IPv6 networking is not
 # enabled by default. The sysctl operations below enable IPv6.
diff --git a/Makefile b/Makefile
index 1f11e64c4..b2d40280d 100644
--- a/Makefile
+++ b/Makefile
@@ -11,15 +11,15 @@ coredns: check godeps
 	CGO_ENABLED=0 $(SYSTEM) go build -v -ldflags="-s -w -X github.com/coredns/coredns/coremain.gitCommit=$(GITCOMMIT)" -o $(BINARY)
 
 .PHONY: check
-check: fmt core/zmiddleware.go core/dnsserver/zdirectives.go godeps
+check: fmt core/zplugin.go core/dnsserver/zdirectives.go godeps
 
 .PHONY: test
 test: check
-	go test -race -v ./test ./middleware/...
+	go test -race -v ./test ./plugin/...
 
 .PHONY: testk8s
 testk8s: check
-	go test -race -v -tags=k8s -run 'TestKubernetes' ./test ./middleware/kubernetes/...
+	go test -race -v -tags=k8s -run 'TestKubernetes' ./test ./plugin/kubernetes/...
 
 .PHONY: godeps
 godeps:
@@ -38,8 +38,8 @@ endif
 ifeq ($(TEST_TYPE),integration)
 	( cd test ; go test -v  -tags 'etcd k8s' -race ./... )
 endif
-ifeq ($(TEST_TYPE),middleware)
-	( cd middleware ; go test -v  -tags 'etcd k8s' -race ./... )
+ifeq ($(TEST_TYPE),plugin)
+	( cd plugin ; go test -v  -tags 'etcd k8s' -race ./... )
 endif
 ifeq ($(TEST_TYPE),coverage)
 	for d in `go list ./... | grep -v vendor`; do \
@@ -55,7 +55,7 @@ ifeq ($(TEST_TYPE),coverage)
 endif
 
 
-core/zmiddleware.go core/dnsserver/zdirectives.go: middleware.cfg
+core/zplugin.go core/dnsserver/zdirectives.go: plugin.cfg
 	go generate coredns.go
 
 .PHONY: gen
diff --git a/README.md b/README.md
index 55d1418ee..ba0e81815 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
 [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1250/badge)](https://bestpractices.coreinfrastructure.org/projects/1250)
 
 CoreDNS is a DNS server that started as a fork of [Caddy](https://github.com/mholt/caddy/). It has
-the same model: it chains middleware. In fact it's so similar that CoreDNS is now a server type
+the same model: it chains plugins. In fact it's so similar that CoreDNS is now a server type
 plugin for Caddy.
 
 CoreDNS is also a [Cloud Native Computing Foundation](https://cncf.io) inception level project.
@@ -18,7 +18,7 @@ layer that exposes services in etcd in the DNS. CoreDNS builds on this idea and
 server that can talk to multiple backends (etcd, kubernetes, etc.).
 
 CoreDNS aims to be a fast and flexible DNS server. The keyword here is *flexible*: with CoreDNS you
-are able to do what you want with your DNS data. And if not: write some middleware!
+are able to do what you want with your DNS data. And if not: write some plugin!
 
 CoreDNS can listen for DNS request coming in over UDP/TCP (go'old DNS), TLS ([RFC
 7858](https://tools.ietf.org/html/rfc7858)) and gRPC (not a standard).
@@ -44,7 +44,7 @@ Currently CoreDNS is able to:
 * Rewrite queries (qtype, qclass and qname) (*rewrite*).
 * Echo back the IP address, transport and port number used (*whoami*).
 
-Each of the middlewares has a README.md of its own.
+Each of the plugins has a README.md of its own.
 
 ## Status
 
@@ -92,7 +92,7 @@ The above command alone will have `coredns` binary generated.
 
 ## Examples
 
-When starting CoreDNS without any configuration, it loads the `whoami` middleware and starts
+When starting CoreDNS without any configuration, it loads the `whoami` plugin and starts
 listening on port 53 (override with `-dns.port`), it should show the following:
 
 ~~~ txt
diff --git a/core/coredns.go b/core/coredns.go
index cee9761e2..ef941aebf 100644
--- a/core/coredns.go
+++ b/core/coredns.go
@@ -6,27 +6,27 @@ import (
 	_ "github.com/coredns/coredns/core/dnsserver"
 
 	// plug in the standard directives (sorted)
-	_ "github.com/coredns/coredns/middleware/auto"
-	_ "github.com/coredns/coredns/middleware/bind"
-	_ "github.com/coredns/coredns/middleware/cache"
-	_ "github.com/coredns/coredns/middleware/chaos"
-	_ "github.com/coredns/coredns/middleware/dnssec"
-	_ "github.com/coredns/coredns/middleware/dnstap"
-	_ "github.com/coredns/coredns/middleware/erratic"
-	_ "github.com/coredns/coredns/middleware/errors"
-	_ "github.com/coredns/coredns/middleware/etcd"
-	_ "github.com/coredns/coredns/middleware/file"
-	_ "github.com/coredns/coredns/middleware/health"
-	_ "github.com/coredns/coredns/middleware/kubernetes"
-	_ "github.com/coredns/coredns/middleware/loadbalance"
-	_ "github.com/coredns/coredns/middleware/log"
-	_ "github.com/coredns/coredns/middleware/metrics"
-	_ "github.com/coredns/coredns/middleware/pprof"
-	_ "github.com/coredns/coredns/middleware/proxy"
-	_ "github.com/coredns/coredns/middleware/reverse"
-	_ "github.com/coredns/coredns/middleware/rewrite"
-	_ "github.com/coredns/coredns/middleware/root"
-	_ "github.com/coredns/coredns/middleware/secondary"
-	_ "github.com/coredns/coredns/middleware/trace"
-	_ "github.com/coredns/coredns/middleware/whoami"
+	_ "github.com/coredns/coredns/plugin/auto"
+	_ "github.com/coredns/coredns/plugin/bind"
+	_ "github.com/coredns/coredns/plugin/cache"
+	_ "github.com/coredns/coredns/plugin/chaos"
+	_ "github.com/coredns/coredns/plugin/dnssec"
+	_ "github.com/coredns/coredns/plugin/dnstap"
+	_ "github.com/coredns/coredns/plugin/erratic"
+	_ "github.com/coredns/coredns/plugin/errors"
+	_ "github.com/coredns/coredns/plugin/etcd"
+	_ "github.com/coredns/coredns/plugin/file"
+	_ "github.com/coredns/coredns/plugin/health"
+	_ "github.com/coredns/coredns/plugin/kubernetes"
+	_ "github.com/coredns/coredns/plugin/loadbalance"
+	_ "github.com/coredns/coredns/plugin/log"
+	_ "github.com/coredns/coredns/plugin/metrics"
+	_ "github.com/coredns/coredns/plugin/pprof"
+	_ "github.com/coredns/coredns/plugin/proxy"
+	_ "github.com/coredns/coredns/plugin/reverse"
+	_ "github.com/coredns/coredns/plugin/rewrite"
+	_ "github.com/coredns/coredns/plugin/root"
+	_ "github.com/coredns/coredns/plugin/secondary"
+	_ "github.com/coredns/coredns/plugin/trace"
+	_ "github.com/coredns/coredns/plugin/whoami"
 )
diff --git a/core/dnsserver/address.go b/core/dnsserver/address.go
index a6087df9f..e8ef13dbf 100644
--- a/core/dnsserver/address.go
+++ b/core/dnsserver/address.go
@@ -3,7 +3,7 @@ package dnsserver
 import (
 	"strings"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/miekg/dns"
 )
@@ -50,7 +50,7 @@ func normalizeZone(str string) (zoneAddr, error) {
 		str = str[len(TransportGRPC+"://"):]
 	}
 
-	host, port, err := middleware.SplitHostPort(str)
+	host, port, err := plugin.SplitHostPort(str)
 	if err != nil {
 		return zoneAddr{}, err
 	}
diff --git a/core/dnsserver/config.go b/core/dnsserver/config.go
index 0255c2651..0d25183c0 100644
--- a/core/dnsserver/config.go
+++ b/core/dnsserver/config.go
@@ -3,8 +3,7 @@ package dnsserver
 import (
 	"crypto/tls"
 
-	"github.com/coredns/coredns/middleware"
-
+	"github.com/coredns/coredns/plugin"
 	"github.com/mholt/caddy"
 )
 
@@ -20,7 +19,7 @@ type Config struct {
 	Port string
 
 	// Root points to a base directory we we find user defined "things".
-	// First consumer is the file middleware to looks for zone files in this place.
+	// First consumer is the file plugin to looks for zone files in this place.
 	Root string
 
 	// Debug controls the panic/recover mechanism that is enabled by default.
@@ -33,16 +32,16 @@ type Config struct {
 	// TLSConfig when listening for encrypted connections (gRPC, DNS-over-TLS).
 	TLSConfig *tls.Config
 
-	// Middleware stack.
-	Middleware []middleware.Middleware
+	// Plugin stack.
+	Plugin []plugin.Plugin
 
-	// Compiled middleware stack.
-	middlewareChain middleware.Handler
+	// Compiled plugin stack.
+	pluginChain plugin.Handler
 
-	// Middleware interested in announcing that they exist, so other middleware can call methods
+	// Plugin interested in announcing that they exist, so other plugin can call methods
 	// on them should register themselves here. The name should be the name as return by the
 	// Handler's Name method.
-	registry map[string]middleware.Handler
+	registry map[string]plugin.Handler
 }
 
 // GetConfig gets the Config that corresponds to c.
diff --git a/core/dnsserver/register.go b/core/dnsserver/register.go
index 779a7da0d..8e19ba46e 100644
--- a/core/dnsserver/register.go
+++ b/core/dnsserver/register.go
@@ -6,7 +6,7 @@ import (
 	"net"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 	"github.com/mholt/caddy/caddyfile"
@@ -119,27 +119,33 @@ func (h *dnsContext) MakeServers() ([]caddy.Server, error) {
 	return servers, nil
 }
 
-// AddMiddleware adds a middleware to a site's middleware stack.
-func (c *Config) AddMiddleware(m middleware.Middleware) {
-	c.Middleware = append(c.Middleware, m)
+// AddPlugin adds a plugin to a site's plugin stack.
+func (c *Config) AddPlugin(m plugin.Plugin) {
+	c.Plugin = append(c.Plugin, m)
+}
+
+// AddMiddleware adds a plugin to a site's plugin stack. This method is deprecated, use AddPlugin.
+func (c *Config) AddMiddleware(m plugin.Plugin) {
+	println("deprecated: use AddPlugin")
+	c.AddPlugin(m)
 }
 
 // registerHandler adds a handler to a site's handler registration. Handlers
-//  use this to announce that they exist to other middleware.
-func (c *Config) registerHandler(h middleware.Handler) {
+//  use this to announce that they exist to other plugin.
+func (c *Config) registerHandler(h plugin.Handler) {
 	if c.registry == nil {
-		c.registry = make(map[string]middleware.Handler)
+		c.registry = make(map[string]plugin.Handler)
 	}
 
 	// Just overwrite...
 	c.registry[h.Name()] = h
 }
 
-// Handler returns the middleware handler that has been added to the config under its name.
-// This is useful to inspect if a certain middleware is active in this server.
-// Note that this is order dependent and the order is defined in directives.go, i.e. if your middleware
-// comes before the middleware you are checking; it will not be there (yet).
-func (c *Config) Handler(name string) middleware.Handler {
+// Handler returns the plugin handler that has been added to the config under its name.
+// This is useful to inspect if a certain plugin is active in this server.
+// Note that this is order dependent and the order is defined in directives.go, i.e. if your plugin
+// comes before the plugin you are checking; it will not be there (yet).
+func (c *Config) Handler(name string) plugin.Handler {
 	if c.registry == nil {
 		return nil
 	}
diff --git a/core/dnsserver/server-grpc.go b/core/dnsserver/server-grpc.go
index 21c5cffeb..8f6d8106d 100644
--- a/core/dnsserver/server-grpc.go
+++ b/core/dnsserver/server-grpc.go
@@ -24,7 +24,7 @@ type ServergRPC struct {
 	listenAddr net.Addr
 }
 
-// NewServergRPC returns a new CoreDNS GRPC server and compiles all middleware in to it.
+// NewServergRPC returns a new CoreDNS GRPC server and compiles all plugin in to it.
 func NewServergRPC(addr string, group []*Config) (*ServergRPC, error) {
 
 	s, err := NewServer(addr, group)
@@ -62,7 +62,7 @@ func (s *ServergRPC) ServePacket(p net.PacketConn) error { return nil }
 // Listen implements caddy.TCPServer interface.
 func (s *ServergRPC) Listen() (net.Listener, error) {
 
-	// The *tls* middleware must make sure that multiple conflicting
+	// The *tls* plugin must make sure that multiple conflicting
 	// TLS configuration return an error: it can only be specified once.
 	tlsConfig := new(tls.Config)
 	for _, conf := range s.zones {
diff --git a/core/dnsserver/server-tls.go b/core/dnsserver/server-tls.go
index bd75d9e7d..2880b0183 100644
--- a/core/dnsserver/server-tls.go
+++ b/core/dnsserver/server-tls.go
@@ -14,7 +14,7 @@ type ServerTLS struct {
 	*Server
 }
 
-// NewServerTLS returns a new CoreDNS TLS server and compiles all middleware in to it.
+// NewServerTLS returns a new CoreDNS TLS server and compiles all plugin in to it.
 func NewServerTLS(addr string, group []*Config) (*ServerTLS, error) {
 	s, err := NewServer(addr, group)
 	if err != nil {
@@ -43,7 +43,7 @@ func (s *ServerTLS) ServePacket(p net.PacketConn) error { return nil }
 
 // Listen implements caddy.TCPServer interface.
 func (s *ServerTLS) Listen() (net.Listener, error) {
-	// The *tls* middleware must make sure that multiple conflicting
+	// The *tls* plugin must make sure that multiple conflicting
 	// TLS configuration return an error: it can only be specified once.
 	tlsConfig := new(tls.Config)
 	for _, conf := range s.zones {
diff --git a/core/dnsserver/server.go b/core/dnsserver/server.go
index 3f01cac5f..f24b1dd60 100644
--- a/core/dnsserver/server.go
+++ b/core/dnsserver/server.go
@@ -9,11 +9,11 @@ import (
 	"sync"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/metrics/vars"
-	"github.com/coredns/coredns/middleware/pkg/edns"
-	"github.com/coredns/coredns/middleware/pkg/rcode"
-	"github.com/coredns/coredns/middleware/pkg/trace"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/metrics/vars"
+	"github.com/coredns/coredns/plugin/pkg/edns"
+	"github.com/coredns/coredns/plugin/pkg/rcode"
+	"github.com/coredns/coredns/plugin/pkg/trace"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -35,12 +35,12 @@ type Server struct {
 	zones       map[string]*Config // zones keyed by their address
 	dnsWg       sync.WaitGroup     // used to wait on outstanding connections
 	connTimeout time.Duration      // the maximum duration of a graceful shutdown
-	trace       trace.Trace        // the trace middleware for the server
+	trace       trace.Trace        // the trace plugin for the server
 	debug       bool               // disable recover()
 	classChaos  bool               // allow non-INET class queries
 }
 
-// NewServer returns a new CoreDNS server and compiles all middleware in to it. By default CH class
+// NewServer returns a new CoreDNS server and compiles all plugin in to it. By default CH class
 // queries are blocked unless the chaos or proxy is loaded.
 func NewServer(addr string, group []*Config) (*Server, error) {
 
@@ -64,16 +64,16 @@ func NewServer(addr string, group []*Config) (*Server, error) {
 		}
 		// set the config per zone
 		s.zones[site.Zone] = site
-		// compile custom middleware for everything
-		var stack middleware.Handler
-		for i := len(site.Middleware) - 1; i >= 0; i-- {
-			stack = site.Middleware[i](stack)
+		// compile custom plugin for everything
+		var stack plugin.Handler
+		for i := len(site.Plugin) - 1; i >= 0; i-- {
+			stack = site.Plugin[i](stack)
 
 			// register the *handler* also
 			site.registerHandler(stack)
 
 			if s.trace == nil && stack.Name() == "trace" {
-				// we have to stash away the middleware, not the
+				// we have to stash away the plugin, not the
 				// Tracer object, because the Tracer won't be initialized yet
 				if t, ok := stack.(trace.Trace); ok {
 					s.trace = t
@@ -83,7 +83,7 @@ func NewServer(addr string, group []*Config) (*Server, error) {
 				s.classChaos = true
 			}
 		}
-		site.middlewareChain = stack
+		site.pluginChain = stack
 	}
 
 	return s, nil
@@ -177,11 +177,11 @@ func (s *Server) Address() string { return s.Addr }
 // ServeDNS is the entry point for every request to the address that s
 // is bound to. It acts as a multiplexer for the requests zonename as
 // defined in the request so that the correct zone
-// (configuration and middleware stack) will handle the request.
+// (configuration and plugin stack) will handle the request.
 func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
 	if !s.debug {
 		defer func() {
-			// In case the user doesn't enable error middleware, we still
+			// In case the user doesn't enable error plugin, we still
 			// need to make sure that we stay alive up here
 			if rec := recover(); rec != nil {
 				DefaultErrorFunc(w, r, dns.RcodeServerFailure)
@@ -218,8 +218,8 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 
 		if h, ok := s.zones[string(b[:l])]; ok {
 			if r.Question[0].Qtype != dns.TypeDS {
-				rcode, _ := h.middlewareChain.ServeDNS(ctx, w, r)
-				if !middleware.ClientWrite(rcode) {
+				rcode, _ := h.pluginChain.ServeDNS(ctx, w, r)
+				if !plugin.ClientWrite(rcode) {
 					DefaultErrorFunc(w, r, rcode)
 				}
 				return
@@ -239,8 +239,8 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 
 	if dshandler != nil {
 		// DS request, and we found a zone, use the handler for the query
-		rcode, _ := dshandler.middlewareChain.ServeDNS(ctx, w, r)
-		if !middleware.ClientWrite(rcode) {
+		rcode, _ := dshandler.pluginChain.ServeDNS(ctx, w, r)
+		if !plugin.ClientWrite(rcode) {
 			DefaultErrorFunc(w, r, rcode)
 		}
 		return
@@ -248,8 +248,8 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 
 	// Wildcard match, if we have found nothing try the root zone as a last resort.
 	if h, ok := s.zones["."]; ok {
-		rcode, _ := h.middlewareChain.ServeDNS(ctx, w, r)
-		if !middleware.ClientWrite(rcode) {
+		rcode, _ := h.pluginChain.ServeDNS(ctx, w, r)
+		if !plugin.ClientWrite(rcode) {
 			DefaultErrorFunc(w, r, rcode)
 		}
 		return
diff --git a/core/dnsserver/zdirectives.go b/core/dnsserver/zdirectives.go
index 528da4261..521b928cb 100644
--- a/core/dnsserver/zdirectives.go
+++ b/core/dnsserver/zdirectives.go
@@ -5,10 +5,10 @@ package dnsserver
 // Directives are registered in the order they should be
 // executed.
 //
-// Ordering is VERY important. Every middleware will
-// feel the effects of all other middleware below
+// Ordering is VERY important. Every plugin will
+// feel the effects of all other plugin below
 // (after) them during a request, but they must not
-// care what middleware above them are doing.
+// care what plugin above them are doing.
 
 var directives = []string{
 	"tls",
diff --git a/core/zmiddleware.go b/core/zmiddleware.go
deleted file mode 100644
index aa5361712..000000000
--- a/core/zmiddleware.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// generated by directives_generate.go; DO NOT EDIT
-
-package core
-
-import (
-	// Include all middleware.
-	_ "github.com/coredns/coredns/middleware/auto"
-	_ "github.com/coredns/coredns/middleware/autopath"
-	_ "github.com/coredns/coredns/middleware/bind"
-	_ "github.com/coredns/coredns/middleware/cache"
-	_ "github.com/coredns/coredns/middleware/chaos"
-	_ "github.com/coredns/coredns/middleware/debug"
-	_ "github.com/coredns/coredns/middleware/dnssec"
-	_ "github.com/coredns/coredns/middleware/dnstap"
-	_ "github.com/coredns/coredns/middleware/erratic"
-	_ "github.com/coredns/coredns/middleware/errors"
-	_ "github.com/coredns/coredns/middleware/etcd"
-	_ "github.com/coredns/coredns/middleware/federation"
-	_ "github.com/coredns/coredns/middleware/file"
-	_ "github.com/coredns/coredns/middleware/health"
-	_ "github.com/coredns/coredns/middleware/hosts"
-	_ "github.com/coredns/coredns/middleware/kubernetes"
-	_ "github.com/coredns/coredns/middleware/loadbalance"
-	_ "github.com/coredns/coredns/middleware/log"
-	_ "github.com/coredns/coredns/middleware/metrics"
-	_ "github.com/coredns/coredns/middleware/pprof"
-	_ "github.com/coredns/coredns/middleware/proxy"
-	_ "github.com/coredns/coredns/middleware/reverse"
-	_ "github.com/coredns/coredns/middleware/rewrite"
-	_ "github.com/coredns/coredns/middleware/root"
-	_ "github.com/coredns/coredns/middleware/secondary"
-	_ "github.com/coredns/coredns/middleware/tls"
-	_ "github.com/coredns/coredns/middleware/trace"
-	_ "github.com/coredns/coredns/middleware/whoami"
-	_ "github.com/mholt/caddy/startupshutdown"
-)
diff --git a/core/zplugin.go b/core/zplugin.go
new file mode 100644
index 000000000..522636b6a
--- /dev/null
+++ b/core/zplugin.go
@@ -0,0 +1,36 @@
+// generated by directives_generate.go; DO NOT EDIT
+
+package core
+
+import (
+	// Include all plugin.
+	_ "github.com/coredns/coredns/plugin/auto"
+	_ "github.com/coredns/coredns/plugin/autopath"
+	_ "github.com/coredns/coredns/plugin/bind"
+	_ "github.com/coredns/coredns/plugin/cache"
+	_ "github.com/coredns/coredns/plugin/chaos"
+	_ "github.com/coredns/coredns/plugin/debug"
+	_ "github.com/coredns/coredns/plugin/dnssec"
+	_ "github.com/coredns/coredns/plugin/dnstap"
+	_ "github.com/coredns/coredns/plugin/erratic"
+	_ "github.com/coredns/coredns/plugin/errors"
+	_ "github.com/coredns/coredns/plugin/etcd"
+	_ "github.com/coredns/coredns/plugin/federation"
+	_ "github.com/coredns/coredns/plugin/file"
+	_ "github.com/coredns/coredns/plugin/health"
+	_ "github.com/coredns/coredns/plugin/hosts"
+	_ "github.com/coredns/coredns/plugin/kubernetes"
+	_ "github.com/coredns/coredns/plugin/loadbalance"
+	_ "github.com/coredns/coredns/plugin/log"
+	_ "github.com/coredns/coredns/plugin/metrics"
+	_ "github.com/coredns/coredns/plugin/pprof"
+	_ "github.com/coredns/coredns/plugin/proxy"
+	_ "github.com/coredns/coredns/plugin/reverse"
+	_ "github.com/coredns/coredns/plugin/rewrite"
+	_ "github.com/coredns/coredns/plugin/root"
+	_ "github.com/coredns/coredns/plugin/secondary"
+	_ "github.com/coredns/coredns/plugin/tls"
+	_ "github.com/coredns/coredns/plugin/trace"
+	_ "github.com/coredns/coredns/plugin/whoami"
+	_ "github.com/mholt/caddy/startupshutdown"
+)
diff --git a/directives_generate.go b/directives_generate.go
index 3ecb7e066..8c74fa573 100644
--- a/directives_generate.go
+++ b/directives_generate.go
@@ -17,7 +17,7 @@ func main() {
 	mi := make(map[string]string, 0)
 	md := make(map[int]string, 0)
 
-	file, err := os.Open(middlewareFile)
+	file, err := os.Open(pluginFile)
 	fatalIfErr(err)
 
 	defer file.Close()
@@ -41,14 +41,14 @@ func main() {
 			log.Fatalf("Duplicate priority '%d', slot already taken by %q", priority, v)
 		}
 		md[priority] = items[1]
-		mi[items[1]] = middlewarePath + items[2] // Default, unless overridden by 3rd arg
+		mi[items[1]] = pluginPath + items[2] // Default, unless overridden by 3rd arg
 
-		if _, err := os.Stat(middlewareFSPath + items[2]); err != nil { // External package has been given
+		if _, err := os.Stat(pluginFSPath + items[2]); err != nil { // External package has been given
 			mi[items[1]] = items[2]
 		}
 	}
 
-	genImports("core/zmiddleware.go", "core", mi)
+	genImports("core/zplugin.go", "core", mi)
 	genDirectives("core/dnsserver/zdirectives.go", "dnsserver", md)
 }
 
@@ -59,7 +59,7 @@ func genImports(file, pack string, mi map[string]string) {
 		outs += "\n"
 	}
 
-	outs += "// Include all middleware.\n"
+	outs += "// Include all plugin.\n"
 	for _, v := range mi {
 		outs += `_ "` + v + `"` + "\n"
 	}
@@ -79,10 +79,10 @@ func genDirectives(file, pack string, md map[int]string) {
 // Directives are registered in the order they should be
 // executed.
 //
-// Ordering is VERY important. Every middleware will
-// feel the effects of all other middleware below
+// Ordering is VERY important. Every plugin will
+// feel the effects of all other plugin below
 // (after) them during a request, but they must not
-// care what middleware above them are doing.
+// care what plugin above them are doing.
 
 var directives = []string{
 `
@@ -113,8 +113,8 @@ func fatalIfErr(err error) {
 }
 
 const (
-	middlewarePath   = "github.com/coredns/coredns/middleware/"
-	middlewareFile   = "middleware.cfg"
-	middlewareFSPath = "middleware/" // Where the middleware packages are located on the file system
-	header           = "// generated by directives_generate.go; DO NOT EDIT\n\n"
+	pluginPath   = "github.com/coredns/coredns/plugin/"
+	pluginFile   = "plugin.cfg"
+	pluginFSPath = "plugin/" // Where the plugins are located on the file system
+	header       = "// generated by directives_generate.go; DO NOT EDIT\n\n"
 )
diff --git a/middleware/kubernetes/handler.go b/middleware/kubernetes/handler.go
deleted file mode 100644
index e83ab3d7d..000000000
--- a/middleware/kubernetes/handler.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package kubernetes
-
-import (
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/request"
-
-	"github.com/miekg/dns"
-	"golang.org/x/net/context"
-)
-
-// ServeDNS implements the middleware.Handler interface.
-func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
-	state := request.Request{W: w, Req: r}
-
-	m := new(dns.Msg)
-	m.SetReply(r)
-	m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
-
-	zone := middleware.Zones(k.Zones).Matches(state.Name())
-	if zone == "" {
-		return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
-	}
-
-	state.Zone = zone
-
-	var (
-		records []dns.RR
-		extra   []dns.RR
-		err     error
-	)
-
-	switch state.Type() {
-	case "A":
-		records, err = middleware.A(&k, zone, state, nil, middleware.Options{})
-	case "AAAA":
-		records, err = middleware.AAAA(&k, zone, state, nil, middleware.Options{})
-	case "TXT":
-		records, err = middleware.TXT(&k, zone, state, middleware.Options{})
-	case "CNAME":
-		records, err = middleware.CNAME(&k, zone, state, middleware.Options{})
-	case "PTR":
-		records, err = middleware.PTR(&k, zone, state, middleware.Options{})
-	case "MX":
-		records, extra, err = middleware.MX(&k, zone, state, middleware.Options{})
-	case "SRV":
-		records, extra, err = middleware.SRV(&k, zone, state, middleware.Options{})
-	case "SOA":
-		records, err = middleware.SOA(&k, zone, state, middleware.Options{})
-	case "NS":
-		if state.Name() == zone {
-			records, extra, err = middleware.NS(&k, zone, state, middleware.Options{})
-			break
-		}
-		fallthrough
-	default:
-		// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
-		_, err = middleware.A(&k, zone, state, nil, middleware.Options{})
-	}
-
-	if k.IsNameError(err) {
-		if k.Fallthrough {
-			return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
-		}
-		return middleware.BackendError(&k, zone, dns.RcodeNameError, state, nil /* err */, middleware.Options{})
-	}
-	if err != nil {
-		return dns.RcodeServerFailure, err
-	}
-
-	if len(records) == 0 {
-		return middleware.BackendError(&k, zone, dns.RcodeSuccess, state, nil, middleware.Options{})
-	}
-
-	m.Answer = append(m.Answer, records...)
-	m.Extra = append(m.Extra, extra...)
-
-	m = dnsutil.Dedup(m)
-	state.SizeAndDo(m)
-	m, _ = state.Scrub(m)
-	w.WriteMsg(m)
-	return dns.RcodeSuccess, nil
-}
-
-// Name implements the Handler interface.
-func (k Kubernetes) Name() string { return "kubernetes" }
diff --git a/middleware/middleware_test.go b/middleware/middleware_test.go
deleted file mode 100644
index c870d7c16..000000000
--- a/middleware/middleware_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package middleware
diff --git a/middleware/secondary/secondary.go b/middleware/secondary/secondary.go
deleted file mode 100644
index da31d5171..000000000
--- a/middleware/secondary/secondary.go
+++ /dev/null
@@ -1,10 +0,0 @@
-// Package secondary implements a secondary middleware.
-package secondary
-
-import "github.com/coredns/coredns/middleware/file"
-
-// Secondary implements a secondary middleware that allows CoreDNS to retrieve (via AXFR)
-// zone information from a primary server.
-type Secondary struct {
-	file.File
-}
diff --git a/middleware/test/doc.go b/middleware/test/doc.go
deleted file mode 100644
index e2f90262b..000000000
--- a/middleware/test/doc.go
+++ /dev/null
@@ -1,2 +0,0 @@
-// Package test contains helper functions for writing middleware tests.
-package test
diff --git a/middleware.cfg b/plugin.cfg
similarity index 66%
rename from middleware.cfg
rename to plugin.cfg
index ba2ef74ff..550dd246d 100644
--- a/middleware.cfg
+++ b/plugin.cfg
@@ -1,22 +1,22 @@
 # Directives are registered in the order they should be
 # executed.
 #
-# Ordering is VERY important. Every middleware will
-# feel the effects of all other middleware below
+# Ordering is VERY important. Every plugin will
+# feel the effects of all other plugin below
 # (after) them during a request, but they must not
-# care what middleware above them are doing.
+# care what plugin above them are doing.
 
-# How to rebuild with updated middleware configurations:
+# How to rebuild with updated plugin configurations:
 # Modify the list below and run `go gen && go build`
 
 # The parser takes the input format of
-#     <order>:<middleware-name>:<package-name>
+#     <order>:<plugin-name>:<package-name>
 # Or
-#     <order>:<middleware-name>:<fully-qualified-package-name>
+#     <order>:<plugin-name>:<fully-qualified-package-name>
 #
-# External middleware example:
-# 80:log:github.com/coredns/coredns/middleware/log
-# Local middleware example:
+# External plugin example:
+# 80:log:github.com/coredns/coredns/plugin/log
+# Local plugin example:
 # 80:log:log
 
 1:tls:tls
diff --git a/middleware.md b/plugin.md
similarity index 60%
rename from middleware.md
rename to plugin.md
index f946e63e5..b71e2ed0c 100644
--- a/middleware.md
+++ b/plugin.md
@@ -5,14 +5,14 @@
 From the Caddy docs:
 
 > Oh yes, those pesky return values on ServeHTTP(). You read the documentation so you already know
-> what they mean. But what does that imply for the behavior of your middleware?
+> what they mean. But what does that imply for the behavior of your plugin?
 >
 > Basically, return a status code only if you did NOT write to the response body. If you DO write to
-> the response body, return a status code of 0. Return an error value if your middleware encountered
+> the response body, return a status code of 0. Return an error value if your plugin encountered
 > an error that you want logged. It is common to return an error status and an error value together,
 > so that the error handler up the chain can write the correct error page.
 >
-> The returned status code is not logged directly; rather, it tells middleware higher up the chain
+> The returned status code is not logged directly; rather, it tells plugin higher up the chain
 > what status code to use if/when the response body is written. Again, return a 0 status if you've
 > already written a body!
 
@@ -27,28 +27,28 @@ So CoreDNS treats:
 * NOTIMP (dns.RcodeNotImplemented)
 
 as special and will then assume nothing has written to the client. In all other cases it is assumes
-something has been written to the client (by the middleware).
+something has been written to the client (by the plugin).
 
 ## Hooking It Up
 
-See a couple of blog posts on how to write and add middleware to CoreDNS:
+See a couple of blog posts on how to write and add plugin to CoreDNS:
 
-* <https://blog.coredns.io/2017/03/01/how-to-add-middleware-to-coredns/>
-* <https://blog.coredns.io/2016/12/19/writing-middleware-for-coredns/>, slightly older, but useful.
+* <https://blog.coredns.io/2017/03/01/how-to-add-plugin-to-coredns/>
+* <https://blog.coredns.io/2016/12/19/writing-plugin-for-coredns/>, slightly older, but useful.
 
 ## Metrics
 
-When exporting metrics the *Namespace* should be `middleware.Namespace` (="coredns"), and the
-*Subsystem* should be the name of the middleware. The README.md for the middleware should then
-also contain a *Metrics* section detailing the metrics. If the middleware supports dynamic health
+When exporting metrics the *Namespace* should be `plugin.Namespace` (="coredns"), and the
+*Subsystem* should be the name of the plugin. The README.md for the plugin should then
+also contain a *Metrics* section detailing the metrics. If the plugin supports dynamic health
 reporting it should also have *Health* section detailing on its inner workings.
 
 ## Documentation
 
-Each middleware should have a README.md explaining what the middleware does and how it is
+Each plugin should have a README.md explaining what the plugin does and how it is
 configured. The file should have the following layout:
 
-* Title: use the middleware's name
+* Title: use the plugin's name
 * Subsection titled: "Syntax"
 * Subsection titled: "Examples"
 
@@ -58,7 +58,7 @@ More sections are of course possible.
 
 We use the Unix manual page style:
 
-* The name of middleware in the running text should be italic: *middleware*.
+* The name of plugin in the running text should be italic: *plugin*.
 * all CAPITAL: user supplied argument, in the running text references this use strong text: `**`:
   **EXAMPLE**.
 * Optional text: in block quotes: `[optional]`.
@@ -72,8 +72,8 @@ standard domain names created for this purpose.
 
 ## Fallthrough
 
-In a perfect world the following would be true for middleware: "Either you are responsible for
-a zone or not". If the answer is "not", the middleware should call the next middleware in the chain.
+In a perfect world the following would be true for plugin: "Either you are responsible for
+a zone or not". If the answer is "not", the plugin should call the next plugin in the chain.
 If "yes" it should handle *all* names that fall in this zone and the names below - i.e. it should
 handle the entire domain.
 
@@ -82,24 +82,24 @@ handle the entire domain.
     file example.org db.example
 }
 ~~~
-In this example the *file* middleware is handling all names below (and including) `example.org`. If
-a query comes in that is not a subdomain (or equal to) `example.org` the next middleware is called.
+In this example the *file* plugin is handling all names below (and including) `example.org`. If
+a query comes in that is not a subdomain (or equal to) `example.org` the next plugin is called.
 
 Now, the world isn't perfect, and there are good reasons to "fallthrough" to the next middlware,
-meaning a middleware is only responsible for a subset of names within the zone. The first of these
-to appear was the *reverse* middleware that synthesis PTR and A/AAAA responses (useful with IPv6).
+meaning a plugin is only responsible for a subset of names within the zone. The first of these
+to appear was the *reverse* plugin that synthesis PTR and A/AAAA responses (useful with IPv6).
 
-The nature of the *reverse* middleware is such that it only deals with A,AAAA and PTR and then only
+The nature of the *reverse* plugin is such that it only deals with A,AAAA and PTR and then only
 for a subset of the names. Ideally you would want to layer *reverse* **in front off** another
-middleware such as *file* or *auto* (or even *proxy*). This means *reverse* handles some special
-reverse cases and **all other** request are handled by the backing middleware. This is exactly what
-"fallthrough" does. To keep things explicit we've opted that middlewares implement such behavior
+plugin such as *file* or *auto* (or even *proxy*). This means *reverse* handles some special
+reverse cases and **all other** request are handled by the backing plugin. This is exactly what
+"fallthrough" does. To keep things explicit we've opted that plugins implement such behavior
 should implement a `fallthrough` keyword.
 
 ### Example Fallthrough Usage
 
-The following Corefile example, sets up the *reverse* middleware, but disables fallthrough. It
-also defines a zonefile for use with the *file* middleware for other names in the `compute.internal`.
+The following Corefile example, sets up the *reverse* plugin, but disables fallthrough. It
+also defines a zonefile for use with the *file* plugin for other names in the `compute.internal`.
 
 ~~~ txt
 arpa compute.internal {
@@ -136,13 +136,13 @@ compute.internal.	3600	IN	MX	10 mx.compute.internal.
 
 ## Qualifying for main repo
 
-Middleware for CoreDNS can live out-of-tree, `middleware.cfg` defaults to CoreDNS' repo but other
-repos work just as well. So when do we consider the inclusion of a new middleware in the main repo?
+Middleware for CoreDNS can live out-of-tree, `plugin.cfg` defaults to CoreDNS' repo but other
+repos work just as well. So when do we consider the inclusion of a new plugin in the main repo?
 
-* First, the middleware should be useful for other people. "Useful" is a subjective term. We will
+* First, the plugin should be useful for other people. "Useful" is a subjective term. We will
   probably need to further refine this.
-* It should be sufficiently different from other middleware to warrant inclusion.
+* It should be sufficiently different from other plugin to warrant inclusion.
 * Current internet standards need be supported: IPv4 and IPv6, so A and AAAA records should be
-  handled (if your middleware is in the business of dealing with address records that is).
+  handled (if your plugin is in the business of dealing with address records that is).
 * It must have tests.
 * It must have a README.md for documentation.
diff --git a/middleware/auto/README.md b/plugin/auto/README.md
similarity index 92%
rename from middleware/auto/README.md
rename to plugin/auto/README.md
index b69c1c291..7cbc4fced 100644
--- a/middleware/auto/README.md
+++ b/plugin/auto/README.md
@@ -3,7 +3,7 @@
 *auto* enables serving zone data from an RFC 1035-style master file which is automatically picked
 up from disk.
 
-The *auto* middleware is used for an "old-style" DNS server. It serves from a preloaded file that exists
+The *auto* plugin is used for an "old-style" DNS server. It serves from a preloaded file that exists
 on disk. If the zone file contains signatures (i.e. is signed, i.e. DNSSEC) correct DNSSEC answers
 are returned. Only NSEC is supported! If you use this setup *you* are responsible for resigning the
 zonefile. New zones or changed zone are automatically picked up from disk.
@@ -34,7 +34,7 @@ are used.
   pointing to external names. **ADDRESS** can be an IP address, and IP:port or a string pointing to
   a file that is structured as /etc/resolv.conf.
 
-All directives from the *file* middleware are supported. Note that *auto* will load all zones found,
+All directives from the *file* plugin are supported. Note that *auto* will load all zones found,
 even though the directive might only receive queries for a specific zone. I.e:
 
 ~~~
diff --git a/middleware/auto/auto.go b/plugin/auto/auto.go
similarity index 80%
rename from middleware/auto/auto.go
rename to plugin/auto/auto.go
index 31fe53e23..e9cab1950 100644
--- a/middleware/auto/auto.go
+++ b/plugin/auto/auto.go
@@ -5,10 +5,10 @@ import (
 	"regexp"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/file"
-	"github.com/coredns/coredns/middleware/metrics"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/file"
+	"github.com/coredns/coredns/plugin/metrics"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -18,7 +18,7 @@ import (
 type (
 	// Auto holds the zones and the loader configuration for automatically loading zones.
 	Auto struct {
-		Next middleware.Handler
+		Next plugin.Handler
 		*Zones
 
 		metrics *metrics.Metrics
@@ -39,7 +39,7 @@ type (
 	}
 )
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (a Auto) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	qname := state.Name()
@@ -47,13 +47,13 @@ func (a Auto) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
 	// TODO(miek): match the qname better in the map
 
 	// Precheck with the origins, i.e. are we allowed to looks here.
-	zone := middleware.Zones(a.Zones.Origins()).Matches(qname)
+	zone := plugin.Zones(a.Zones.Origins()).Matches(qname)
 	if zone == "" {
-		return middleware.NextOrFailure(a.Name(), a.Next, ctx, w, r)
+		return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
 	}
 
 	// Now the real zone.
-	zone = middleware.Zones(a.Zones.Names()).Matches(qname)
+	zone = plugin.Zones(a.Zones.Names()).Matches(qname)
 
 	a.Zones.RLock()
 	z, ok := a.Zones.Z[zone]
diff --git a/middleware/auto/regexp.go b/plugin/auto/regexp.go
similarity index 100%
rename from middleware/auto/regexp.go
rename to plugin/auto/regexp.go
diff --git a/middleware/auto/regexp_test.go b/plugin/auto/regexp_test.go
similarity index 100%
rename from middleware/auto/regexp_test.go
rename to plugin/auto/regexp_test.go
diff --git a/middleware/auto/setup.go b/plugin/auto/setup.go
similarity index 87%
rename from middleware/auto/setup.go
rename to plugin/auto/setup.go
index 426fb93b2..75966f8a0 100644
--- a/middleware/auto/setup.go
+++ b/plugin/auto/setup.go
@@ -9,11 +9,11 @@ import (
 	"time"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/file"
-	"github.com/coredns/coredns/middleware/metrics"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/file"
+	"github.com/coredns/coredns/plugin/metrics"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/proxy"
 
 	"github.com/mholt/caddy"
 )
@@ -28,7 +28,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	a, err := autoParse(c)
 	if err != nil {
-		return middleware.Error("auto", err)
+		return plugin.Error("auto", err)
 	}
 
 	c.OnStartup(func() error {
@@ -67,7 +67,7 @@ func setup(c *caddy.Controller) error {
 		return nil
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		a.Next = next
 		return a
 	})
@@ -93,7 +93,7 @@ func autoParse(c *caddy.Controller) (Auto, error) {
 			a.Zones.origins = args
 		}
 		for i := range a.Zones.origins {
-			a.Zones.origins[i] = middleware.Host(a.Zones.origins[i]).Normalize()
+			a.Zones.origins[i] = plugin.Host(a.Zones.origins[i]).Normalize()
 		}
 
 		for c.NextBlock() {
diff --git a/middleware/auto/setup_test.go b/plugin/auto/setup_test.go
similarity index 100%
rename from middleware/auto/setup_test.go
rename to plugin/auto/setup_test.go
diff --git a/middleware/auto/walk.go b/plugin/auto/walk.go
similarity index 97%
rename from middleware/auto/walk.go
rename to plugin/auto/walk.go
index 1bb351691..a98f2318e 100644
--- a/middleware/auto/walk.go
+++ b/plugin/auto/walk.go
@@ -7,7 +7,7 @@ import (
 	"path/filepath"
 	"regexp"
 
-	"github.com/coredns/coredns/middleware/file"
+	"github.com/coredns/coredns/plugin/file"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/auto/walk_test.go b/plugin/auto/walk_test.go
similarity index 100%
rename from middleware/auto/walk_test.go
rename to plugin/auto/walk_test.go
diff --git a/middleware/auto/watcher_test.go b/plugin/auto/watcher_test.go
similarity index 100%
rename from middleware/auto/watcher_test.go
rename to plugin/auto/watcher_test.go
diff --git a/middleware/auto/zone.go b/plugin/auto/zone.go
similarity index 97%
rename from middleware/auto/zone.go
rename to plugin/auto/zone.go
index ead26541e..e46f04e33 100644
--- a/middleware/auto/zone.go
+++ b/plugin/auto/zone.go
@@ -4,7 +4,7 @@ package auto
 import (
 	"sync"
 
-	"github.com/coredns/coredns/middleware/file"
+	"github.com/coredns/coredns/plugin/file"
 )
 
 // Zones maps zone names to a *Zone. This keep track of what we zones we have loaded at
diff --git a/middleware/autopath/README.md b/plugin/autopath/README.md
similarity index 69%
rename from middleware/autopath/README.md
rename to plugin/autopath/README.md
index 582b11f4e..02b4390fc 100644
--- a/middleware/autopath/README.md
+++ b/plugin/autopath/README.md
@@ -1,6 +1,6 @@
 # autopath
 
-The *autopath* middleware allows CoreDNS to perform server side search path completion.
+The *autopath* plugin allows CoreDNS to perform server side search path completion.
 If it sees a query that matches the first element of the configured search path, *autopath* will
 follow the chain of search path elements and returns the first reply that is not NXDOMAIN.
 On any failures the original reply is returned.
@@ -16,10 +16,10 @@ autopath [ZONE..] RESOLV-CONF
 
 * **ZONES** zones *autopath* should be authoritative for.
 * **RESOLV-CONF** points to a `resolv.conf` like file or uses a special syntax to point to another
-  middleware. For instance `@kubernetes`, will call out to the kubernetes middleware (for each
+  plugin. For instance `@kubernetes`, will call out to the kubernetes plugin (for each
   query) to retrieve the search list it should use.
 
-Currently the following set of middleware has implemented *autopath*:
+Currently the following set of plugin has implemented *autopath*:
 
 * *kubernetes*
 * *erratic*
@@ -37,9 +37,9 @@ Use `my-resolv.conf` as the file to get the search path from. This file only nee
 autopath @kubernetes
 ~~~
 
-Use the search path dynamically retrieved from the kubernetes middleware.
+Use the search path dynamically retrieved from the kubernetes plugin.
 
 ## Bugs
 
-When the *cache* middleware is enabled it is possible for pods in different namespaces to get the
+When the *cache* plugin is enabled it is possible for pods in different namespaces to get the
 same answer.
diff --git a/middleware/autopath/autopath.go b/plugin/autopath/autopath.go
similarity index 83%
rename from middleware/autopath/autopath.go
rename to plugin/autopath/autopath.go
index 94db8bc56..5c804a040 100644
--- a/middleware/autopath/autopath.go
+++ b/plugin/autopath/autopath.go
@@ -4,7 +4,7 @@ client's search path resolution by performing these lookups on the server...
 
 The server has a copy (via AutoPathFunc) of the client's search path and on
 receiving a query it first establish if the suffix matches the FIRST configured
-element. If no match can be found the query will be forwarded up the middleware
+element. If no match can be found the query will be forwarded up the plugin
 chain without interference (iff 'fallthrough' has been set).
 
 If the query is deemed to fall in the search path the server will perform the
@@ -34,23 +34,23 @@ package autopath
 import (
 	"log"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/pkg/nonwriter"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/nonwriter"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
 
-// Func defines the function middleware should implement to return a search
-// path to the autopath middleware. The last element of the slice must be the empty string.
+// Func defines the function plugin should implement to return a search
+// path to the autopath plugin. The last element of the slice must be the empty string.
 // If Func returns a nil slice, no autopathing will be done.
 type Func func(request.Request) []string
 
 // AutoPath perform autopath: service side search path completion.
 type AutoPath struct {
-	Next  middleware.Handler
+	Next  plugin.Handler
 	Zones []string
 
 	// Search always includes "" as the last element, so we try the base query with out any search paths added as well.
@@ -58,13 +58,13 @@ type AutoPath struct {
 	searchFunc Func
 }
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 
-	zone := middleware.Zones(a.Zones).Matches(state.Name())
+	zone := plugin.Zones(a.Zones).Matches(state.Name())
 	if zone == "" {
-		return middleware.NextOrFailure(a.Name(), a.Next, ctx, w, r)
+		return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
 	}
 
 	// Check if autopath should be done, searchFunc takes precedence over the local configured search path.
@@ -77,11 +77,11 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
 
 	if len(searchpath) == 0 {
 		log.Printf("[WARNING] No search path available for autopath")
-		return middleware.NextOrFailure(a.Name(), a.Next, ctx, w, r)
+		return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
 	}
 
 	if !firstInSearchPath(state.Name(), searchpath) {
-		return middleware.NextOrFailure(a.Name(), a.Next, ctx, w, r)
+		return plugin.NextOrFailure(a.Name(), a.Next, ctx, w, r)
 	}
 
 	origQName := state.QName()
@@ -104,7 +104,7 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
 		ar.Question[0].Name = newQName
 		nw := nonwriter.New(w)
 
-		rcode, err := middleware.NextOrFailure(a.Name(), a.Next, ctx, nw, ar)
+		rcode, err := plugin.NextOrFailure(a.Name(), a.Next, ctx, nw, ar)
 		if err != nil {
 			// Return now - not sure if this is the best. We should also check if the write has happened.
 			return rcode, err
@@ -115,7 +115,7 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
 			firstErr = err
 		}
 
-		if !middleware.ClientWrite(rcode) {
+		if !plugin.ClientWrite(rcode) {
 			continue
 		}
 
@@ -131,7 +131,7 @@ func (a *AutoPath) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
 		return rcode, err
 
 	}
-	if middleware.ClientWrite(firstRcode) {
+	if plugin.ClientWrite(firstRcode) {
 		w.WriteMsg(firstReply)
 	}
 	return firstRcode, firstErr
diff --git a/middleware/autopath/autopath_test.go b/plugin/autopath/autopath_test.go
similarity index 95%
rename from middleware/autopath/autopath_test.go
rename to plugin/autopath/autopath_test.go
index b99744ab8..a00bbf0a6 100644
--- a/middleware/autopath/autopath_test.go
+++ b/plugin/autopath/autopath_test.go
@@ -3,9 +3,9 @@ package autopath
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -100,7 +100,7 @@ func TestAutoPathNoAnswer(t *testing.T) {
 			t.Errorf("expected no error, got %v\n", err)
 			continue
 		}
-		if middleware.ClientWrite(rcode) {
+		if plugin.ClientWrite(rcode) {
 			t.Fatalf("expected no client write, got one for rcode %d", rcode)
 		}
 	}
diff --git a/middleware/autopath/cname.go b/plugin/autopath/cname.go
similarity index 100%
rename from middleware/autopath/cname.go
rename to plugin/autopath/cname.go
diff --git a/middleware/autopath/setup.go b/plugin/autopath/setup.go
similarity index 76%
rename from middleware/autopath/setup.go
rename to plugin/autopath/setup.go
index 368d92cf4..c83912a63 100644
--- a/middleware/autopath/setup.go
+++ b/plugin/autopath/setup.go
@@ -4,9 +4,9 @@ import (
 	"fmt"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/erratic"
-	"github.com/coredns/coredns/middleware/kubernetes"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/erratic"
+	"github.com/coredns/coredns/plugin/kubernetes"
 
 	"github.com/mholt/caddy"
 	"github.com/miekg/dns"
@@ -23,10 +23,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	ap, mw, err := autoPathParse(c)
 	if err != nil {
-		return middleware.Error("autopath", err)
+		return plugin.Error("autopath", err)
 	}
 
-	// Do this in OnStartup, so all middleware has been initialized.
+	// Do this in OnStartup, so all plugin has been initialized.
 	c.OnStartup(func() error {
 		m := dnsserver.GetConfig(c).Handler(mw)
 		if m == nil {
@@ -41,7 +41,7 @@ func setup(c *caddy.Controller) error {
 		return nil
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		ap.Next = next
 		return ap
 	})
@@ -49,7 +49,7 @@ func setup(c *caddy.Controller) error {
 	return nil
 }
 
-// allowedMiddleware has a list of middleware that can be used by autopath.
+// allowedMiddleware has a list of plugin that can be used by autopath.
 var allowedMiddleware = map[string]bool{
 	"@kubernetes": true,
 	"@erratic":    true,
@@ -77,7 +77,7 @@ func autoPathParse(c *caddy.Controller) (*AutoPath, string, error) {
 				return ap, "", fmt.Errorf("failed to parse %q: %v", resolv, err)
 			}
 			ap.search = rc.Search
-			middleware.Zones(ap.search).Normalize()
+			plugin.Zones(ap.search).Normalize()
 			ap.search = append(ap.search, "") // sentinal value as demanded.
 		}
 		ap.Zones = zoneAndresolv[:len(zoneAndresolv)-1]
@@ -86,7 +86,7 @@ func autoPathParse(c *caddy.Controller) (*AutoPath, string, error) {
 			copy(ap.Zones, c.ServerBlockKeys)
 		}
 		for i, str := range ap.Zones {
-			ap.Zones[i] = middleware.Host(str).Normalize()
+			ap.Zones[i] = plugin.Host(str).Normalize()
 		}
 	}
 	return ap, mw, nil
diff --git a/middleware/autopath/setup_test.go b/plugin/autopath/setup_test.go
similarity index 95%
rename from middleware/autopath/setup_test.go
rename to plugin/autopath/setup_test.go
index 0f086c5bb..3e13aa74f 100644
--- a/middleware/autopath/setup_test.go
+++ b/plugin/autopath/setup_test.go
@@ -6,7 +6,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/mholt/caddy"
 )
@@ -22,7 +22,7 @@ func TestSetupAutoPath(t *testing.T) {
 		input              string
 		shouldErr          bool
 		expectedZone       string
-		expectedMw         string   // expected middleware.
+		expectedMw         string   // expected plugin.
 		expectedSearch     []string // expected search path
 		expectedErrContent string   // substring from the expected error. Empty for positive cases.
 	}{
diff --git a/middleware/backend.go b/plugin/backend.go
similarity index 94%
rename from middleware/backend.go
rename to plugin/backend.go
index bf4bf8967..b520ce390 100644
--- a/middleware/backend.go
+++ b/plugin/backend.go
@@ -1,7 +1,7 @@
-package middleware
+package plugin
 
 import (
-	"github.com/coredns/coredns/middleware/etcd/msg"
+	"github.com/coredns/coredns/plugin/etcd/msg"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/backend_lookup.go b/plugin/backend_lookup.go
similarity index 98%
rename from middleware/backend_lookup.go
rename to plugin/backend_lookup.go
index 9e451feed..f04b397b2 100644
--- a/middleware/backend_lookup.go
+++ b/plugin/backend_lookup.go
@@ -1,4 +1,4 @@
-package middleware
+package plugin
 
 import (
 	"fmt"
@@ -6,8 +6,8 @@ import (
 	"net"
 	"time"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/bind/README.md b/plugin/bind/README.md
similarity index 100%
rename from middleware/bind/README.md
rename to plugin/bind/README.md
diff --git a/middleware/bind/bind.go b/plugin/bind/bind.go
similarity index 100%
rename from middleware/bind/bind.go
rename to plugin/bind/bind.go
diff --git a/middleware/bind/bind_test.go b/plugin/bind/bind_test.go
similarity index 100%
rename from middleware/bind/bind_test.go
rename to plugin/bind/bind_test.go
diff --git a/middleware/bind/setup.go b/plugin/bind/setup.go
similarity index 62%
rename from middleware/bind/setup.go
rename to plugin/bind/setup.go
index 1e7178cc3..796377841 100644
--- a/middleware/bind/setup.go
+++ b/plugin/bind/setup.go
@@ -5,7 +5,7 @@ import (
 	"net"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -14,11 +14,11 @@ func setupBind(c *caddy.Controller) error {
 	config := dnsserver.GetConfig(c)
 	for c.Next() {
 		if !c.Args(&config.ListenHost) {
-			return middleware.Error("bind", c.ArgErr())
+			return plugin.Error("bind", c.ArgErr())
 		}
 	}
 	if net.ParseIP(config.ListenHost) == nil {
-		return middleware.Error("bind", fmt.Errorf("not a valid IP address: %s", config.ListenHost))
+		return plugin.Error("bind", fmt.Errorf("not a valid IP address: %s", config.ListenHost))
 	}
 	return nil
 }
diff --git a/middleware/cache/README.md b/plugin/cache/README.md
similarity index 100%
rename from middleware/cache/README.md
rename to plugin/cache/README.md
diff --git a/middleware/cache/cache.go b/plugin/cache/cache.go
similarity index 93%
rename from middleware/cache/cache.go
rename to plugin/cache/cache.go
index 434efa296..b37e527cf 100644
--- a/middleware/cache/cache.go
+++ b/plugin/cache/cache.go
@@ -7,17 +7,17 @@ import (
 	"log"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/response"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/response"
 
 	"github.com/miekg/dns"
 )
 
-// Cache is middleware that looks up responses in a cache and caches replies.
+// Cache is plugin that looks up responses in a cache and caches replies.
 // It has a success and a denial of existence cache.
 type Cache struct {
-	Next  middleware.Handler
+	Next  plugin.Handler
 	Zones []string
 
 	ncache *cache.Cache
diff --git a/middleware/cache/cache_test.go b/plugin/cache/cache_test.go
similarity index 94%
rename from middleware/cache/cache_test.go
rename to plugin/cache/cache_test.go
index f364e69f1..ad23f4d5a 100644
--- a/middleware/cache/cache_test.go
+++ b/plugin/cache/cache_test.go
@@ -8,10 +8,10 @@ import (
 
 	"golang.org/x/net/context"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/response"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/response"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
@@ -175,7 +175,7 @@ func TestCache(t *testing.T) {
 
 		crr.set(m, k, mt, c.pttl)
 
-		name := middleware.Name(m.Question[0].Name).Normalize()
+		name := plugin.Name(m.Question[0].Name).Normalize()
 		qtype := m.Question[0].Qtype
 
 		i, _ := c.get(time.Now().UTC(), name, qtype, do)
@@ -235,8 +235,8 @@ func BenchmarkCacheResponse(b *testing.B) {
 	})
 }
 
-func BackendHandler() middleware.Handler {
-	return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+func BackendHandler() plugin.Handler {
+	return plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 		m := new(dns.Msg)
 		m.SetReply(r)
 		m.Response = true
diff --git a/middleware/cache/freq/freq.go b/plugin/cache/freq/freq.go
similarity index 100%
rename from middleware/cache/freq/freq.go
rename to plugin/cache/freq/freq.go
diff --git a/middleware/cache/freq/freq_test.go b/plugin/cache/freq/freq_test.go
similarity index 100%
rename from middleware/cache/freq/freq_test.go
rename to plugin/cache/freq/freq_test.go
diff --git a/middleware/cache/handler.go b/plugin/cache/handler.go
similarity index 87%
rename from middleware/cache/handler.go
rename to plugin/cache/handler.go
index 90c63d93a..ebd87d659 100644
--- a/middleware/cache/handler.go
+++ b/plugin/cache/handler.go
@@ -3,7 +3,7 @@ package cache
 import (
 	"time"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -11,13 +11,13 @@ import (
 	"golang.org/x/net/context"
 )
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 
 	qname := state.Name()
 	qtype := state.QType()
-	zone := middleware.Zones(c.Zones).Matches(qname)
+	zone := plugin.Zones(c.Zones).Matches(qname)
 	if zone == "" {
 		return c.Next.ServeDNS(ctx, w, r)
 	}
@@ -46,7 +46,7 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 			// that we've gathered sofar. See we copy the frequencies info back
 			// into the new item that was stored in the cache.
 			prr := &ResponseWriter{ResponseWriter: w, Cache: c, prefetch: true}
-			middleware.NextOrFailure(c.Name(), c.Next, ctx, prr, r)
+			plugin.NextOrFailure(c.Name(), c.Next, ctx, prr, r)
 
 			if i1, _ := c.get(now, qname, qtype, do); i1 != nil {
 				i1.Freq.Reset(now, i.Freq.Hits())
@@ -57,7 +57,7 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 	}
 
 	crr := &ResponseWriter{ResponseWriter: w, Cache: c}
-	return middleware.NextOrFailure(c.Name(), c.Next, ctx, crr, r)
+	return plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r)
 }
 
 // Name implements the Handler interface.
@@ -81,28 +81,28 @@ func (c *Cache) get(now time.Time, qname string, qtype uint16, do bool) (*item,
 
 var (
 	cacheSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "size",
 		Help:      "The number of elements in the cache.",
 	}, []string{"type"})
 
 	cacheCapacity = prometheus.NewGaugeVec(prometheus.GaugeOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "capacity",
 		Help:      "The cache's capacity.",
 	}, []string{"type"})
 
 	cacheHits = prometheus.NewCounterVec(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "hits_total",
 		Help:      "The count of cache hits.",
 	}, []string{"type"})
 
 	cacheMisses = prometheus.NewCounter(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "misses_total",
 		Help:      "The count of cache misses.",
diff --git a/middleware/cache/item.go b/plugin/cache/item.go
similarity index 95%
rename from middleware/cache/item.go
rename to plugin/cache/item.go
index 02571ac5c..2c215617b 100644
--- a/middleware/cache/item.go
+++ b/plugin/cache/item.go
@@ -3,8 +3,8 @@ package cache
 import (
 	"time"
 
-	"github.com/coredns/coredns/middleware/cache/freq"
-	"github.com/coredns/coredns/middleware/pkg/response"
+	"github.com/coredns/coredns/plugin/cache/freq"
+	"github.com/coredns/coredns/plugin/pkg/response"
 	"github.com/miekg/dns"
 )
 
diff --git a/middleware/cache/prefech_test.go b/plugin/cache/prefech_test.go
similarity index 74%
rename from middleware/cache/prefech_test.go
rename to plugin/cache/prefech_test.go
index 69ad5f92a..0e9d84da2 100644
--- a/middleware/cache/prefech_test.go
+++ b/plugin/cache/prefech_test.go
@@ -5,11 +5,11 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
@@ -36,8 +36,8 @@ func TestPrefetch(t *testing.T) {
 	c.ServeDNS(ctx, rec, req)
 }
 
-func PrefetchHandler(t *testing.T, rcode int, err error) middleware.Handler {
-	return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+func PrefetchHandler(t *testing.T, rcode int, err error) plugin.Handler {
+	return plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 		m := new(dns.Msg)
 		m.SetQuestion("lowttl.example.org.", dns.TypeA)
 		m.Response = true
diff --git a/middleware/cache/setup.go b/plugin/cache/setup.go
similarity index 93%
rename from middleware/cache/setup.go
rename to plugin/cache/setup.go
index 65cfb70d1..d8ef9a8d7 100644
--- a/middleware/cache/setup.go
+++ b/plugin/cache/setup.go
@@ -6,8 +6,8 @@ import (
 	"time"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
 
 	"github.com/mholt/caddy"
 )
@@ -22,9 +22,9 @@ func init() {
 func setup(c *caddy.Controller) error {
 	ca, err := cacheParse(c)
 	if err != nil {
-		return middleware.Error("cache", err)
+		return plugin.Error("cache", err)
 	}
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		ca.Next = next
 		return ca
 	})
@@ -155,7 +155,7 @@ func cacheParse(c *caddy.Controller) (*Cache, error) {
 		}
 
 		for i := range origins {
-			origins[i] = middleware.Host(origins[i]).Normalize()
+			origins[i] = plugin.Host(origins[i]).Normalize()
 		}
 
 		ca.Zones = origins
diff --git a/middleware/cache/setup_test.go b/plugin/cache/setup_test.go
similarity index 100%
rename from middleware/cache/setup_test.go
rename to plugin/cache/setup_test.go
diff --git a/middleware/chaos/README.md b/plugin/chaos/README.md
similarity index 82%
rename from middleware/chaos/README.md
rename to plugin/chaos/README.md
index 264ab0601..4c43590e5 100644
--- a/middleware/chaos/README.md
+++ b/plugin/chaos/README.md
@@ -1,6 +1,6 @@
 # chaos
 
-The *chaos* middleware allows CoreDNS to respond to TXT queries in the CH class.
+The *chaos* plugin allows CoreDNS to respond to TXT queries in the CH class.
 
 This is useful for retrieving version or author information from the server.
 
@@ -13,7 +13,7 @@ chaos [VERSION] [AUTHORS...]
 * **VERSION** is the version to return. Defaults to `CoreDNS-<version>`, if not set.
 * **AUTHORS** is what authors to return. No default.
 
-Note that you have to make sure that this middleware will get actual queries for the
+Note that you have to make sure that this plugin will get actual queries for the
 following zones: `version.bind`, `version.server`, `authors.bind`, `hostname.bind` and
 `id.server`.
 
diff --git a/middleware/chaos/chaos.go b/plugin/chaos/chaos.go
similarity index 82%
rename from middleware/chaos/chaos.go
rename to plugin/chaos/chaos.go
index e320a1b7a..c9811fbd0 100644
--- a/middleware/chaos/chaos.go
+++ b/plugin/chaos/chaos.go
@@ -1,10 +1,10 @@
-// Package chaos implements a middleware that answer to 'CH version.bind TXT' type queries.
+// Package chaos implements a plugin that answer to 'CH version.bind TXT' type queries.
 package chaos
 
 import (
 	"os"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -14,16 +14,16 @@ import (
 // Chaos allows CoreDNS to reply to CH TXT queries and return author or
 // version information.
 type Chaos struct {
-	Next    middleware.Handler
+	Next    plugin.Handler
 	Version string
 	Authors map[string]bool
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (c Chaos) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	if state.QClass() != dns.ClassCHAOS || state.QType() != dns.TypeTXT {
-		return middleware.NextOrFailure(c.Name(), c.Next, ctx, w, r)
+		return plugin.NextOrFailure(c.Name(), c.Next, ctx, w, r)
 	}
 
 	m := new(dns.Msg)
diff --git a/middleware/chaos/chaos_test.go b/plugin/chaos/chaos_test.go
similarity index 90%
rename from middleware/chaos/chaos_test.go
rename to plugin/chaos/chaos_test.go
index dd383370b..332d90381 100644
--- a/middleware/chaos/chaos_test.go
+++ b/plugin/chaos/chaos_test.go
@@ -3,9 +3,9 @@ package chaos
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -18,7 +18,7 @@ func TestChaos(t *testing.T) {
 	}
 
 	tests := []struct {
-		next          middleware.Handler
+		next          plugin.Handler
 		qname         string
 		qtype         uint16
 		expectedCode  int
diff --git a/middleware/chaos/setup.go b/plugin/chaos/setup.go
similarity index 85%
rename from middleware/chaos/setup.go
rename to plugin/chaos/setup.go
index 17b4f90cc..2064f4eae 100644
--- a/middleware/chaos/setup.go
+++ b/plugin/chaos/setup.go
@@ -2,7 +2,7 @@ package chaos
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -18,10 +18,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	version, authors, err := chaosParse(c)
 	if err != nil {
-		return middleware.Error("chaos", err)
+		return plugin.Error("chaos", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Chaos{Next: next, Version: version, Authors: authors}
 	})
 
diff --git a/middleware/chaos/setup_test.go b/plugin/chaos/setup_test.go
similarity index 100%
rename from middleware/chaos/setup_test.go
rename to plugin/chaos/setup_test.go
diff --git a/middleware/debug/README.md b/plugin/debug/README.md
similarity index 73%
rename from middleware/debug/README.md
rename to plugin/debug/README.md
index cae6d0ff8..2598a1900 100644
--- a/middleware/debug/README.md
+++ b/plugin/debug/README.md
@@ -2,7 +2,7 @@
 
 *debug* disables the automatic recovery upon a CoreDNS crash so that you'll get a nice stack trace.
 
-Note that the *errors* middleware (if loaded) will also set a `recover` negating this setting.
+Note that the *errors* plugin (if loaded) will also set a `recover` negating this setting.
 The main use of *debug* is to help testing.
 
 ## Syntax
diff --git a/middleware/debug/debug.go b/plugin/debug/debug.go
similarity index 80%
rename from middleware/debug/debug.go
rename to plugin/debug/debug.go
index f92a27554..d69ce0e55 100644
--- a/middleware/debug/debug.go
+++ b/plugin/debug/debug.go
@@ -2,7 +2,7 @@ package debug
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -19,7 +19,7 @@ func setup(c *caddy.Controller) error {
 
 	for c.Next() {
 		if c.NextArg() {
-			return middleware.Error("debug", c.ArgErr())
+			return plugin.Error("debug", c.ArgErr())
 		}
 		config.Debug = true
 	}
diff --git a/middleware/debug/debug_test.go b/plugin/debug/debug_test.go
similarity index 100%
rename from middleware/debug/debug_test.go
rename to plugin/debug/debug_test.go
diff --git a/middleware/dnssec/README.md b/plugin/dnssec/README.md
similarity index 91%
rename from middleware/dnssec/README.md
rename to plugin/dnssec/README.md
index 2422ea640..e087f6c9a 100644
--- a/middleware/dnssec/README.md
+++ b/plugin/dnssec/README.md
@@ -16,7 +16,7 @@ CSK (common signing key), forgoing the ZSK/KSK split. All signing operations are
 Authenticated denial of existence is implemented with NSEC black lies. Using ECDSA as an algorithm
 is preferred as this leads to smaller signatures (compared to RSA). NSEC3 is *not* supported.
 
-If multiple *dnssec* middlewares are specified in the same zone, the last one specified will be
+If multiple *dnssec* plugins are specified in the same zone, the last one specified will be
 used ( see [bugs](#bugs) ).
 
 * `ZONES` zones that should be signed. If empty, the zones from the configuration block
@@ -33,7 +33,7 @@ used ( see [bugs](#bugs) ).
 
     * generated private key `Kexample.org+013+45330.private`
 
-* `cache_capacity` indicates the capacity of the cache. The dnssec middleware uses a cache to store
+* `cache_capacity` indicates the capacity of the cache. The dnssec plugin uses a cache to store
   RRSIGs. The default capacity is 10000.
 
 ## Metrics
@@ -71,7 +71,7 @@ cluster.local:53 {
 
 ## Bugs
 
-Multiple *dnssec* middlewares inside one server stanza will silently overwrite earlier ones, here
+Multiple *dnssec* plugins inside one server stanza will silently overwrite earlier ones, here
 `example.local` will overwrite the one for `cluster.local`.
 
 ~~~
diff --git a/middleware/dnssec/black_lies.go b/plugin/dnssec/black_lies.go
similarity index 100%
rename from middleware/dnssec/black_lies.go
rename to plugin/dnssec/black_lies.go
diff --git a/middleware/dnssec/black_lies_test.go b/plugin/dnssec/black_lies_test.go
similarity index 96%
rename from middleware/dnssec/black_lies_test.go
rename to plugin/dnssec/black_lies_test.go
index 342e7bb3a..80c2ce484 100644
--- a/middleware/dnssec/black_lies_test.go
+++ b/plugin/dnssec/black_lies_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/dnssec/cache.go b/plugin/dnssec/cache.go
similarity index 100%
rename from middleware/dnssec/cache.go
rename to plugin/dnssec/cache.go
diff --git a/middleware/dnssec/cache_test.go b/plugin/dnssec/cache_test.go
similarity index 87%
rename from middleware/dnssec/cache_test.go
rename to plugin/dnssec/cache_test.go
index 7d42a90df..b978df244 100644
--- a/middleware/dnssec/cache_test.go
+++ b/plugin/dnssec/cache_test.go
@@ -4,8 +4,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 )
 
diff --git a/middleware/dnssec/dnskey.go b/plugin/dnssec/dnskey.go
similarity index 100%
rename from middleware/dnssec/dnskey.go
rename to plugin/dnssec/dnskey.go
diff --git a/middleware/dnssec/dnssec.go b/plugin/dnssec/dnssec.go
similarity index 88%
rename from middleware/dnssec/dnssec.go
rename to plugin/dnssec/dnssec.go
index 4e1e70217..84de05c86 100644
--- a/middleware/dnssec/dnssec.go
+++ b/plugin/dnssec/dnssec.go
@@ -1,14 +1,14 @@
-// Package dnssec implements a middleware that signs responses on-the-fly using
+// Package dnssec implements a plugin that signs responses on-the-fly using
 // NSEC black lies.
 package dnssec
 
 import (
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/response"
-	"github.com/coredns/coredns/middleware/pkg/singleflight"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/response"
+	"github.com/coredns/coredns/plugin/pkg/singleflight"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -16,7 +16,7 @@ import (
 
 // Dnssec signs the reply on-the-fly.
 type Dnssec struct {
-	Next middleware.Handler
+	Next plugin.Handler
 
 	zones    []string
 	keys     []*DNSKEY
@@ -25,7 +25,7 @@ type Dnssec struct {
 }
 
 // New returns a new Dnssec.
-func New(zones []string, keys []*DNSKEY, next middleware.Handler, c *cache.Cache) Dnssec {
+func New(zones []string, keys []*DNSKEY, next plugin.Handler, c *cache.Cache) Dnssec {
 	return Dnssec{Next: next,
 		zones:    zones,
 		keys:     keys,
diff --git a/middleware/dnssec/dnssec_test.go b/plugin/dnssec/dnssec_test.go
similarity index 98%
rename from middleware/dnssec/dnssec_test.go
rename to plugin/dnssec/dnssec_test.go
index 3549a7c8f..83ce70beb 100644
--- a/middleware/dnssec/dnssec_test.go
+++ b/plugin/dnssec/dnssec_test.go
@@ -4,8 +4,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/dnssec/handler.go b/plugin/dnssec/handler.go
similarity index 81%
rename from middleware/dnssec/handler.go
rename to plugin/dnssec/handler.go
index dab02e469..6fa2dd042 100644
--- a/middleware/dnssec/handler.go
+++ b/plugin/dnssec/handler.go
@@ -1,7 +1,7 @@
 package dnssec
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -9,16 +9,16 @@ import (
 	"golang.org/x/net/context"
 )
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (d Dnssec) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 
 	do := state.Do()
 	qname := state.Name()
 	qtype := state.QType()
-	zone := middleware.Zones(d.zones).Matches(qname)
+	zone := plugin.Zones(d.zones).Matches(qname)
 	if zone == "" {
-		return middleware.NextOrFailure(d.Name(), d.Next, ctx, w, r)
+		return plugin.NextOrFailure(d.Name(), d.Next, ctx, w, r)
 	}
 
 	// Intercept queries for DNSKEY, but only if one of the zones matches the qname, otherwise we let
@@ -36,33 +36,33 @@ func (d Dnssec) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 	}
 
 	drr := &ResponseWriter{w, d}
-	return middleware.NextOrFailure(d.Name(), d.Next, ctx, drr, r)
+	return plugin.NextOrFailure(d.Name(), d.Next, ctx, drr, r)
 }
 
 var (
 	cacheSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "cache_size",
 		Help:      "The number of elements in the dnssec cache.",
 	}, []string{"type"})
 
 	cacheCapacity = prometheus.NewGaugeVec(prometheus.GaugeOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "cache_capacity",
 		Help:      "The dnssec cache's capacity.",
 	}, []string{"type"})
 
 	cacheHits = prometheus.NewCounter(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "cache_hits_total",
 		Help:      "The count of cache hits.",
 	})
 
 	cacheMisses = prometheus.NewCounter(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "cache_misses_total",
 		Help:      "The count of cache misses.",
diff --git a/middleware/dnssec/handler_test.go b/plugin/dnssec/handler_test.go
similarity index 95%
rename from middleware/dnssec/handler_test.go
rename to plugin/dnssec/handler_test.go
index 19d0ef01f..2202a9ffe 100644
--- a/middleware/dnssec/handler_test.go
+++ b/plugin/dnssec/handler_test.go
@@ -4,10 +4,10 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/file"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/file"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/dnssec/responsewriter.go b/plugin/dnssec/responsewriter.go
similarity index 92%
rename from middleware/dnssec/responsewriter.go
rename to plugin/dnssec/responsewriter.go
index d3c34d114..793cbcdd0 100644
--- a/middleware/dnssec/responsewriter.go
+++ b/plugin/dnssec/responsewriter.go
@@ -4,7 +4,7 @@ import (
 	"log"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -23,7 +23,7 @@ func (d *ResponseWriter) WriteMsg(res *dns.Msg) error {
 	state := request.Request{W: d.ResponseWriter, Req: res}
 
 	qname := state.Name()
-	zone := middleware.Zones(d.d.zones).Matches(qname)
+	zone := plugin.Zones(d.d.zones).Matches(qname)
 	if zone == "" {
 		return d.ResponseWriter.WriteMsg(res)
 	}
diff --git a/middleware/dnssec/rrsig.go b/plugin/dnssec/rrsig.go
similarity index 100%
rename from middleware/dnssec/rrsig.go
rename to plugin/dnssec/rrsig.go
diff --git a/middleware/dnssec/setup.go b/plugin/dnssec/setup.go
similarity index 88%
rename from middleware/dnssec/setup.go
rename to plugin/dnssec/setup.go
index 90425b711..2f5c21d97 100644
--- a/middleware/dnssec/setup.go
+++ b/plugin/dnssec/setup.go
@@ -6,8 +6,8 @@ import (
 	"strings"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/cache"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/cache"
 
 	"github.com/mholt/caddy"
 )
@@ -22,11 +22,11 @@ func init() {
 func setup(c *caddy.Controller) error {
 	zones, keys, capacity, err := dnssecParse(c)
 	if err != nil {
-		return middleware.Error("dnssec", err)
+		return plugin.Error("dnssec", err)
 	}
 
 	ca := cache.New(capacity)
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return New(zones, keys, next, ca)
 	})
 
@@ -74,12 +74,12 @@ func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, int, error) {
 		}
 	}
 	for i := range zones {
-		zones[i] = middleware.Host(zones[i]).Normalize()
+		zones[i] = plugin.Host(zones[i]).Normalize()
 	}
 
 	// Check if each keys owner name can actually sign the zones we want them to sign
 	for _, k := range keys {
-		kname := middleware.Name(k.K.Header().Name)
+		kname := plugin.Name(k.K.Header().Name)
 		ok := false
 		for i := range zones {
 			if kname.Matches(zones[i]) {
diff --git a/middleware/dnssec/setup_test.go b/plugin/dnssec/setup_test.go
similarity index 100%
rename from middleware/dnssec/setup_test.go
rename to plugin/dnssec/setup_test.go
diff --git a/middleware/dnstap/README.md b/plugin/dnstap/README.md
similarity index 100%
rename from middleware/dnstap/README.md
rename to plugin/dnstap/README.md
diff --git a/middleware/dnstap/handler.go b/plugin/dnstap/handler.go
similarity index 78%
rename from middleware/dnstap/handler.go
rename to plugin/dnstap/handler.go
index eb2924be5..b20bb2ad9 100644
--- a/middleware/dnstap/handler.go
+++ b/plugin/dnstap/handler.go
@@ -4,9 +4,9 @@ import (
 	"fmt"
 	"io"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/dnstap/msg"
-	"github.com/coredns/coredns/middleware/dnstap/taprw"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
+	"github.com/coredns/coredns/plugin/dnstap/taprw"
 
 	tap "github.com/dnstap/golang-dnstap"
 	"github.com/miekg/dns"
@@ -15,7 +15,7 @@ import (
 
 // Dnstap is the dnstap handler.
 type Dnstap struct {
-	Next middleware.Handler
+	Next plugin.Handler
 	Out  io.Writer
 	Pack bool
 }
@@ -32,7 +32,7 @@ type (
 	}
 )
 
-// TapperFromContext will return a Tapper if the dnstap middleware is enabled.
+// TapperFromContext will return a Tapper if the dnstap plugin is enabled.
 func TapperFromContext(ctx context.Context) (t Tapper) {
 	t, _ = ctx.(Tapper)
 	return
@@ -62,14 +62,14 @@ func (h Dnstap) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 	rw := &taprw.ResponseWriter{ResponseWriter: w, Tapper: &h, Query: r}
 	rw.QueryEpoch()
 
-	code, err := middleware.NextOrFailure(h.Name(), h.Next, tapContext{ctx, h}, rw, r)
+	code, err := plugin.NextOrFailure(h.Name(), h.Next, tapContext{ctx, h}, rw, r)
 	if err != nil {
 		// ignore dnstap errors
 		return code, err
 	}
 
 	if err := rw.DnstapError(); err != nil {
-		return code, middleware.Error("dnstap", err)
+		return code, plugin.Error("dnstap", err)
 	}
 
 	return code, nil
diff --git a/middleware/dnstap/handler_test.go b/plugin/dnstap/handler_test.go
similarity index 92%
rename from middleware/dnstap/handler_test.go
rename to plugin/dnstap/handler_test.go
index dfdde582d..54509de82 100644
--- a/middleware/dnstap/handler_test.go
+++ b/plugin/dnstap/handler_test.go
@@ -5,8 +5,8 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/dnstap/test"
-	mwtest "github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/dnstap/test"
+	mwtest "github.com/coredns/coredns/plugin/test"
 
 	tap "github.com/dnstap/golang-dnstap"
 	"github.com/golang/protobuf/proto"
diff --git a/middleware/dnstap/msg/msg.go b/plugin/dnstap/msg/msg.go
similarity index 97%
rename from middleware/dnstap/msg/msg.go
rename to plugin/dnstap/msg/msg.go
index 0e2cd5d40..07930929e 100644
--- a/middleware/dnstap/msg/msg.go
+++ b/plugin/dnstap/msg/msg.go
@@ -11,7 +11,7 @@ import (
 	"github.com/miekg/dns"
 )
 
-// Builder helps to build Data by being aware of the dnstap middleware configuration.
+// Builder helps to build Data by being aware of the dnstap plugin configuration.
 type Builder struct {
 	Full bool
 	Data
diff --git a/middleware/dnstap/msg/msg_test.go b/plugin/dnstap/msg/msg_test.go
similarity index 95%
rename from middleware/dnstap/msg/msg_test.go
rename to plugin/dnstap/msg/msg_test.go
index 2f80a90cd..649659a80 100644
--- a/middleware/dnstap/msg/msg_test.go
+++ b/plugin/dnstap/msg/msg_test.go
@@ -5,7 +5,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	tap "github.com/dnstap/golang-dnstap"
diff --git a/middleware/dnstap/msg/wrapper.go b/plugin/dnstap/msg/wrapper.go
similarity index 100%
rename from middleware/dnstap/msg/wrapper.go
rename to plugin/dnstap/msg/wrapper.go
diff --git a/middleware/dnstap/out/socket.go b/plugin/dnstap/out/socket.go
similarity index 100%
rename from middleware/dnstap/out/socket.go
rename to plugin/dnstap/out/socket.go
diff --git a/middleware/dnstap/out/socket_test.go b/plugin/dnstap/out/socket_test.go
similarity index 100%
rename from middleware/dnstap/out/socket_test.go
rename to plugin/dnstap/out/socket_test.go
diff --git a/middleware/dnstap/out/tcp.go b/plugin/dnstap/out/tcp.go
similarity index 100%
rename from middleware/dnstap/out/tcp.go
rename to plugin/dnstap/out/tcp.go
diff --git a/middleware/dnstap/out/tcp_test.go b/plugin/dnstap/out/tcp_test.go
similarity index 100%
rename from middleware/dnstap/out/tcp_test.go
rename to plugin/dnstap/out/tcp_test.go
diff --git a/middleware/dnstap/setup.go b/plugin/dnstap/setup.go
similarity index 84%
rename from middleware/dnstap/setup.go
rename to plugin/dnstap/setup.go
index 63a3eb099..a57873470 100644
--- a/middleware/dnstap/setup.go
+++ b/plugin/dnstap/setup.go
@@ -7,9 +7,9 @@ import (
 	"strings"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/dnstap/out"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/dnstap/out"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 
 	"github.com/mholt/caddy"
 	"github.com/mholt/caddy/caddyfile"
@@ -24,7 +24,7 @@ func init() {
 
 func wrapSetup(c *caddy.Controller) error {
 	if err := setup(c); err != nil {
-		return middleware.Error("dnstap", err)
+		return plugin.Error("dnstap", err)
 	}
 	return nil
 }
@@ -88,8 +88,8 @@ func setup(c *caddy.Controller) error {
 		return nil
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(
-		func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(
+		func(next plugin.Handler) plugin.Handler {
 			dnstap.Next = next
 			return dnstap
 		})
diff --git a/middleware/dnstap/setup_test.go b/plugin/dnstap/setup_test.go
similarity index 100%
rename from middleware/dnstap/setup_test.go
rename to plugin/dnstap/setup_test.go
diff --git a/middleware/dnstap/taprw/writer.go b/plugin/dnstap/taprw/writer.go
similarity index 97%
rename from middleware/dnstap/taprw/writer.go
rename to plugin/dnstap/taprw/writer.go
index 99572afd9..ae9965411 100644
--- a/middleware/dnstap/taprw/writer.go
+++ b/plugin/dnstap/taprw/writer.go
@@ -5,7 +5,7 @@ package taprw
 import (
 	"fmt"
 
-	"github.com/coredns/coredns/middleware/dnstap/msg"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
 
 	tap "github.com/dnstap/golang-dnstap"
 	"github.com/miekg/dns"
diff --git a/middleware/dnstap/taprw/writer_test.go b/plugin/dnstap/taprw/writer_test.go
similarity index 90%
rename from middleware/dnstap/taprw/writer_test.go
rename to plugin/dnstap/taprw/writer_test.go
index 426f1f580..6969dc515 100644
--- a/middleware/dnstap/taprw/writer_test.go
+++ b/plugin/dnstap/taprw/writer_test.go
@@ -4,9 +4,9 @@ import (
 	"errors"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/dnstap/msg"
-	"github.com/coredns/coredns/middleware/dnstap/test"
-	mwtest "github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
+	"github.com/coredns/coredns/plugin/dnstap/test"
+	mwtest "github.com/coredns/coredns/plugin/test"
 
 	tap "github.com/dnstap/golang-dnstap"
 	"github.com/miekg/dns"
diff --git a/middleware/dnstap/test/helpers.go b/plugin/dnstap/test/helpers.go
similarity index 96%
rename from middleware/dnstap/test/helpers.go
rename to plugin/dnstap/test/helpers.go
index 46ba327ab..8c5809725 100644
--- a/middleware/dnstap/test/helpers.go
+++ b/plugin/dnstap/test/helpers.go
@@ -4,7 +4,7 @@ import (
 	"net"
 	"reflect"
 
-	"github.com/coredns/coredns/middleware/dnstap/msg"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
 
 	tap "github.com/dnstap/golang-dnstap"
 	"golang.org/x/net/context"
diff --git a/middleware/erratic/README.md b/plugin/erratic/README.md
similarity index 78%
rename from middleware/erratic/README.md
rename to plugin/erratic/README.md
index a84146fbb..a41faaca9 100644
--- a/middleware/erratic/README.md
+++ b/plugin/erratic/README.md
@@ -1,13 +1,13 @@
 # erratic
 
-*erratic* is a middleware useful for testing client behavior. It returns a static response to all
+*erratic* is a plugin useful for testing client behavior. It returns a static response to all
 queries, but the responses can be delayed, dropped or truncated.
 
-The *erratic* middleware will respond to every A or AAAA query. For any other type it will return
+The *erratic* plugin will respond to every A or AAAA query. For any other type it will return
 a SERVFAIL response. The reply for A will return 192.0.2.53 (see RFC 5737), for AAAA it returns
 2001:DB8::53 (see RFC 3849).
 
-*erratic* can also be used in conjunction with the *autopath* middleware. This is mostly to aid in
+*erratic* can also be used in conjunction with the *autopath* plugin. This is mostly to aid in
  testing.
 
 ## Syntax
diff --git a/middleware/erratic/autopath.go b/plugin/erratic/autopath.go
similarity index 70%
rename from middleware/erratic/autopath.go
rename to plugin/erratic/autopath.go
index 79b0ec847..0e29fffe5 100644
--- a/middleware/erratic/autopath.go
+++ b/plugin/erratic/autopath.go
@@ -2,7 +2,7 @@ package erratic
 
 import "github.com/coredns/coredns/request"
 
-// AutoPath implements the AutoPathFunc call from the autopath middleware.
+// AutoPath implements the AutoPathFunc call from the autopath plugin.
 func (e *Erratic) AutoPath(state request.Request) []string {
 	return []string{"a.example.org.", "b.example.org.", ""}
 }
diff --git a/middleware/erratic/erratic.go b/plugin/erratic/erratic.go
similarity index 88%
rename from middleware/erratic/erratic.go
rename to plugin/erratic/erratic.go
index b05e45f03..5b8cd30c9 100644
--- a/middleware/erratic/erratic.go
+++ b/plugin/erratic/erratic.go
@@ -1,4 +1,4 @@
-// Package erratic implements a middleware that returns erratic answers (delayed, dropped).
+// Package erratic implements a plugin that returns erratic answers (delayed, dropped).
 package erratic
 
 import (
@@ -11,7 +11,7 @@ import (
 	"golang.org/x/net/context"
 )
 
-// Erratic is a middleware that returns erratic repsonses to each client.
+// Erratic is a plugin that returns erratic repsonses to each client.
 type Erratic struct {
 	drop uint64
 
@@ -23,7 +23,7 @@ type Erratic struct {
 	q uint64 // counter of queries
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (e *Erratic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	drop := false
diff --git a/middleware/erratic/erratic_test.go b/plugin/erratic/erratic_test.go
similarity index 94%
rename from middleware/erratic/erratic_test.go
rename to plugin/erratic/erratic_test.go
index 4b54e0c12..7a1a420da 100644
--- a/middleware/erratic/erratic_test.go
+++ b/plugin/erratic/erratic_test.go
@@ -3,8 +3,8 @@ package erratic
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/erratic/setup.go b/plugin/erratic/setup.go
similarity index 92%
rename from middleware/erratic/setup.go
rename to plugin/erratic/setup.go
index 98db02247..b0a56927d 100644
--- a/middleware/erratic/setup.go
+++ b/plugin/erratic/setup.go
@@ -6,7 +6,7 @@ import (
 	"time"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -21,10 +21,10 @@ func init() {
 func setupErratic(c *caddy.Controller) error {
 	e, err := parseErratic(c)
 	if err != nil {
-		return middleware.Error("erratic", err)
+		return plugin.Error("erratic", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return e
 	})
 
diff --git a/middleware/erratic/setup_test.go b/plugin/erratic/setup_test.go
similarity index 100%
rename from middleware/erratic/setup_test.go
rename to plugin/erratic/setup_test.go
diff --git a/middleware/errors/README.md b/plugin/errors/README.md
similarity index 100%
rename from middleware/errors/README.md
rename to plugin/errors/README.md
diff --git a/middleware/errors/errors.go b/plugin/errors/errors.go
similarity index 83%
rename from middleware/errors/errors.go
rename to plugin/errors/errors.go
index 9b0bfa946..a313f2e0d 100644
--- a/middleware/errors/errors.go
+++ b/plugin/errors/errors.go
@@ -1,4 +1,4 @@
-// Package errors implements an HTTP error handling middleware.
+// Package errors implements an HTTP error handling plugin.
 package errors
 
 import (
@@ -8,25 +8,25 @@ import (
 	"strings"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
 
-// errorHandler handles DNS errors (and errors from other middleware).
+// errorHandler handles DNS errors (and errors from other plugin).
 type errorHandler struct {
-	Next    middleware.Handler
+	Next    plugin.Handler
 	LogFile string
 	Log     *log.Logger
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (h errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	defer h.recovery(ctx, w, r)
 
-	rcode, err := middleware.NextOrFailure(h.Name(), h.Next, ctx, w, r)
+	rcode, err := plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 
 	if err != nil {
 		state := request.Request{W: w, Req: r}
diff --git a/middleware/errors/errors_test.go b/plugin/errors/errors_test.go
similarity index 80%
rename from middleware/errors/errors_test.go
rename to plugin/errors/errors_test.go
index 5e565964c..039562a56 100644
--- a/middleware/errors/errors_test.go
+++ b/plugin/errors/errors_test.go
@@ -8,9 +8,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -22,7 +22,7 @@ func TestErrors(t *testing.T) {
 
 	testErr := errors.New("test error")
 	tests := []struct {
-		next         middleware.Handler
+		next         plugin.Handler
 		expectedCode int
 		expectedLog  string
 		expectedErr  error
@@ -66,8 +66,8 @@ func TestErrors(t *testing.T) {
 	}
 }
 
-func genErrorHandler(rcode int, err error) middleware.Handler {
-	return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+func genErrorHandler(rcode int, err error) plugin.Handler {
+	return plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 		return rcode, err
 	})
 }
diff --git a/middleware/errors/setup.go b/plugin/errors/setup.go
similarity index 82%
rename from middleware/errors/setup.go
rename to plugin/errors/setup.go
index af9a7bbff..19bdcdb80 100644
--- a/middleware/errors/setup.go
+++ b/plugin/errors/setup.go
@@ -6,7 +6,7 @@ import (
 	"os"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -21,12 +21,12 @@ func init() {
 func setup(c *caddy.Controller) error {
 	handler, err := errorsParse(c)
 	if err != nil {
-		return middleware.Error("errors", err)
+		return plugin.Error("errors", err)
 	}
 
 	handler.Log = log.New(os.Stdout, "", 0)
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		handler.Next = next
 		return handler
 	})
diff --git a/middleware/errors/setup_test.go b/plugin/errors/setup_test.go
similarity index 100%
rename from middleware/errors/setup_test.go
rename to plugin/errors/setup_test.go
diff --git a/middleware/etcd/README.md b/plugin/etcd/README.md
similarity index 92%
rename from middleware/etcd/README.md
rename to plugin/etcd/README.md
index f7991eb7c..f65c193f1 100644
--- a/middleware/etcd/README.md
+++ b/plugin/etcd/README.md
@@ -4,7 +4,7 @@
 a [message](https://github.com/skynetservices/skydns/blob/2fcff74cdc9f9a7dd64189a447ef27ac354b725f/msg/service.go#L26)
 like [SkyDNS](https://github.com/skynetservices/skydns). It should also work just like SkyDNS.
 
-The etcd middleware makes extensive use of the proxy middleware to forward and query other servers
+The etcd plugin makes extensive use of the proxy plugin to forward and query other servers
 in the network.
 
 ## Syntax
@@ -18,7 +18,7 @@ etcd [ZONES...]
 The path will default to `/skydns` the local etcd proxy (http://localhost:2379).
 If no zones are specified the block's zone will be used as the zone.
 
-If you want to `round robin` A and AAAA responses look at the `loadbalance` middleware.
+If you want to `round robin` A and AAAA responses look at the `loadbalance` plugin.
 
 ~~~
 etcd [ZONES...] {
@@ -33,12 +33,12 @@ etcd [ZONES...] {
 
 * `stubzones` enables the stub zones feature. The stubzone is *only* done in the etcd tree located
     under the *first* zone specified.
-* `fallthrough` If zone matches but no record can be generated, pass request to the next middleware.
+* `fallthrough` If zone matches but no record can be generated, pass request to the next plugin.
 * **PATH** the path inside etcd. Defaults to "/skydns".
 * **ENDPOINT** the etcd endpoints. Defaults to "http://localhost:2397".
 * `upstream` upstream resolvers to be used resolve external names found in etcd (think CNAMEs)
   pointing to external names. If you want CoreDNS to act as a proxy for clients, you'll need to add
-  the proxy middleware. **ADDRESS** can be an IP address, and IP:port or a string pointing to a file
+  the proxy plugin. **ADDRESS** can be an IP address, and IP:port or a string pointing to a file
   that is structured as /etc/resolv.conf.
 * `tls` followed by:
   * no arguments, if the server certificate is signed by a system-installed CA and no client cert is needed
diff --git a/middleware/etcd/cname_test.go b/plugin/etcd/cname_test.go
similarity index 93%
rename from middleware/etcd/cname_test.go
rename to plugin/etcd/cname_test.go
index 4c39491fd..33291094b 100644
--- a/middleware/etcd/cname_test.go
+++ b/plugin/etcd/cname_test.go
@@ -7,9 +7,9 @@ package etcd
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/etcd/etcd.go b/plugin/etcd/etcd.go
similarity index 87%
rename from middleware/etcd/etcd.go
rename to plugin/etcd/etcd.go
index 5ef6e0a47..862be065b 100644
--- a/middleware/etcd/etcd.go
+++ b/plugin/etcd/etcd.go
@@ -1,4 +1,4 @@
-// Package etcd provides the etcd backend middleware.
+// Package etcd provides the etcd backend plugin.
 package etcd
 
 import (
@@ -7,11 +7,11 @@ import (
 	"strings"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/cache"
-	"github.com/coredns/coredns/middleware/pkg/singleflight"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/cache"
+	"github.com/coredns/coredns/plugin/pkg/singleflight"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/coredns/coredns/request"
 
 	etcdc "github.com/coreos/etcd/client"
@@ -19,9 +19,9 @@ import (
 	"golang.org/x/net/context"
 )
 
-// Etcd is a middleware talks to an etcd cluster.
+// Etcd is a plugin talks to an etcd cluster.
 type Etcd struct {
-	Next        middleware.Handler
+	Next        plugin.Handler
 	Fallthrough bool
 	Zones       []string
 	PathPrefix  string
@@ -35,7 +35,7 @@ type Etcd struct {
 }
 
 // Services implements the ServiceBackend interface.
-func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Options) (services []msg.Service, err error) {
+func (e *Etcd) Services(state request.Request, exact bool, opt plugin.Options) (services []msg.Service, err error) {
 	services, err = e.Records(state, exact)
 	if err != nil {
 		return
@@ -46,7 +46,7 @@ func (e *Etcd) Services(state request.Request, exact bool, opt middleware.Option
 }
 
 // Reverse implements the ServiceBackend interface.
-func (e *Etcd) Reverse(state request.Request, exact bool, opt middleware.Options) (services []msg.Service, err error) {
+func (e *Etcd) Reverse(state request.Request, exact bool, opt plugin.Options) (services []msg.Service, err error) {
 	return e.Services(state, exact, opt)
 }
 
diff --git a/middleware/etcd/group_test.go b/plugin/etcd/group_test.go
similarity index 91%
rename from middleware/etcd/group_test.go
rename to plugin/etcd/group_test.go
index 43ce4754a..d7f6172c7 100644
--- a/middleware/etcd/group_test.go
+++ b/plugin/etcd/group_test.go
@@ -5,9 +5,9 @@ package etcd
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/etcd/handler.go b/plugin/etcd/handler.go
similarity index 56%
rename from middleware/etcd/handler.go
rename to plugin/etcd/handler.go
index 7857b1955..49f15343d 100644
--- a/middleware/etcd/handler.go
+++ b/plugin/etcd/handler.go
@@ -1,17 +1,17 @@
 package etcd
 
 import (
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
-	opt := middleware.Options{}
+	opt := plugin.Options{}
 	state := request.Request{W: w, Req: r}
 
 	name := state.Name()
@@ -21,16 +21,16 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
 	// handler will handle the request.
 	if e.Stubmap != nil && len(*e.Stubmap) > 0 {
 		for zone := range *e.Stubmap {
-			if middleware.Name(zone).Matches(name) {
+			if plugin.Name(zone).Matches(name) {
 				stub := Stub{Etcd: e, Zone: zone}
 				return stub.ServeDNS(ctx, w, r)
 			}
 		}
 	}
 
-	zone := middleware.Zones(e.Zones).Matches(state.Name())
+	zone := plugin.Zones(e.Zones).Matches(state.Name())
 	if zone == "" {
-		return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
+		return plugin.NextOrFailure(e.Name(), e.Next, ctx, w, r)
 	}
 
 	var (
@@ -39,45 +39,45 @@ func (e *Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
 	)
 	switch state.Type() {
 	case "A":
-		records, err = middleware.A(e, zone, state, nil, opt)
+		records, err = plugin.A(e, zone, state, nil, opt)
 	case "AAAA":
-		records, err = middleware.AAAA(e, zone, state, nil, opt)
+		records, err = plugin.AAAA(e, zone, state, nil, opt)
 	case "TXT":
-		records, err = middleware.TXT(e, zone, state, opt)
+		records, err = plugin.TXT(e, zone, state, opt)
 	case "CNAME":
-		records, err = middleware.CNAME(e, zone, state, opt)
+		records, err = plugin.CNAME(e, zone, state, opt)
 	case "PTR":
-		records, err = middleware.PTR(e, zone, state, opt)
+		records, err = plugin.PTR(e, zone, state, opt)
 	case "MX":
-		records, extra, err = middleware.MX(e, zone, state, opt)
+		records, extra, err = plugin.MX(e, zone, state, opt)
 	case "SRV":
-		records, extra, err = middleware.SRV(e, zone, state, opt)
+		records, extra, err = plugin.SRV(e, zone, state, opt)
 	case "SOA":
-		records, err = middleware.SOA(e, zone, state, opt)
+		records, err = plugin.SOA(e, zone, state, opt)
 	case "NS":
 		if state.Name() == zone {
-			records, extra, err = middleware.NS(e, zone, state, opt)
+			records, extra, err = plugin.NS(e, zone, state, opt)
 			break
 		}
 		fallthrough
 	default:
 		// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
-		_, err = middleware.A(e, zone, state, nil, opt)
+		_, err = plugin.A(e, zone, state, nil, opt)
 	}
 
 	if e.IsNameError(err) {
 		if e.Fallthrough {
-			return middleware.NextOrFailure(e.Name(), e.Next, ctx, w, r)
+			return plugin.NextOrFailure(e.Name(), e.Next, ctx, w, r)
 		}
 		// Make err nil when returning here, so we don't log spam for NXDOMAIN.
-		return middleware.BackendError(e, zone, dns.RcodeNameError, state, nil /* err */, opt)
+		return plugin.BackendError(e, zone, dns.RcodeNameError, state, nil /* err */, opt)
 	}
 	if err != nil {
-		return middleware.BackendError(e, zone, dns.RcodeServerFailure, state, err, opt)
+		return plugin.BackendError(e, zone, dns.RcodeServerFailure, state, err, opt)
 	}
 
 	if len(records) == 0 {
-		return middleware.BackendError(e, zone, dns.RcodeSuccess, state, err, opt)
+		return plugin.BackendError(e, zone, dns.RcodeSuccess, state, err, opt)
 	}
 
 	m := new(dns.Msg)
diff --git a/middleware/etcd/lookup_test.go b/plugin/etcd/lookup_test.go
similarity index 96%
rename from middleware/etcd/lookup_test.go
rename to plugin/etcd/lookup_test.go
index 010bd66df..1f52d5993 100644
--- a/middleware/etcd/lookup_test.go
+++ b/plugin/etcd/lookup_test.go
@@ -8,12 +8,12 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/pkg/singleflight"
-	"github.com/coredns/coredns/middleware/pkg/tls"
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/pkg/singleflight"
+	"github.com/coredns/coredns/plugin/pkg/tls"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 
 	etcdc "github.com/coreos/etcd/client"
 	"github.com/miekg/dns"
diff --git a/middleware/etcd/msg/path.go b/plugin/etcd/msg/path.go
similarity index 96%
rename from middleware/etcd/msg/path.go
rename to plugin/etcd/msg/path.go
index 2184b9fcd..2abdec0fe 100644
--- a/middleware/etcd/msg/path.go
+++ b/plugin/etcd/msg/path.go
@@ -4,7 +4,7 @@ import (
 	"path"
 	"strings"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/etcd/msg/path_test.go b/plugin/etcd/msg/path_test.go
similarity index 100%
rename from middleware/etcd/msg/path_test.go
rename to plugin/etcd/msg/path_test.go
diff --git a/middleware/etcd/msg/service.go b/plugin/etcd/msg/service.go
similarity index 100%
rename from middleware/etcd/msg/service.go
rename to plugin/etcd/msg/service.go
diff --git a/middleware/etcd/msg/service_test.go b/plugin/etcd/msg/service_test.go
similarity index 100%
rename from middleware/etcd/msg/service_test.go
rename to plugin/etcd/msg/service_test.go
diff --git a/middleware/etcd/msg/type.go b/plugin/etcd/msg/type.go
similarity index 100%
rename from middleware/etcd/msg/type.go
rename to plugin/etcd/msg/type.go
diff --git a/middleware/etcd/msg/type_test.go b/plugin/etcd/msg/type_test.go
similarity index 100%
rename from middleware/etcd/msg/type_test.go
rename to plugin/etcd/msg/type_test.go
diff --git a/middleware/etcd/multi_test.go b/plugin/etcd/multi_test.go
similarity index 90%
rename from middleware/etcd/multi_test.go
rename to plugin/etcd/multi_test.go
index 301b2c49e..56b5af265 100644
--- a/middleware/etcd/multi_test.go
+++ b/plugin/etcd/multi_test.go
@@ -5,9 +5,9 @@ package etcd
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/etcd/other_test.go b/plugin/etcd/other_test.go
similarity index 96%
rename from middleware/etcd/other_test.go
rename to plugin/etcd/other_test.go
index b3849b9f7..d28c33537 100644
--- a/middleware/etcd/other_test.go
+++ b/plugin/etcd/other_test.go
@@ -9,9 +9,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/etcd/setup.go b/plugin/etcd/setup.go
similarity index 86%
rename from middleware/etcd/setup.go
rename to plugin/etcd/setup.go
index 7cbcfd2ea..415feb2ef 100644
--- a/middleware/etcd/setup.go
+++ b/plugin/etcd/setup.go
@@ -4,11 +4,11 @@ import (
 	"crypto/tls"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/pkg/singleflight"
-	mwtls "github.com/coredns/coredns/middleware/pkg/tls"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/singleflight"
+	mwtls "github.com/coredns/coredns/plugin/pkg/tls"
+	"github.com/coredns/coredns/plugin/proxy"
 
 	etcdc "github.com/coreos/etcd/client"
 	"github.com/mholt/caddy"
@@ -25,7 +25,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	e, stubzones, err := etcdParse(c)
 	if err != nil {
-		return middleware.Error("etcd", err)
+		return plugin.Error("etcd", err)
 	}
 
 	if stubzones {
@@ -35,7 +35,7 @@ func setup(c *caddy.Controller) error {
 		})
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		e.Next = next
 		return e
 	})
@@ -66,7 +66,7 @@ func etcdParse(c *caddy.Controller) (*Etcd, bool, error) {
 			copy(etc.Zones, c.ServerBlockKeys)
 		}
 		for i, str := range etc.Zones {
-			etc.Zones[i] = middleware.Host(str).Normalize()
+			etc.Zones[i] = plugin.Host(str).Normalize()
 		}
 
 		if c.NextBlock() {
diff --git a/middleware/etcd/setup_test.go b/plugin/etcd/setup_test.go
similarity index 100%
rename from middleware/etcd/setup_test.go
rename to plugin/etcd/setup_test.go
diff --git a/middleware/etcd/stub.go b/plugin/etcd/stub.go
similarity index 93%
rename from middleware/etcd/stub.go
rename to plugin/etcd/stub.go
index b40af6341..d7b9d5036 100644
--- a/middleware/etcd/stub.go
+++ b/plugin/etcd/stub.go
@@ -6,9 +6,9 @@ import (
 	"strconv"
 	"time"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/etcd/stub_handler.go b/plugin/etcd/stub_handler.go
similarity index 97%
rename from middleware/etcd/stub_handler.go
rename to plugin/etcd/stub_handler.go
index a6b752177..6f4a49950 100644
--- a/middleware/etcd/stub_handler.go
+++ b/plugin/etcd/stub_handler.go
@@ -16,7 +16,7 @@ type Stub struct {
 	Zone string // for what zone (and thus what nameservers are we called)
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (s Stub) ServeDNS(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) (int, error) {
 	if hasStubEdns0(req) {
 		log.Printf("[WARNING] Forwarding cycle detected, refusing msg: %s", req.Question[0].Name)
diff --git a/middleware/etcd/stub_test.go b/plugin/etcd/stub_test.go
similarity index 93%
rename from middleware/etcd/stub_test.go
rename to plugin/etcd/stub_test.go
index 5f22f42c9..56fd481b7 100644
--- a/middleware/etcd/stub_test.go
+++ b/plugin/etcd/stub_test.go
@@ -7,9 +7,9 @@ import (
 	"strconv"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/federation/README.md b/plugin/federation/README.md
similarity index 91%
rename from middleware/federation/README.md
rename to plugin/federation/README.md
index c22a909f5..fb3d44e8c 100644
--- a/middleware/federation/README.md
+++ b/plugin/federation/README.md
@@ -1,8 +1,8 @@
 # federation
 
-The *federation* middleware enables
+The *federation* plugin enables
 [federated](https://kubernetes.io/docs/tasks/federation/federation-service-discovery/) queries to be
-resolved via the kubernetes middleware.
+resolved via the kubernetes plugin.
 
 Enabling *federation* without also having *kubernetes* is a noop.
 
diff --git a/middleware/federation/federation.go b/plugin/federation/federation.go
similarity index 77%
rename from middleware/federation/federation.go
rename to plugin/federation/federation.go
index bc74d9fc9..c94e8f819 100644
--- a/middleware/federation/federation.go
+++ b/plugin/federation/federation.go
@@ -9,15 +9,15 @@ the federation label. For federation to work we do a normal k8s lookup
 *without* that label, if that comes back with NXDOMAIN or NODATA(??) we create
 a federation record and return that.
 
-Federation is only useful in conjunction with the kubernetes middleware, without it is a noop.
+Federation is only useful in conjunction with the kubernetes plugin, without it is a noop.
 */
 package federation
 
 import (
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/pkg/nonwriter"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/nonwriter"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -29,12 +29,12 @@ type Federation struct {
 	f     map[string]string
 	zones []string
 
-	Next        middleware.Handler
+	Next        plugin.Handler
 	Federations Func
 }
 
-// Func needs to be implemented by any middleware that implements
-// federation. Right now this is only the kubernetes middleware.
+// Func needs to be implemented by any plugin that implements
+// federation. Right now this is only the kubernetes plugin.
 type Func func(state request.Request, fname, fzone string) (msg.Service, error)
 
 // New returns a new federation.
@@ -42,16 +42,16 @@ func New() *Federation {
 	return &Federation{f: make(map[string]string)}
 }
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (f *Federation) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	if f.Federations == nil {
-		return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r)
+		return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
 	}
 
 	state := request.Request{W: w, Req: r}
-	zone := middleware.Zones(f.zones).Matches(state.Name())
+	zone := plugin.Zones(f.zones).Matches(state.Name())
 	if zone == "" {
-		return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r)
+		return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
 	}
 
 	state.Zone = zone
@@ -59,19 +59,19 @@ func (f *Federation) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.
 	// Remove the federation label from the qname to see if something exists.
 	without, label := f.isNameFederation(state.Name(), state.Zone)
 	if without == "" {
-		return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r)
+		return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
 	}
 
 	qname := r.Question[0].Name
 	r.Question[0].Name = without
 	state.Clear()
 
-	// Start the next middleware, but with a nowriter, capture the result, if NXDOMAIN
+	// Start the next plugin, but with a nowriter, capture the result, if NXDOMAIN
 	// perform federation, otherwise just write the result.
 	nw := nonwriter.New(w)
-	ret, err := middleware.NextOrFailure(f.Name(), f.Next, ctx, nw, r)
+	ret, err := plugin.NextOrFailure(f.Name(), f.Next, ctx, nw, r)
 
-	if !middleware.ClientWrite(ret) {
+	if !plugin.ClientWrite(ret) {
 		// something went wrong
 		r.Question[0].Name = qname
 		return ret, err
@@ -113,7 +113,7 @@ func (f *Federation) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.
 	return dns.RcodeSuccess, nil
 }
 
-// Name implements the middleware.Handle interface.
+// Name implements the plugin.Handle interface.
 func (f *Federation) Name() string { return "federation" }
 
 // IsNameFederation checks the qname to see if it is a potential federation. The federation
diff --git a/middleware/federation/federation_test.go b/plugin/federation/federation_test.go
similarity index 92%
rename from middleware/federation/federation_test.go
rename to plugin/federation/federation_test.go
index 6f27cabad..920f1a340 100644
--- a/middleware/federation/federation_test.go
+++ b/plugin/federation/federation_test.go
@@ -3,9 +3,9 @@ package federation
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/kubernetes"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/kubernetes"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/federation/kubernetes_api_test.go b/plugin/federation/kubernetes_api_test.go
similarity index 97%
rename from middleware/federation/kubernetes_api_test.go
rename to plugin/federation/kubernetes_api_test.go
index 9e7056e49..48a03666e 100644
--- a/middleware/federation/kubernetes_api_test.go
+++ b/plugin/federation/kubernetes_api_test.go
@@ -1,7 +1,7 @@
 package federation
 
 import (
-	"github.com/coredns/coredns/middleware/kubernetes"
+	"github.com/coredns/coredns/plugin/kubernetes"
 
 	"k8s.io/client-go/1.5/pkg/api"
 )
diff --git a/middleware/federation/setup.go b/plugin/federation/setup.go
similarity index 80%
rename from middleware/federation/setup.go
rename to plugin/federation/setup.go
index 1ef635603..72514fe8f 100644
--- a/middleware/federation/setup.go
+++ b/plugin/federation/setup.go
@@ -4,8 +4,8 @@ import (
 	"fmt"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/kubernetes"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/kubernetes"
 	"github.com/miekg/dns"
 
 	"github.com/mholt/caddy"
@@ -21,10 +21,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	fed, err := federationParse(c)
 	if err != nil {
-		return middleware.Error("federation", err)
+		return plugin.Error("federation", err)
 	}
 
-	// Do this in OnStartup, so all middleware has been initialized.
+	// Do this in OnStartup, so all plugin has been initialized.
 	c.OnStartup(func() error {
 		m := dnsserver.GetConfig(c).Handler("kubernetes")
 		if m == nil {
@@ -36,7 +36,7 @@ func setup(c *caddy.Controller) error {
 		return nil
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		fed.Next = next
 		return fed
 	})
@@ -73,7 +73,7 @@ func federationParse(c *caddy.Controller) (*Federation, error) {
 		}
 
 		for i := range origins {
-			origins[i] = middleware.Host(origins[i]).Normalize()
+			origins[i] = plugin.Host(origins[i]).Normalize()
 		}
 
 		fed.zones = origins
diff --git a/middleware/federation/setup_test.go b/plugin/federation/setup_test.go
similarity index 100%
rename from middleware/federation/setup_test.go
rename to plugin/federation/setup_test.go
diff --git a/middleware/file/README.md b/plugin/file/README.md
similarity index 94%
rename from middleware/file/README.md
rename to plugin/file/README.md
index 29656d161..d7e1590b4 100644
--- a/middleware/file/README.md
+++ b/plugin/file/README.md
@@ -2,7 +2,7 @@
 
 *file* enables serving zone data from an RFC 1035-style master file.
 
-The file middleware is used for an "old-style" DNS server. It serves from a preloaded file that exists
+The file plugin is used for an "old-style" DNS server. It serves from a preloaded file that exists
 on disk. If the zone file contains signatures (i.e. is signed, i.e. DNSSEC) correct DNSSEC answers
 are returned. Only NSEC is supported! If you use this setup *you* are responsible for resigning the
 zonefile.
@@ -18,7 +18,7 @@ file DBFILE [ZONES...]
 * **ZONES** zones it should be authoritative for. If empty, the zones from the configuration block
     are used.
 
-If you want to round robin A and AAAA responses look at the *loadbalance* middleware.
+If you want to round robin A and AAAA responses look at the *loadbalance* plugin.
 
 TSIG key configuration is TODO; directive format for transfer will probably be extended with
 TSIG key information, something like `transfer out [ADDRESS...] key [NAME[:ALG]] [BASE64]`
diff --git a/middleware/file/closest.go b/plugin/file/closest.go
similarity index 89%
rename from middleware/file/closest.go
rename to plugin/file/closest.go
index ea201671f..64652af83 100644
--- a/middleware/file/closest.go
+++ b/plugin/file/closest.go
@@ -1,7 +1,7 @@
 package file
 
 import (
-	"github.com/coredns/coredns/middleware/file/tree"
+	"github.com/coredns/coredns/plugin/file/tree"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/file/closest_test.go b/plugin/file/closest_test.go
similarity index 100%
rename from middleware/file/closest_test.go
rename to plugin/file/closest_test.go
diff --git a/middleware/file/cname_test.go b/plugin/file/cname_test.go
similarity index 95%
rename from middleware/file/cname_test.go
rename to plugin/file/cname_test.go
index 90e6f05a9..1178a7512 100644
--- a/middleware/file/cname_test.go
+++ b/plugin/file/cname_test.go
@@ -4,9 +4,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/delegation_test.go b/plugin/file/delegation_test.go
similarity index 98%
rename from middleware/file/delegation_test.go
rename to plugin/file/delegation_test.go
index 49510944f..1ad9804f4 100644
--- a/middleware/file/delegation_test.go
+++ b/plugin/file/delegation_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/dname.go b/plugin/file/dname.go
similarity index 95%
rename from middleware/file/dname.go
rename to plugin/file/dname.go
index 6bbfd9377..f552bfdfd 100644
--- a/middleware/file/dname.go
+++ b/plugin/file/dname.go
@@ -1,7 +1,7 @@
 package file
 
 import (
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/file/dname_test.go b/plugin/file/dname_test.go
similarity index 98%
rename from middleware/file/dname_test.go
rename to plugin/file/dname_test.go
index 27890a78c..92e33dde7 100644
--- a/middleware/file/dname_test.go
+++ b/plugin/file/dname_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/dnssec_test.go b/plugin/file/dnssec_test.go
similarity index 99%
rename from middleware/file/dnssec_test.go
rename to plugin/file/dnssec_test.go
index 136a9dfee..17b122c7e 100644
--- a/middleware/file/dnssec_test.go
+++ b/plugin/file/dnssec_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/dnssex_test.go b/plugin/file/dnssex_test.go
similarity index 100%
rename from middleware/file/dnssex_test.go
rename to plugin/file/dnssex_test.go
diff --git a/middleware/file/ds_test.go b/plugin/file/ds_test.go
similarity index 95%
rename from middleware/file/ds_test.go
rename to plugin/file/ds_test.go
index f5c9bb332..e1087a81d 100644
--- a/middleware/file/ds_test.go
+++ b/plugin/file/ds_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/ent_test.go b/plugin/file/ent_test.go
similarity index 98%
rename from middleware/file/ent_test.go
rename to plugin/file/ent_test.go
index 433aa182d..6f4f1db6c 100644
--- a/middleware/file/ent_test.go
+++ b/plugin/file/ent_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/example_org.go b/plugin/file/example_org.go
similarity index 100%
rename from middleware/file/example_org.go
rename to plugin/file/example_org.go
diff --git a/middleware/file/file.go b/plugin/file/file.go
similarity index 91%
rename from middleware/file/file.go
rename to plugin/file/file.go
index 27ab0cd1b..89c2df90a 100644
--- a/middleware/file/file.go
+++ b/plugin/file/file.go
@@ -6,7 +6,7 @@ import (
 	"io"
 	"log"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -14,9 +14,9 @@ import (
 )
 
 type (
-	// File is the middleware that reads zone data from disk.
+	// File is the plugin that reads zone data from disk.
 	File struct {
-		Next  middleware.Handler
+		Next  plugin.Handler
 		Zones Zones
 	}
 
@@ -27,15 +27,15 @@ type (
 	}
 )
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (f File) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 
 	qname := state.Name()
 	// TODO(miek): match the qname better in the map
-	zone := middleware.Zones(f.Zones.Names).Matches(qname)
+	zone := plugin.Zones(f.Zones.Names).Matches(qname)
 	if zone == "" {
-		return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r)
+		return plugin.NextOrFailure(f.Name(), f.Next, ctx, w, r)
 	}
 
 	z, ok := f.Zones.Z[zone]
diff --git a/middleware/file/file_test.go b/plugin/file/file_test.go
similarity index 100%
rename from middleware/file/file_test.go
rename to plugin/file/file_test.go
diff --git a/middleware/file/glue_test.go b/plugin/file/glue_test.go
similarity index 98%
rename from middleware/file/glue_test.go
rename to plugin/file/glue_test.go
index 14716ae33..3880953c2 100644
--- a/middleware/file/glue_test.go
+++ b/plugin/file/glue_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/include_test.go b/plugin/file/include_test.go
similarity index 93%
rename from middleware/file/include_test.go
rename to plugin/file/include_test.go
index f07a02e03..fad91df5c 100644
--- a/middleware/file/include_test.go
+++ b/plugin/file/include_test.go
@@ -4,7 +4,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 )
 
 // Make sure the external miekg/dns dependency is up to date
diff --git a/middleware/file/lookup.go b/plugin/file/lookup.go
similarity index 99%
rename from middleware/file/lookup.go
rename to plugin/file/lookup.go
index 89e0f5a47..cf2f06841 100644
--- a/middleware/file/lookup.go
+++ b/plugin/file/lookup.go
@@ -1,7 +1,7 @@
 package file
 
 import (
-	"github.com/coredns/coredns/middleware/file/tree"
+	"github.com/coredns/coredns/plugin/file/tree"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/file/lookup_test.go b/plugin/file/lookup_test.go
similarity index 98%
rename from middleware/file/lookup_test.go
rename to plugin/file/lookup_test.go
index 82d8f77ff..8fd93fd8e 100644
--- a/middleware/file/lookup_test.go
+++ b/plugin/file/lookup_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/notify.go b/plugin/file/notify.go
similarity index 97%
rename from middleware/file/notify.go
rename to plugin/file/notify.go
index b1628c3a6..68850e0d3 100644
--- a/middleware/file/notify.go
+++ b/plugin/file/notify.go
@@ -5,7 +5,7 @@ import (
 	"log"
 	"net"
 
-	"github.com/coredns/coredns/middleware/pkg/rcode"
+	"github.com/coredns/coredns/plugin/pkg/rcode"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/file/nsec3_test.go b/plugin/file/nsec3_test.go
similarity index 100%
rename from middleware/file/nsec3_test.go
rename to plugin/file/nsec3_test.go
diff --git a/middleware/file/reload.go b/plugin/file/reload.go
similarity index 100%
rename from middleware/file/reload.go
rename to plugin/file/reload.go
diff --git a/middleware/file/reload_test.go b/plugin/file/reload_test.go
similarity index 97%
rename from middleware/file/reload_test.go
rename to plugin/file/reload_test.go
index c4d065155..601c426d3 100644
--- a/middleware/file/reload_test.go
+++ b/plugin/file/reload_test.go
@@ -8,7 +8,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/file/secondary.go b/plugin/file/secondary.go
similarity index 100%
rename from middleware/file/secondary.go
rename to plugin/file/secondary.go
diff --git a/middleware/file/secondary_test.go b/plugin/file/secondary_test.go
similarity index 98%
rename from middleware/file/secondary_test.go
rename to plugin/file/secondary_test.go
index cdb051d26..8f2c2e15f 100644
--- a/middleware/file/secondary_test.go
+++ b/plugin/file/secondary_test.go
@@ -6,7 +6,7 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/file/setup.go b/plugin/file/setup.go
similarity index 90%
rename from middleware/file/setup.go
rename to plugin/file/setup.go
index 2ac7610c5..bf0523c54 100644
--- a/middleware/file/setup.go
+++ b/plugin/file/setup.go
@@ -6,9 +6,9 @@ import (
 	"path"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/proxy"
 
 	"github.com/mholt/caddy"
 )
@@ -23,7 +23,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	zones, err := fileParse(c)
 	if err != nil {
-		return middleware.Error("file", err)
+		return plugin.Error("file", err)
 	}
 
 	// Add startup functions to notify the master(s).
@@ -40,7 +40,7 @@ func setup(c *caddy.Controller) error {
 		})
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return File{Next: next, Zones: zones}
 	})
 
@@ -79,7 +79,7 @@ func fileParse(c *caddy.Controller) (Zones, error) {
 		}
 
 		for i := range origins {
-			origins[i] = middleware.Host(origins[i]).Normalize()
+			origins[i] = plugin.Host(origins[i]).Normalize()
 			zone, err := Parse(reader, origins[i], fileName, 0)
 			if err == nil {
 				z[origins[i]] = zone
diff --git a/middleware/file/setup_test.go b/plugin/file/setup_test.go
similarity index 97%
rename from middleware/file/setup_test.go
rename to plugin/file/setup_test.go
index 111be1261..62e8476f6 100644
--- a/middleware/file/setup_test.go
+++ b/plugin/file/setup_test.go
@@ -3,7 +3,7 @@ package file
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/mholt/caddy"
 )
diff --git a/middleware/file/tree/all.go b/plugin/file/tree/all.go
similarity index 100%
rename from middleware/file/tree/all.go
rename to plugin/file/tree/all.go
diff --git a/middleware/file/tree/elem.go b/plugin/file/tree/elem.go
similarity index 100%
rename from middleware/file/tree/elem.go
rename to plugin/file/tree/elem.go
diff --git a/middleware/file/tree/less.go b/plugin/file/tree/less.go
similarity index 100%
rename from middleware/file/tree/less.go
rename to plugin/file/tree/less.go
diff --git a/middleware/file/tree/less_test.go b/plugin/file/tree/less_test.go
similarity index 100%
rename from middleware/file/tree/less_test.go
rename to plugin/file/tree/less_test.go
diff --git a/middleware/file/tree/print.go b/plugin/file/tree/print.go
similarity index 100%
rename from middleware/file/tree/print.go
rename to plugin/file/tree/print.go
diff --git a/middleware/file/tree/tree.go b/plugin/file/tree/tree.go
similarity index 100%
rename from middleware/file/tree/tree.go
rename to plugin/file/tree/tree.go
diff --git a/middleware/file/wildcard.go b/plugin/file/wildcard.go
similarity index 100%
rename from middleware/file/wildcard.go
rename to plugin/file/wildcard.go
diff --git a/middleware/file/wildcard_test.go b/plugin/file/wildcard_test.go
similarity index 98%
rename from middleware/file/wildcard_test.go
rename to plugin/file/wildcard_test.go
index 7f1a2fed3..038d37a43 100644
--- a/middleware/file/wildcard_test.go
+++ b/plugin/file/wildcard_test.go
@@ -4,8 +4,8 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/file/xfr.go b/plugin/file/xfr.go
similarity index 83%
rename from middleware/file/xfr.go
rename to plugin/file/xfr.go
index 54f7b71f8..4a03779ed 100644
--- a/middleware/file/xfr.go
+++ b/plugin/file/xfr.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"log"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -16,14 +16,14 @@ type Xfr struct {
 	*Zone
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (x Xfr) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	if !x.TransferAllowed(state) {
 		return dns.RcodeServerFailure, nil
 	}
 	if state.QType() != dns.TypeAXFR && state.QType() != dns.TypeIXFR {
-		return 0, middleware.Error(x.Name(), fmt.Errorf("xfr called with non transfer type: %d", state.QType()))
+		return 0, plugin.Error(x.Name(), fmt.Errorf("xfr called with non transfer type: %d", state.QType()))
 	}
 
 	records := x.All()
@@ -56,7 +56,7 @@ func (x Xfr) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (in
 	return dns.RcodeSuccess, nil
 }
 
-// Name implements the middleware.Hander interface.
+// Name implements the plugin.Hander interface.
 func (x Xfr) Name() string { return "xfr" }
 
 const transferLength = 1000 // Start a new envelop after message reaches this size in bytes. Intentionally small to test multi envelope parsing.
diff --git a/middleware/file/xfr_test.go b/plugin/file/xfr_test.go
similarity index 100%
rename from middleware/file/xfr_test.go
rename to plugin/file/xfr_test.go
diff --git a/middleware/file/zone.go b/plugin/file/zone.go
similarity index 97%
rename from middleware/file/zone.go
rename to plugin/file/zone.go
index 3f3bcf0f7..1cef9dc3a 100644
--- a/middleware/file/zone.go
+++ b/plugin/file/zone.go
@@ -7,8 +7,8 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/coredns/coredns/middleware/file/tree"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin/file/tree"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/file/zone_test.go b/plugin/file/zone_test.go
similarity index 100%
rename from middleware/file/zone_test.go
rename to plugin/file/zone_test.go
diff --git a/middleware/health/README.md b/plugin/health/README.md
similarity index 71%
rename from middleware/health/README.md
rename to plugin/health/README.md
index 195a480c0..59aed3b81 100644
--- a/middleware/health/README.md
+++ b/plugin/health/README.md
@@ -10,8 +10,8 @@ health [ADDRESS]
 
 Optionally takes an address; the default is `:8080`. The health path is fixed to `/health`. The
 health endpoint returns a 200 response code and the word "OK" when CoreDNS is healthy. It returns
-a 503. *health* periodically (1s) polls middleware that exports health information. If any of the
-middleware signals that it is unhealthy, the server will go unhealthy too. Each middleware that
+a 503. *health* periodically (1s) polls plugin that exports health information. If any of the
+plugin signals that it is unhealthy, the server will go unhealthy too. Each plugin that
 supports health checks has a section "Health" in their README.
 
 ## Examples
diff --git a/middleware/health/health.go b/plugin/health/health.go
similarity index 84%
rename from middleware/health/health.go
rename to plugin/health/health.go
index 5e5c4c32f..0a256c963 100644
--- a/middleware/health/health.go
+++ b/plugin/health/health.go
@@ -17,10 +17,10 @@ type health struct {
 	ln  net.Listener
 	mux *http.ServeMux
 
-	// A slice of Healthers that the health middleware will poll every second for their health status.
+	// A slice of Healthers that the health plugin will poll every second for their health status.
 	h []Healther
 	sync.RWMutex
-	ok bool // ok is the global boolean indicating an all healthy middleware stack
+	ok bool // ok is the global boolean indicating an all healthy plugin stack
 }
 
 func (h *health) Startup() error {
diff --git a/middleware/health/health_test.go b/plugin/health/health_test.go
similarity index 95%
rename from middleware/health/health_test.go
rename to plugin/health/health_test.go
index ea22ad8b6..f05f53073 100644
--- a/middleware/health/health_test.go
+++ b/plugin/health/health_test.go
@@ -1,6 +1,6 @@
 package health
 
-// TODO(miek): enable again if middleware gets health check.
+// TODO(miek): enable again if plugin gets health check.
 /*
 func TestHealth(t *testing.T) {
 	h := health{Addr: ":0"}
diff --git a/middleware/health/healther.go b/plugin/health/healther.go
similarity index 58%
rename from middleware/health/healther.go
rename to plugin/health/healther.go
index 1b794e03b..ad0261dfb 100644
--- a/middleware/health/healther.go
+++ b/plugin/health/healther.go
@@ -1,25 +1,25 @@
 package health
 
-// Healther interface needs to be implemented by each middleware willing to
-// provide healthhceck information to the health middleware. As a second step
-// the middleware needs to registered against the health middleware, by addding
+// Healther interface needs to be implemented by each plugin willing to
+// provide healthhceck information to the health plugin. As a second step
+// the plugin needs to registered against the health plugin, by addding
 // it to healthers map. Note this method should return quickly, i.e. just
 // checking a boolean status, as it is called every second from the health
-// middleware.
+// plugin.
 type Healther interface {
-	// Health returns a boolean indicating the health status of a middleware.
+	// Health returns a boolean indicating the health status of a plugin.
 	// False indicates unhealthy.
 	Health() bool
 }
 
-// Ok returns the global health status of all middleware configured in this server.
+// Ok returns the global health status of all plugin configured in this server.
 func (h *health) Ok() bool {
 	h.RLock()
 	defer h.RUnlock()
 	return h.ok
 }
 
-// SetOk sets the global health status of all middleware configured in this server.
+// SetOk sets the global health status of all plugin configured in this server.
 func (h *health) SetOk(ok bool) {
 	h.Lock()
 	defer h.Unlock()
diff --git a/middleware/health/setup.go b/plugin/health/setup.go
similarity index 85%
rename from middleware/health/setup.go
rename to plugin/health/setup.go
index bf465bd74..2fec9baa7 100644
--- a/middleware/health/setup.go
+++ b/plugin/health/setup.go
@@ -5,7 +5,7 @@ import (
 	"time"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -20,7 +20,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	addr, err := healthParse(c)
 	if err != nil {
-		return middleware.Error("health", err)
+		return plugin.Error("health", err)
 	}
 
 	h := &health{Addr: addr}
@@ -49,7 +49,7 @@ func setup(c *caddy.Controller) error {
 	c.OnStartup(h.Startup)
 	c.OnFinalShutdown(h.Shutdown)
 
-	// Don't do AddMiddleware, as health is not *really* a middleware just a separate webserver running.
+	// Don't do AddMiddleware, as health is not *really* a plugin just a separate webserver running.
 	return nil
 }
 
diff --git a/middleware/health/setup_test.go b/plugin/health/setup_test.go
similarity index 100%
rename from middleware/health/setup_test.go
rename to plugin/health/setup_test.go
diff --git a/middleware/hosts/README.md b/plugin/hosts/README.md
similarity index 77%
rename from middleware/hosts/README.md
rename to plugin/hosts/README.md
index 91d340cb5..60c738077 100644
--- a/middleware/hosts/README.md
+++ b/plugin/hosts/README.md
@@ -2,9 +2,9 @@
 
 *hosts* enables serving zone data from a `/etc/hosts` style file.
 
-The hosts middleware is useful for serving zones from a /etc/hosts file. It serves from a preloaded
+The hosts plugin is useful for serving zones from a /etc/hosts file. It serves from a preloaded
 file that exists on disk. It checks the file for changes and updates the zones accordingly. This
-middleware only supports A, AAAA, and PTR records. The hosts middleware can be used with readily
+plugin only supports A, AAAA, and PTR records. The hosts plugin can be used with readily
 available hosts files that block access to advertising servers.
 
 ## Syntax
@@ -19,7 +19,7 @@ hosts [FILE [ZONES...]] {
   directive will be prepended to it. Defaults to /etc/hosts if omitted
 * **ZONES** zones it should be authoritative for. If empty, the zones from the configuration block
     are used.
-* `fallthrough` If zone matches and no record can be generated, pass request to the next middleware.
+* `fallthrough` If zone matches and no record can be generated, pass request to the next plugin.
 
 ## Examples
 
@@ -36,7 +36,7 @@ hosts example.hosts
 ~~~
 
 Load example.hosts file and only serve example.org and example.net from it and fall through to the
-next middleware if query doesn't match.
+next plugin if query doesn't match.
 
 ~~~
 hosts example.hosts example.org example.net {
diff --git a/middleware/hosts/hosts.go b/plugin/hosts/hosts.go
similarity index 85%
rename from middleware/hosts/hosts.go
rename to plugin/hosts/hosts.go
index 28efc47ec..09dedbb64 100644
--- a/middleware/hosts/hosts.go
+++ b/plugin/hosts/hosts.go
@@ -5,33 +5,33 @@ import (
 
 	"golang.org/x/net/context"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 	"github.com/miekg/dns"
 )
 
-// Hosts is the middleware handler
+// Hosts is the plugin handler
 type Hosts struct {
-	Next middleware.Handler
+	Next plugin.Handler
 	*Hostsfile
 
 	Fallthrough bool
 }
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	qname := state.Name()
 
 	answers := []dns.RR{}
 
-	zone := middleware.Zones(h.Origins).Matches(qname)
+	zone := plugin.Zones(h.Origins).Matches(qname)
 	if zone == "" {
 		// PTR zones don't need to be specified in Origins
 		if state.Type() != "PTR" {
 			// If this doesn't match we need to fall through regardless of h.Fallthrough
-			return middleware.NextOrFailure(h.Name(), h.Next, ctx, w, r)
+			return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 		}
 	}
 
@@ -40,7 +40,7 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
 		names := h.LookupStaticAddr(dnsutil.ExtractAddressFromReverse(qname))
 		if len(names) == 0 {
 			// If this doesn't match we need to fall through regardless of h.Fallthrough
-			return middleware.NextOrFailure(h.Name(), h.Next, ctx, w, r)
+			return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 		}
 		answers = h.ptr(qname, names)
 	case dns.TypeA:
@@ -53,7 +53,7 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
 
 	if len(answers) == 0 {
 		if h.Fallthrough {
-			return middleware.NextOrFailure(h.Name(), h.Next, ctx, w, r)
+			return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
 		}
 		if !h.otherRecordsExist(state.QType(), qname) {
 			return dns.RcodeNameError, nil
@@ -93,7 +93,7 @@ func (h Hosts) otherRecordsExist(qtype uint16, qname string) bool {
 
 }
 
-// Name implements the middleware.Handle interface.
+// Name implements the plugin.Handle interface.
 func (h Hosts) Name() string { return "hosts" }
 
 // a takes a slice of net.IPs and returns a slice of A RRs.
diff --git a/middleware/hosts/hosts_test.go b/plugin/hosts/hosts_test.go
similarity index 93%
rename from middleware/hosts/hosts_test.go
rename to plugin/hosts/hosts_test.go
index b6ebaa43a..68b91b8c2 100644
--- a/middleware/hosts/hosts_test.go
+++ b/plugin/hosts/hosts_test.go
@@ -5,8 +5,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/hosts/hostsfile.go b/plugin/hosts/hostsfile.go
similarity index 96%
rename from middleware/hosts/hostsfile.go
rename to plugin/hosts/hostsfile.go
index a4f4a017d..91e828099 100644
--- a/middleware/hosts/hostsfile.go
+++ b/plugin/hosts/hostsfile.go
@@ -16,7 +16,7 @@ import (
 	"sync"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 )
 
 const cacheMaxAge = 5 * time.Second
@@ -31,7 +31,7 @@ func parseLiteralIP(addr string) net.IP {
 }
 
 func absDomainName(b string) string {
-	return middleware.Name(b).Normalize()
+	return plugin.Name(b).Normalize()
 }
 
 // Hostsfile contains known host entries.
@@ -110,7 +110,7 @@ func (h *Hostsfile) Parse(file io.Reader) {
 		ver := ipVersion(string(f[0]))
 		for i := 1; i < len(f); i++ {
 			name := absDomainName(string(f[i]))
-			if middleware.Zones(h.Origins).Matches(name) == "" {
+			if plugin.Zones(h.Origins).Matches(name) == "" {
 				// name is not in Origins
 				continue
 			}
diff --git a/middleware/hosts/hostsfile_test.go b/plugin/hosts/hostsfile_test.go
similarity index 100%
rename from middleware/hosts/hostsfile_test.go
rename to plugin/hosts/hostsfile_test.go
diff --git a/middleware/hosts/setup.go b/plugin/hosts/setup.go
similarity index 86%
rename from middleware/hosts/setup.go
rename to plugin/hosts/setup.go
index 38458541c..c7c0c728a 100644
--- a/middleware/hosts/setup.go
+++ b/plugin/hosts/setup.go
@@ -6,7 +6,7 @@ import (
 	"path"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -21,10 +21,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	h, err := hostsParse(c)
 	if err != nil {
-		return middleware.Error("hosts", err)
+		return plugin.Error("hosts", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		h.Next = next
 		return h
 	})
@@ -66,7 +66,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
 		}
 
 		for i := range origins {
-			origins[i] = middleware.Host(origins[i]).Normalize()
+			origins[i] = plugin.Host(origins[i]).Normalize()
 		}
 		h.Origins = origins
 
diff --git a/middleware/hosts/setup_test.go b/plugin/hosts/setup_test.go
similarity index 100%
rename from middleware/hosts/setup_test.go
rename to plugin/hosts/setup_test.go
diff --git a/middleware/kubernetes/DEV-README.md b/plugin/kubernetes/DEV-README.md
similarity index 100%
rename from middleware/kubernetes/DEV-README.md
rename to plugin/kubernetes/DEV-README.md
diff --git a/middleware/kubernetes/README.md b/plugin/kubernetes/README.md
similarity index 87%
rename from middleware/kubernetes/README.md
rename to plugin/kubernetes/README.md
index 3e199c93a..387f1cf75 100644
--- a/middleware/kubernetes/README.md
+++ b/plugin/kubernetes/README.md
@@ -1,15 +1,15 @@
 # kubernetes
 
-The *kubernetes* middleware enables the reading zone data from a Kubernetes cluster.  It implements
+The *kubernetes* plugin enables the reading zone data from a Kubernetes cluster.  It implements
 the [Kubernetes DNS-Based Service Discovery
 Specification](https://github.com/kubernetes/dns/blob/master/docs/specification.md).
 
-CoreDNS running the kubernetes middleware can be used as a replacement of kube-dns in a kubernetes
+CoreDNS running the kubernetes plugin can be used as a replacement of kube-dns in a kubernetes
 cluster.  See the [deployment](https://github.com/coredns/deployment) repository for details on [how
 to deploy CoreDNS in Kubernetes](https://github.com/coredns/deployment/tree/master/kubernetes).
 
 [stubDomains](http://blog.kubernetes.io/2017/04/configuring-private-dns-zones-upstream-nameservers-kubernetes.html)
-are implemented via the *proxy* middleware.
+are implemented via the *proxy* plugin.
 
 ## Syntax
 
@@ -17,10 +17,10 @@ are implemented via the *proxy* middleware.
 kubernetes [ZONES...]
 ~~~
 
-With only the directive specified, the *kubernetes* middleware will default to the zone specified in
+With only the directive specified, the *kubernetes* plugin will default to the zone specified in
 the server's block. It will handle all queries in that zone and connect to Kubernetes in-cluster. It
 will not provide PTR records for services, or A records for pods. If **ZONES** is used it specifies
-all the zones the middleware should be authoritative for.
+all the zones the plugin should be authoritative for.
 
 ```
 kubernetes [ZONES...] {
@@ -70,7 +70,7 @@ kubernetes [ZONES...] {
   5 seconds, the maximum is capped at 3600 seconds.
 * `fallthrough`  If a query for a record in the cluster zone results in NXDOMAIN, normally that is
   what the response will be. However, if you specify this option, the query will instead be passed
-  on down the middleware chain, which can include another middleware to handle the query.
+  on down the plugin chain, which can include another plugin to handle the query.
 
 ## Examples
 
@@ -105,7 +105,7 @@ kubernetes cluster.local {
 }
 ~~~
 
-Here we use the *proxy* middleware to implement stubDomains that forwards `example.org` and
+Here we use the *proxy* plugin to implement stubDomains that forwards `example.org` and
 `example.com` to another nameserver.
 
 ~~~ txt
@@ -125,7 +125,7 @@ example.com {
 
 ## AutoPath
 
-The *kubernetes* middleware can be used in conjunction with the *autopath* middleware.  Using this
+The *kubernetes* plugin can be used in conjunction with the *autopath* plugin.  Using this
 feature enables server-side domain search path completion in kubernetes clusters.  Note: `pods` must
 be set to `verified` for this to function properly.
 
@@ -138,7 +138,7 @@ be set to `verified` for this to function properly.
 
 ## Federation
 
-The *kubernetes* middleware can be used in conjunction with the *federation* middleware.  Using this
+The *kubernetes* plugin can be used in conjunction with the *federation* plugin.  Using this
 feature enables serving federated domains from the kubernetes clusters.
 
     cluster.local {
diff --git a/middleware/kubernetes/apiproxy.go b/plugin/kubernetes/apiproxy.go
similarity index 96%
rename from middleware/kubernetes/apiproxy.go
rename to plugin/kubernetes/apiproxy.go
index f6d2c00fa..3e185f898 100644
--- a/middleware/kubernetes/apiproxy.go
+++ b/plugin/kubernetes/apiproxy.go
@@ -7,7 +7,7 @@ import (
 	"net"
 	"net/http"
 
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
 )
 
 type proxyHandler struct {
diff --git a/middleware/kubernetes/autopath.go b/plugin/kubernetes/autopath.go
similarity index 86%
rename from middleware/kubernetes/autopath.go
rename to plugin/kubernetes/autopath.go
index be71ce326..f758869f1 100644
--- a/middleware/kubernetes/autopath.go
+++ b/plugin/kubernetes/autopath.go
@@ -1,17 +1,17 @@
 package kubernetes
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"k8s.io/client-go/1.5/pkg/api"
 )
 
-// AutoPath implements the AutoPathFunc call from the autopath middleware.
+// AutoPath implements the AutoPathFunc call from the autopath plugin.
 // It returns a per-query search path or nil indicating no searchpathing should happen.
 func (k *Kubernetes) AutoPath(state request.Request) []string {
 	// Check if the query falls in a zone we are actually authoriative for and thus if we want autopath.
-	zone := middleware.Zones(k.Zones).Matches(state.Name())
+	zone := plugin.Zones(k.Zones).Matches(state.Name())
 	if zone == "" {
 		return nil
 	}
diff --git a/middleware/kubernetes/controller.go b/plugin/kubernetes/controller.go
similarity index 100%
rename from middleware/kubernetes/controller.go
rename to plugin/kubernetes/controller.go
diff --git a/middleware/kubernetes/federation.go b/plugin/kubernetes/federation.go
similarity index 86%
rename from middleware/kubernetes/federation.go
rename to plugin/kubernetes/federation.go
index f192a4a76..df6ae948b 100644
--- a/middleware/kubernetes/federation.go
+++ b/plugin/kubernetes/federation.go
@@ -1,8 +1,8 @@
 package kubernetes
 
 import (
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 )
 
@@ -21,7 +21,7 @@ const (
 	LabelRegion = "failure-domain.beta.kubernetes.io/region"
 )
 
-// Federations is used from the federations middleware to return the service that should be
+// Federations is used from the federations plugin to return the service that should be
 // returned as a CNAME for federation(s) to work.
 func (k *Kubernetes) Federations(state request.Request, fname, fzone string) (msg.Service, error) {
 	nodeName := k.localNodeName()
diff --git a/plugin/kubernetes/handler.go b/plugin/kubernetes/handler.go
new file mode 100644
index 000000000..9dc435111
--- /dev/null
+++ b/plugin/kubernetes/handler.go
@@ -0,0 +1,86 @@
+package kubernetes
+
+import (
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/request"
+
+	"github.com/miekg/dns"
+	"golang.org/x/net/context"
+)
+
+// ServeDNS implements the plugin.Handler interface.
+func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+	state := request.Request{W: w, Req: r}
+
+	m := new(dns.Msg)
+	m.SetReply(r)
+	m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true
+
+	zone := plugin.Zones(k.Zones).Matches(state.Name())
+	if zone == "" {
+		return plugin.NextOrFailure(k.Name(), k.Next, ctx, w, r)
+	}
+
+	state.Zone = zone
+
+	var (
+		records []dns.RR
+		extra   []dns.RR
+		err     error
+	)
+
+	switch state.Type() {
+	case "A":
+		records, err = plugin.A(&k, zone, state, nil, plugin.Options{})
+	case "AAAA":
+		records, err = plugin.AAAA(&k, zone, state, nil, plugin.Options{})
+	case "TXT":
+		records, err = plugin.TXT(&k, zone, state, plugin.Options{})
+	case "CNAME":
+		records, err = plugin.CNAME(&k, zone, state, plugin.Options{})
+	case "PTR":
+		records, err = plugin.PTR(&k, zone, state, plugin.Options{})
+	case "MX":
+		records, extra, err = plugin.MX(&k, zone, state, plugin.Options{})
+	case "SRV":
+		records, extra, err = plugin.SRV(&k, zone, state, plugin.Options{})
+	case "SOA":
+		records, err = plugin.SOA(&k, zone, state, plugin.Options{})
+	case "NS":
+		if state.Name() == zone {
+			records, extra, err = plugin.NS(&k, zone, state, plugin.Options{})
+			break
+		}
+		fallthrough
+	default:
+		// Do a fake A lookup, so we can distinguish between NODATA and NXDOMAIN
+		_, err = plugin.A(&k, zone, state, nil, plugin.Options{})
+	}
+
+	if k.IsNameError(err) {
+		if k.Fallthrough {
+			return plugin.NextOrFailure(k.Name(), k.Next, ctx, w, r)
+		}
+		return plugin.BackendError(&k, zone, dns.RcodeNameError, state, nil /* err */, plugin.Options{})
+	}
+	if err != nil {
+		return dns.RcodeServerFailure, err
+	}
+
+	if len(records) == 0 {
+		return plugin.BackendError(&k, zone, dns.RcodeSuccess, state, nil, plugin.Options{})
+	}
+
+	m.Answer = append(m.Answer, records...)
+	m.Extra = append(m.Extra, extra...)
+
+	m = dnsutil.Dedup(m)
+	state.SizeAndDo(m)
+	m, _ = state.Scrub(m)
+	w.WriteMsg(m)
+	return dns.RcodeSuccess, nil
+}
+
+// Name implements the Handler interface.
+func (k Kubernetes) Name() string { return "kubernetes" }
diff --git a/middleware/kubernetes/handler_pod_disabled_test.go b/plugin/kubernetes/handler_pod_disabled_test.go
similarity index 92%
rename from middleware/kubernetes/handler_pod_disabled_test.go
rename to plugin/kubernetes/handler_pod_disabled_test.go
index b1fb7604c..4c6e15710 100644
--- a/middleware/kubernetes/handler_pod_disabled_test.go
+++ b/plugin/kubernetes/handler_pod_disabled_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/handler_pod_insecure_test.go b/plugin/kubernetes/handler_pod_insecure_test.go
similarity index 91%
rename from middleware/kubernetes/handler_pod_insecure_test.go
rename to plugin/kubernetes/handler_pod_insecure_test.go
index bc09f3c4f..b2df8a504 100644
--- a/middleware/kubernetes/handler_pod_insecure_test.go
+++ b/plugin/kubernetes/handler_pod_insecure_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/handler_pod_verified_test.go b/plugin/kubernetes/handler_pod_verified_test.go
similarity index 92%
rename from middleware/kubernetes/handler_pod_verified_test.go
rename to plugin/kubernetes/handler_pod_verified_test.go
index 879e785af..ea585cc6a 100644
--- a/middleware/kubernetes/handler_pod_verified_test.go
+++ b/plugin/kubernetes/handler_pod_verified_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/handler_test.go b/plugin/kubernetes/handler_test.go
similarity index 98%
rename from middleware/kubernetes/handler_test.go
rename to plugin/kubernetes/handler_test.go
index 8ab51aff8..5413f5b4c 100644
--- a/middleware/kubernetes/handler_test.go
+++ b/plugin/kubernetes/handler_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/kubernetes.go b/plugin/kubernetes/kubernetes.go
similarity index 96%
rename from middleware/kubernetes/kubernetes.go
rename to plugin/kubernetes/kubernetes.go
index fe58df74d..90fcd6182 100644
--- a/middleware/kubernetes/kubernetes.go
+++ b/plugin/kubernetes/kubernetes.go
@@ -9,11 +9,11 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -26,9 +26,9 @@ import (
 	clientcmdapi "k8s.io/client-go/1.5/tools/clientcmd/api"
 )
 
-// Kubernetes implements a middleware that connects to a Kubernetes cluster.
+// Kubernetes implements a plugin that connects to a Kubernetes cluster.
 type Kubernetes struct {
-	Next          middleware.Handler
+	Next          plugin.Handler
 	Zones         []string
 	Proxy         proxy.Proxy // Proxy for looking up names during the resolution process
 	APIServerList []string
@@ -81,7 +81,7 @@ var (
 )
 
 // Services implements the ServiceBackend interface.
-func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.Options) (svcs []msg.Service, err error) {
+func (k *Kubernetes) Services(state request.Request, exact bool, opt plugin.Options) (svcs []msg.Service, err error) {
 
 	// We're looking again at types, which we've already done in ServeDNS, but there are some types k8s just can't answer.
 	switch state.QType() {
@@ -133,7 +133,7 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
 	return internal, e
 }
 
-// primaryZone will return the first non-reverse zone being handled by this middleware
+// primaryZone will return the first non-reverse zone being handled by this plugin
 func (k *Kubernetes) primaryZone() string { return k.Zones[k.primaryZoneIndex] }
 
 // Lookup implements the ServiceBackend interface.
diff --git a/middleware/kubernetes/kubernetes_apex_test.go b/plugin/kubernetes/kubernetes_apex_test.go
similarity index 93%
rename from middleware/kubernetes/kubernetes_apex_test.go
rename to plugin/kubernetes/kubernetes_apex_test.go
index 9a87a790a..41b70b883 100644
--- a/middleware/kubernetes/kubernetes_apex_test.go
+++ b/plugin/kubernetes/kubernetes_apex_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/kubernetes_test.go b/plugin/kubernetes/kubernetes_test.go
similarity index 98%
rename from middleware/kubernetes/kubernetes_test.go
rename to plugin/kubernetes/kubernetes_test.go
index 573a517b1..f347f10fc 100644
--- a/middleware/kubernetes/kubernetes_test.go
+++ b/plugin/kubernetes/kubernetes_test.go
@@ -3,7 +3,7 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -222,7 +222,7 @@ func TestServices(t *testing.T) {
 			Req:  &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
 			Zone: "interwebs.test.", // must match from k.Zones[0]
 		}
-		svcs, e := k.Services(state, false, middleware.Options{})
+		svcs, e := k.Services(state, false, plugin.Options{})
 		if e != nil {
 			t.Errorf("Test %d: got error '%v'", i, e)
 			continue
diff --git a/middleware/kubernetes/local.go b/plugin/kubernetes/local.go
similarity index 100%
rename from middleware/kubernetes/local.go
rename to plugin/kubernetes/local.go
diff --git a/middleware/kubernetes/ns.go b/plugin/kubernetes/ns.go
similarity index 100%
rename from middleware/kubernetes/ns.go
rename to plugin/kubernetes/ns.go
diff --git a/middleware/kubernetes/ns_test.go b/plugin/kubernetes/ns_test.go
similarity index 100%
rename from middleware/kubernetes/ns_test.go
rename to plugin/kubernetes/ns_test.go
diff --git a/middleware/kubernetes/parse.go b/plugin/kubernetes/parse.go
similarity index 95%
rename from middleware/kubernetes/parse.go
rename to plugin/kubernetes/parse.go
index bf8adfec3..a66e77699 100644
--- a/middleware/kubernetes/parse.go
+++ b/plugin/kubernetes/parse.go
@@ -1,7 +1,7 @@
 package kubernetes
 
 import (
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -32,7 +32,7 @@ func parseRequest(state request.Request) (r recordRequest, err error) {
 	// 2. (endpoint): endpoint.service.namespace.pod|svc.zone
 	// 3. (service): service.namespace.pod|svc.zone
 	//
-	// Federations are handled in the federation middleware. And aren't parsed here.
+	// Federations are handled in the federation plugin. And aren't parsed here.
 
 	base, _ := dnsutil.TrimZone(state.Name(), state.Zone)
 	segs := dns.SplitDomainName(base)
diff --git a/middleware/kubernetes/parse_test.go b/plugin/kubernetes/parse_test.go
similarity index 100%
rename from middleware/kubernetes/parse_test.go
rename to plugin/kubernetes/parse_test.go
diff --git a/middleware/kubernetes/reverse.go b/plugin/kubernetes/reverse.go
similarity index 88%
rename from middleware/kubernetes/reverse.go
rename to plugin/kubernetes/reverse.go
index 25ece8035..0143b721a 100644
--- a/middleware/kubernetes/reverse.go
+++ b/plugin/kubernetes/reverse.go
@@ -3,14 +3,14 @@ package kubernetes
 import (
 	"strings"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 )
 
 // Reverse implements the ServiceBackend interface.
-func (k *Kubernetes) Reverse(state request.Request, exact bool, opt middleware.Options) ([]msg.Service, error) {
+func (k *Kubernetes) Reverse(state request.Request, exact bool, opt plugin.Options) ([]msg.Service, error) {
 
 	ip := dnsutil.ExtractAddressFromReverse(state.Name())
 	if ip == "" {
diff --git a/middleware/kubernetes/reverse_test.go b/plugin/kubernetes/reverse_test.go
similarity index 96%
rename from middleware/kubernetes/reverse_test.go
rename to plugin/kubernetes/reverse_test.go
index aaf0907e8..aa9d09585 100644
--- a/middleware/kubernetes/reverse_test.go
+++ b/plugin/kubernetes/reverse_test.go
@@ -3,8 +3,8 @@ package kubernetes
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/kubernetes/setup.go b/plugin/kubernetes/setup.go
similarity index 90%
rename from middleware/kubernetes/setup.go
rename to plugin/kubernetes/setup.go
index 15b87c2cd..e60239d42 100644
--- a/middleware/kubernetes/setup.go
+++ b/plugin/kubernetes/setup.go
@@ -8,9 +8,9 @@ import (
 	"time"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/proxy"
 	"github.com/miekg/dns"
 
 	"github.com/mholt/caddy"
@@ -27,12 +27,12 @@ func init() {
 func setup(c *caddy.Controller) error {
 	kubernetes, initOpts, err := kubernetesParse(c)
 	if err != nil {
-		return middleware.Error("kubernetes", err)
+		return plugin.Error("kubernetes", err)
 	}
 
 	err = kubernetes.initKubeCache(initOpts)
 	if err != nil {
-		return middleware.Error("kubernetes", err)
+		return plugin.Error("kubernetes", err)
 	}
 
 	// Register KubeCache start and stop functions with Caddy
@@ -51,7 +51,7 @@ func setup(c *caddy.Controller) error {
 		return kubernetes.APIConn.Stop()
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		kubernetes.Next = next
 		return kubernetes
 	})
@@ -74,12 +74,12 @@ func kubernetesParse(c *caddy.Controller) (*Kubernetes, dnsControlOpts, error) {
 		if len(zones) != 0 {
 			k8s.Zones = zones
 			for i := 0; i < len(k8s.Zones); i++ {
-				k8s.Zones[i] = middleware.Host(k8s.Zones[i]).Normalize()
+				k8s.Zones[i] = plugin.Host(k8s.Zones[i]).Normalize()
 			}
 		} else {
 			k8s.Zones = make([]string, len(c.ServerBlockKeys))
 			for i := 0; i < len(c.ServerBlockKeys); i++ {
-				k8s.Zones[i] = middleware.Host(c.ServerBlockKeys[i]).Normalize()
+				k8s.Zones[i] = plugin.Host(c.ServerBlockKeys[i]).Normalize()
 			}
 		}
 
@@ -201,7 +201,7 @@ func searchFromResolvConf() []string {
 	if err != nil {
 		return nil
 	}
-	middleware.Zones(rc.Search).Normalize()
+	plugin.Zones(rc.Search).Normalize()
 	return rc.Search
 }
 
diff --git a/middleware/kubernetes/setup_reverse_test.go b/plugin/kubernetes/setup_reverse_test.go
similarity index 100%
rename from middleware/kubernetes/setup_reverse_test.go
rename to plugin/kubernetes/setup_reverse_test.go
diff --git a/middleware/kubernetes/setup_test.go b/plugin/kubernetes/setup_test.go
similarity index 100%
rename from middleware/kubernetes/setup_test.go
rename to plugin/kubernetes/setup_test.go
diff --git a/middleware/kubernetes/setup_ttl_test.go b/plugin/kubernetes/setup_ttl_test.go
similarity index 100%
rename from middleware/kubernetes/setup_ttl_test.go
rename to plugin/kubernetes/setup_ttl_test.go
diff --git a/middleware/loadbalance/README.md b/plugin/loadbalance/README.md
similarity index 100%
rename from middleware/loadbalance/README.md
rename to plugin/loadbalance/README.md
diff --git a/middleware/loadbalance/handler.go b/plugin/loadbalance/handler.go
similarity index 50%
rename from middleware/loadbalance/handler.go
rename to plugin/loadbalance/handler.go
index 3d3e4aa26..da4cf1549 100644
--- a/middleware/loadbalance/handler.go
+++ b/plugin/loadbalance/handler.go
@@ -1,22 +1,22 @@
-// Package loadbalance is middleware for rewriting responses to do "load balancing"
+// Package loadbalance is plugin for rewriting responses to do "load balancing"
 package loadbalance
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
 
-// RoundRobin is middleware to rewrite responses for "load balancing".
+// RoundRobin is plugin to rewrite responses for "load balancing".
 type RoundRobin struct {
-	Next middleware.Handler
+	Next plugin.Handler
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (rr RoundRobin) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	wrr := &RoundRobinResponseWriter{w}
-	return middleware.NextOrFailure(rr.Name(), rr.Next, ctx, wrr, r)
+	return plugin.NextOrFailure(rr.Name(), rr.Next, ctx, wrr, r)
 }
 
 // Name implements the Handler interface.
diff --git a/middleware/loadbalance/loadbalance.go b/plugin/loadbalance/loadbalance.go
similarity index 100%
rename from middleware/loadbalance/loadbalance.go
rename to plugin/loadbalance/loadbalance.go
diff --git a/middleware/loadbalance/loadbalance_test.go b/plugin/loadbalance/loadbalance_test.go
similarity index 94%
rename from middleware/loadbalance/loadbalance_test.go
rename to plugin/loadbalance/loadbalance_test.go
index 8c9205ca9..bde92b543 100644
--- a/middleware/loadbalance/loadbalance_test.go
+++ b/plugin/loadbalance/loadbalance_test.go
@@ -3,9 +3,9 @@ package loadbalance
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -160,8 +160,8 @@ func countRecords(result []dns.RR) (cname int, address int, mx int, sorted bool)
 	return
 }
 
-func handler() middleware.Handler {
-	return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+func handler() plugin.Handler {
+	return plugin.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 		w.WriteMsg(r)
 		return dns.RcodeSuccess, nil
 	})
diff --git a/middleware/loadbalance/setup.go b/plugin/loadbalance/setup.go
similarity index 74%
rename from middleware/loadbalance/setup.go
rename to plugin/loadbalance/setup.go
index 334d288a0..c2d90958e 100644
--- a/middleware/loadbalance/setup.go
+++ b/plugin/loadbalance/setup.go
@@ -2,7 +2,7 @@ package loadbalance
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	"github.com/mholt/caddy"
 )
 
@@ -18,7 +18,7 @@ func setup(c *caddy.Controller) error {
 		// TODO(miek): block and option parsing
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return RoundRobin{Next: next}
 	})
 
diff --git a/middleware/log/README.md b/plugin/log/README.md
similarity index 100%
rename from middleware/log/README.md
rename to plugin/log/README.md
diff --git a/middleware/log/log.go b/plugin/log/log.go
similarity index 74%
rename from middleware/log/log.go
rename to plugin/log/log.go
index f4a976002..52af79d35 100644
--- a/middleware/log/log.go
+++ b/plugin/log/log.go
@@ -1,39 +1,39 @@
-// Package log implements basic but useful request (access) logging middleware.
+// Package log implements basic but useful request (access) logging plugin.
 package log
 
 import (
 	"log"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/metrics/vars"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/pkg/rcode"
-	"github.com/coredns/coredns/middleware/pkg/replacer"
-	"github.com/coredns/coredns/middleware/pkg/response"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/metrics/vars"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/pkg/rcode"
+	"github.com/coredns/coredns/plugin/pkg/replacer"
+	"github.com/coredns/coredns/plugin/pkg/response"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
 )
 
-// Logger is a basic request logging middleware.
+// Logger is a basic request logging plugin.
 type Logger struct {
-	Next      middleware.Handler
+	Next      plugin.Handler
 	Rules     []Rule
 	ErrorFunc func(dns.ResponseWriter, *dns.Msg, int) // failover error handler
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 	for _, rule := range l.Rules {
-		if !middleware.Name(rule.NameScope).Matches(state.Name()) {
+		if !plugin.Name(rule.NameScope).Matches(state.Name()) {
 			continue
 		}
 
 		rrw := dnsrecorder.New(w)
-		rc, err := middleware.NextOrFailure(l.Name(), l.Next, ctx, rrw, r)
+		rc, err := plugin.NextOrFailure(l.Name(), l.Next, ctx, rrw, r)
 
 		if rc > 0 {
 			// There was an error up the chain, but no response has been written yet.
@@ -62,13 +62,13 @@ func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 		return rc, err
 
 	}
-	return middleware.NextOrFailure(l.Name(), l.Next, ctx, w, r)
+	return plugin.NextOrFailure(l.Name(), l.Next, ctx, w, r)
 }
 
 // Name implements the Handler interface.
 func (l Logger) Name() string { return "log" }
 
-// Rule configures the logging middleware.
+// Rule configures the logging plugin.
 type Rule struct {
 	NameScope  string
 	Class      response.Class
diff --git a/middleware/log/log_test.go b/plugin/log/log_test.go
similarity index 92%
rename from middleware/log/log_test.go
rename to plugin/log/log_test.go
index 80efc971c..ee1201a13 100644
--- a/middleware/log/log_test.go
+++ b/plugin/log/log_test.go
@@ -6,9 +6,9 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/pkg/response"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/pkg/response"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/middleware/log/setup.go b/plugin/log/setup.go
similarity index 87%
rename from middleware/log/setup.go
rename to plugin/log/setup.go
index 498829888..673962f10 100644
--- a/middleware/log/setup.go
+++ b/plugin/log/setup.go
@@ -6,8 +6,8 @@ import (
 	"os"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/response"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/response"
 
 	"github.com/mholt/caddy"
 	"github.com/miekg/dns"
@@ -23,7 +23,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	rules, err := logParse(c)
 	if err != nil {
-		return middleware.Error("log", err)
+		return plugin.Error("log", err)
 	}
 
 	// Open the log files for writing when the server starts
@@ -32,7 +32,7 @@ func setup(c *caddy.Controller) error {
 			// We only support stdout
 			writer := os.Stdout
 			if rules[i].OutputFile != "stdout" {
-				return middleware.Error("log", fmt.Errorf("invalid log file: %s", rules[i].OutputFile))
+				return plugin.Error("log", fmt.Errorf("invalid log file: %s", rules[i].OutputFile))
 			}
 
 			rules[i].Log = log.New(writer, "", 0)
@@ -41,7 +41,7 @@ func setup(c *caddy.Controller) error {
 		return nil
 	})
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Logger{Next: next, Rules: rules, ErrorFunc: dnsserver.DefaultErrorFunc}
 	})
 
diff --git a/middleware/log/setup_test.go b/plugin/log/setup_test.go
similarity index 98%
rename from middleware/log/setup_test.go
rename to plugin/log/setup_test.go
index 596239312..161f674be 100644
--- a/middleware/log/setup_test.go
+++ b/plugin/log/setup_test.go
@@ -3,7 +3,7 @@ package log
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/response"
+	"github.com/coredns/coredns/plugin/pkg/response"
 
 	"github.com/mholt/caddy"
 )
diff --git a/middleware/metrics/README.md b/plugin/metrics/README.md
similarity index 94%
rename from middleware/metrics/README.md
rename to plugin/metrics/README.md
index a1ab52b88..ead1f7e75 100644
--- a/middleware/metrics/README.md
+++ b/plugin/metrics/README.md
@@ -24,7 +24,7 @@ Extra labels used are:
   other types.
 * The `response_rcode_count_total` has an extra label `rcode` which holds the rcode of the response.
 
-If monitoring is enabled, queries that do not enter the middleware chain are exported under the fake
+If monitoring is enabled, queries that do not enter the plugin chain are exported under the fake
 name "dropped" (without a closing dot - this is never a valid domain name).
 
 
diff --git a/middleware/metrics/handler.go b/plugin/metrics/handler.go
similarity index 66%
rename from middleware/metrics/handler.go
rename to plugin/metrics/handler.go
index 50dc4141e..bc9a6ec47 100644
--- a/middleware/metrics/handler.go
+++ b/plugin/metrics/handler.go
@@ -1,10 +1,10 @@
 package metrics
 
 import (
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/metrics/vars"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/pkg/rcode"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/metrics/vars"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/pkg/rcode"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -16,14 +16,14 @@ func (m *Metrics) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
 	state := request.Request{W: w, Req: r}
 
 	qname := state.QName()
-	zone := middleware.Zones(m.ZoneNames()).Matches(qname)
+	zone := plugin.Zones(m.ZoneNames()).Matches(qname)
 	if zone == "" {
 		zone = "."
 	}
 
 	// Record response to get status code and size of the reply.
 	rw := dnsrecorder.New(w)
-	status, err := middleware.NextOrFailure(m.Name(), m.Next, ctx, rw, r)
+	status, err := plugin.NextOrFailure(m.Name(), m.Next, ctx, rw, r)
 
 	vars.Report(state, zone, rcode.ToString(rw.Rcode), rw.Len, rw.Start)
 
diff --git a/middleware/metrics/metrics.go b/plugin/metrics/metrics.go
similarity index 90%
rename from middleware/metrics/metrics.go
rename to plugin/metrics/metrics.go
index 6e06a2bf4..0dabcdf96 100644
--- a/middleware/metrics/metrics.go
+++ b/plugin/metrics/metrics.go
@@ -1,4 +1,4 @@
-// Package metrics implement a handler and middleware that provides Prometheus metrics.
+// Package metrics implement a handler and plugin that provides Prometheus metrics.
 package metrics
 
 import (
@@ -7,8 +7,8 @@ import (
 	"net/http"
 	"sync"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/metrics/vars"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/metrics/vars"
 
 	"github.com/prometheus/client_golang/prometheus"
 )
@@ -26,7 +26,7 @@ func init() {
 
 // Metrics holds the prometheus configuration. The metrics' path is fixed to be /metrics
 type Metrics struct {
-	Next middleware.Handler
+	Next plugin.Handler
 	Addr string
 	ln   net.Listener
 	mux  *http.ServeMux
diff --git a/middleware/metrics/metrics_test.go b/plugin/metrics/metrics_test.go
similarity index 88%
rename from middleware/metrics/metrics_test.go
rename to plugin/metrics/metrics_test.go
index 18a9011ed..f5a17607c 100644
--- a/middleware/metrics/metrics_test.go
+++ b/plugin/metrics/metrics_test.go
@@ -3,10 +3,10 @@ package metrics
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	mtest "github.com/coredns/coredns/middleware/metrics/test"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	mtest "github.com/coredns/coredns/plugin/metrics/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -22,7 +22,7 @@ func TestMetrics(t *testing.T) {
 	met.AddZone("example.org.")
 
 	tests := []struct {
-		next          middleware.Handler
+		next          plugin.Handler
 		qname         string
 		qtype         uint16
 		metric        string
diff --git a/middleware/metrics/setup.go b/plugin/metrics/setup.go
similarity index 88%
rename from middleware/metrics/setup.go
rename to plugin/metrics/setup.go
index 30b05d4ff..eecfac62c 100644
--- a/middleware/metrics/setup.go
+++ b/plugin/metrics/setup.go
@@ -4,7 +4,7 @@ import (
 	"net"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -21,10 +21,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	m, err := prometheusParse(c)
 	if err != nil {
-		return middleware.Error("prometheus", err)
+		return plugin.Error("prometheus", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		m.Next = next
 		return m
 	})
@@ -57,7 +57,7 @@ func prometheusParse(c *caddy.Controller) (*Metrics, error) {
 		}
 
 		for _, z := range c.ServerBlockKeys {
-			met.AddZone(middleware.Host(z).Normalize())
+			met.AddZone(plugin.Host(z).Normalize())
 		}
 		args := c.RemainingArgs()
 
diff --git a/middleware/metrics/setup_test.go b/plugin/metrics/setup_test.go
similarity index 100%
rename from middleware/metrics/setup_test.go
rename to plugin/metrics/setup_test.go
diff --git a/middleware/metrics/test/scrape.go b/plugin/metrics/test/scrape.go
similarity index 100%
rename from middleware/metrics/test/scrape.go
rename to plugin/metrics/test/scrape.go
diff --git a/middleware/metrics/vars/report.go b/plugin/metrics/vars/report.go
similarity index 100%
rename from middleware/metrics/vars/report.go
rename to plugin/metrics/vars/report.go
diff --git a/middleware/metrics/vars/vars.go b/plugin/metrics/vars/vars.go
similarity index 88%
rename from middleware/metrics/vars/vars.go
rename to plugin/metrics/vars/vars.go
index 42af10007..826f9ebed 100644
--- a/middleware/metrics/vars/vars.go
+++ b/plugin/metrics/vars/vars.go
@@ -1,7 +1,7 @@
 package vars
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/prometheus/client_golang/prometheus"
 )
@@ -9,14 +9,14 @@ import (
 // Request* and Response* are the prometheus counters and gauges we are using for exporting metrics.
 var (
 	RequestCount = prometheus.NewCounterVec(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "request_count_total",
 		Help:      "Counter of DNS requests made per zone, protocol and family.",
 	}, []string{"zone", "proto", "family"})
 
 	RequestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "request_duration_milliseconds",
 		Buckets:   append(prometheus.DefBuckets, []float64{50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 10000}...),
@@ -24,7 +24,7 @@ var (
 	}, []string{"zone"})
 
 	RequestSize = prometheus.NewHistogramVec(prometheus.HistogramOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "request_size_bytes",
 		Help:      "Size of the EDNS0 UDP buffer in bytes (64K for TCP).",
@@ -32,21 +32,21 @@ var (
 	}, []string{"zone", "proto"})
 
 	RequestDo = prometheus.NewCounterVec(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "request_do_count_total",
 		Help:      "Counter of DNS requests with DO bit set per zone.",
 	}, []string{"zone"})
 
 	RequestType = prometheus.NewCounterVec(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "request_type_count_total",
 		Help:      "Counter of DNS requests per type, per zone.",
 	}, []string{"zone", "type"})
 
 	ResponseSize = prometheus.NewHistogramVec(prometheus.HistogramOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "response_size_bytes",
 		Help:      "Size of the returned response in bytes.",
@@ -54,7 +54,7 @@ var (
 	}, []string{"zone", "proto"})
 
 	ResponseRcode = prometheus.NewCounterVec(prometheus.CounterOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: subsystem,
 		Name:      "response_rcode_count_total",
 		Help:      "Counter of response status codes.",
diff --git a/middleware/normalize.go b/plugin/normalize.go
similarity index 99%
rename from middleware/normalize.go
rename to plugin/normalize.go
index 92cc57937..75b9c53c8 100644
--- a/middleware/normalize.go
+++ b/plugin/normalize.go
@@ -1,4 +1,4 @@
-package middleware
+package plugin
 
 import (
 	"fmt"
diff --git a/middleware/normalize_test.go b/plugin/normalize_test.go
similarity index 99%
rename from middleware/normalize_test.go
rename to plugin/normalize_test.go
index e3d2268d3..3eb9c5231 100644
--- a/middleware/normalize_test.go
+++ b/plugin/normalize_test.go
@@ -1,4 +1,4 @@
-package middleware
+package plugin
 
 import "testing"
 
diff --git a/middleware/pkg/cache/cache.go b/plugin/pkg/cache/cache.go
similarity index 100%
rename from middleware/pkg/cache/cache.go
rename to plugin/pkg/cache/cache.go
diff --git a/middleware/pkg/cache/cache_test.go b/plugin/pkg/cache/cache_test.go
similarity index 100%
rename from middleware/pkg/cache/cache_test.go
rename to plugin/pkg/cache/cache_test.go
diff --git a/middleware/pkg/cache/shard_test.go b/plugin/pkg/cache/shard_test.go
similarity index 100%
rename from middleware/pkg/cache/shard_test.go
rename to plugin/pkg/cache/shard_test.go
diff --git a/middleware/pkg/dnsrecorder/recorder.go b/plugin/pkg/dnsrecorder/recorder.go
similarity index 100%
rename from middleware/pkg/dnsrecorder/recorder.go
rename to plugin/pkg/dnsrecorder/recorder.go
diff --git a/middleware/pkg/dnsrecorder/recorder_test.go b/plugin/pkg/dnsrecorder/recorder_test.go
similarity index 100%
rename from middleware/pkg/dnsrecorder/recorder_test.go
rename to plugin/pkg/dnsrecorder/recorder_test.go
diff --git a/middleware/pkg/dnsutil/cname.go b/plugin/pkg/dnsutil/cname.go
similarity index 100%
rename from middleware/pkg/dnsutil/cname.go
rename to plugin/pkg/dnsutil/cname.go
diff --git a/middleware/pkg/dnsutil/cname_test.go b/plugin/pkg/dnsutil/cname_test.go
similarity index 100%
rename from middleware/pkg/dnsutil/cname_test.go
rename to plugin/pkg/dnsutil/cname_test.go
diff --git a/middleware/pkg/dnsutil/dedup.go b/plugin/pkg/dnsutil/dedup.go
similarity index 100%
rename from middleware/pkg/dnsutil/dedup.go
rename to plugin/pkg/dnsutil/dedup.go
diff --git a/middleware/pkg/dnsutil/doc.go b/plugin/pkg/dnsutil/doc.go
similarity index 100%
rename from middleware/pkg/dnsutil/doc.go
rename to plugin/pkg/dnsutil/doc.go
diff --git a/middleware/pkg/dnsutil/host.go b/plugin/pkg/dnsutil/host.go
similarity index 100%
rename from middleware/pkg/dnsutil/host.go
rename to plugin/pkg/dnsutil/host.go
diff --git a/middleware/pkg/dnsutil/host_test.go b/plugin/pkg/dnsutil/host_test.go
similarity index 100%
rename from middleware/pkg/dnsutil/host_test.go
rename to plugin/pkg/dnsutil/host_test.go
diff --git a/middleware/pkg/dnsutil/join.go b/plugin/pkg/dnsutil/join.go
similarity index 100%
rename from middleware/pkg/dnsutil/join.go
rename to plugin/pkg/dnsutil/join.go
diff --git a/middleware/pkg/dnsutil/join_test.go b/plugin/pkg/dnsutil/join_test.go
similarity index 100%
rename from middleware/pkg/dnsutil/join_test.go
rename to plugin/pkg/dnsutil/join_test.go
diff --git a/middleware/pkg/dnsutil/reverse.go b/plugin/pkg/dnsutil/reverse.go
similarity index 100%
rename from middleware/pkg/dnsutil/reverse.go
rename to plugin/pkg/dnsutil/reverse.go
diff --git a/middleware/pkg/dnsutil/reverse_test.go b/plugin/pkg/dnsutil/reverse_test.go
similarity index 100%
rename from middleware/pkg/dnsutil/reverse_test.go
rename to plugin/pkg/dnsutil/reverse_test.go
diff --git a/middleware/pkg/dnsutil/zone.go b/plugin/pkg/dnsutil/zone.go
similarity index 100%
rename from middleware/pkg/dnsutil/zone.go
rename to plugin/pkg/dnsutil/zone.go
diff --git a/middleware/pkg/dnsutil/zone_test.go b/plugin/pkg/dnsutil/zone_test.go
similarity index 100%
rename from middleware/pkg/dnsutil/zone_test.go
rename to plugin/pkg/dnsutil/zone_test.go
diff --git a/middleware/pkg/edns/edns.go b/plugin/pkg/edns/edns.go
similarity index 92%
rename from middleware/pkg/edns/edns.go
rename to plugin/pkg/edns/edns.go
index 6cbe2cdae..3f0ea5e16 100644
--- a/middleware/pkg/edns/edns.go
+++ b/plugin/pkg/edns/edns.go
@@ -8,7 +8,7 @@ import (
 )
 
 // Version checks the EDNS version in the request. If error
-// is nil everything is OK and we can invoke the middleware. If non-nil, the
+// is nil everything is OK and we can invoke the plugin. If non-nil, the
 // returned Msg is valid to be returned to the client (and should). For some
 // reason this response should not contain a question RR in the question section.
 func Version(req *dns.Msg) (*dns.Msg, error) {
diff --git a/middleware/pkg/edns/edns_test.go b/plugin/pkg/edns/edns_test.go
similarity index 100%
rename from middleware/pkg/edns/edns_test.go
rename to plugin/pkg/edns/edns_test.go
diff --git a/middleware/pkg/healthcheck/healthcheck.go b/plugin/pkg/healthcheck/healthcheck.go
similarity index 100%
rename from middleware/pkg/healthcheck/healthcheck.go
rename to plugin/pkg/healthcheck/healthcheck.go
diff --git a/middleware/pkg/healthcheck/policy.go b/plugin/pkg/healthcheck/policy.go
similarity index 100%
rename from middleware/pkg/healthcheck/policy.go
rename to plugin/pkg/healthcheck/policy.go
diff --git a/middleware/pkg/healthcheck/policy_test.go b/plugin/pkg/healthcheck/policy_test.go
similarity index 100%
rename from middleware/pkg/healthcheck/policy_test.go
rename to plugin/pkg/healthcheck/policy_test.go
diff --git a/middleware/pkg/nonwriter/nonwriter.go b/plugin/pkg/nonwriter/nonwriter.go
similarity index 100%
rename from middleware/pkg/nonwriter/nonwriter.go
rename to plugin/pkg/nonwriter/nonwriter.go
diff --git a/middleware/pkg/nonwriter/nonwriter_test.go b/plugin/pkg/nonwriter/nonwriter_test.go
similarity index 100%
rename from middleware/pkg/nonwriter/nonwriter_test.go
rename to plugin/pkg/nonwriter/nonwriter_test.go
diff --git a/middleware/pkg/rcode/rcode.go b/plugin/pkg/rcode/rcode.go
similarity index 100%
rename from middleware/pkg/rcode/rcode.go
rename to plugin/pkg/rcode/rcode.go
diff --git a/middleware/pkg/rcode/rcode_test.go b/plugin/pkg/rcode/rcode_test.go
similarity index 100%
rename from middleware/pkg/rcode/rcode_test.go
rename to plugin/pkg/rcode/rcode_test.go
diff --git a/middleware/pkg/replacer/replacer.go b/plugin/pkg/replacer/replacer.go
similarity index 98%
rename from middleware/pkg/replacer/replacer.go
rename to plugin/pkg/replacer/replacer.go
index 91f17e17c..fc98e5d29 100644
--- a/middleware/pkg/replacer/replacer.go
+++ b/plugin/pkg/replacer/replacer.go
@@ -5,7 +5,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/pkg/replacer/replacer_test.go b/plugin/pkg/replacer/replacer_test.go
similarity index 93%
rename from middleware/pkg/replacer/replacer_test.go
rename to plugin/pkg/replacer/replacer_test.go
index a72f429a8..95c3bbd52 100644
--- a/middleware/pkg/replacer/replacer_test.go
+++ b/plugin/pkg/replacer/replacer_test.go
@@ -3,8 +3,8 @@ package replacer
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/pkg/response/classify.go b/plugin/pkg/response/classify.go
similarity index 100%
rename from middleware/pkg/response/classify.go
rename to plugin/pkg/response/classify.go
diff --git a/middleware/pkg/response/typify.go b/plugin/pkg/response/typify.go
similarity index 100%
rename from middleware/pkg/response/typify.go
rename to plugin/pkg/response/typify.go
diff --git a/middleware/pkg/response/typify_test.go b/plugin/pkg/response/typify_test.go
similarity index 98%
rename from middleware/pkg/response/typify_test.go
rename to plugin/pkg/response/typify_test.go
index 738c6066d..faeaf3579 100644
--- a/middleware/pkg/response/typify_test.go
+++ b/plugin/pkg/response/typify_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/pkg/singleflight/singleflight.go b/plugin/pkg/singleflight/singleflight.go
similarity index 100%
rename from middleware/pkg/singleflight/singleflight.go
rename to plugin/pkg/singleflight/singleflight.go
diff --git a/middleware/pkg/singleflight/singleflight_test.go b/plugin/pkg/singleflight/singleflight_test.go
similarity index 100%
rename from middleware/pkg/singleflight/singleflight_test.go
rename to plugin/pkg/singleflight/singleflight_test.go
diff --git a/middleware/pkg/tls/tls.go b/plugin/pkg/tls/tls.go
similarity index 100%
rename from middleware/pkg/tls/tls.go
rename to plugin/pkg/tls/tls.go
diff --git a/middleware/pkg/tls/tls_test.go b/plugin/pkg/tls/tls_test.go
similarity index 97%
rename from middleware/pkg/tls/tls_test.go
rename to plugin/pkg/tls/tls_test.go
index 408469045..8c88bfcc4 100644
--- a/middleware/pkg/tls/tls_test.go
+++ b/plugin/pkg/tls/tls_test.go
@@ -4,7 +4,7 @@ import (
 	"path/filepath"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 )
 
 func getPEMFiles(t *testing.T) (rmFunc func(), cert, key, ca string) {
diff --git a/middleware/pkg/trace/trace.go b/plugin/pkg/trace/trace.go
similarity index 72%
rename from middleware/pkg/trace/trace.go
rename to plugin/pkg/trace/trace.go
index e4858942b..35a8ddabd 100644
--- a/middleware/pkg/trace/trace.go
+++ b/plugin/pkg/trace/trace.go
@@ -1,12 +1,12 @@
 package trace
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	ot "github.com/opentracing/opentracing-go"
 )
 
 // Trace holds the tracer and endpoint info
 type Trace interface {
-	middleware.Handler
+	plugin.Handler
 	Tracer() ot.Tracer
 }
diff --git a/middleware/middleware.go b/plugin/plugin.go
similarity index 83%
rename from middleware/middleware.go
rename to plugin/plugin.go
index 9e236c6e0..0c4d7f604 100644
--- a/middleware/middleware.go
+++ b/plugin/plugin.go
@@ -1,5 +1,5 @@
-// Package middleware provides some types and functions common among middleware.
-package middleware
+// Package plugin provides some types and functions common among plugin.
+package plugin
 
 import (
 	"errors"
@@ -11,10 +11,10 @@ import (
 )
 
 type (
-	// Middleware is the middle layer which represents the traditional
-	// idea of middleware: it chains one Handler to the next by being
+	// Plugin is a middle layer which represents the traditional
+	// idea of plugin: it chains one Handler to the next by being
 	// passed the next Handler in the chain.
-	Middleware func(Handler) Handler
+	Plugin func(Handler) Handler
 
 	// Handler is like dns.Handler except ServeDNS may return an rcode
 	// and/or error.
@@ -35,7 +35,7 @@ type (
 	// already written, and that they should not write to it also.
 	//
 	// If ServeDNS encounters an error, it should return the error value
-	// so it can be logged by designated error-handling middleware.
+	// so it can be logged by designated error-handling plugin.
 	//
 	// If writing a response after calling another ServeDNS method, the
 	// returned rcode SHOULD be used when writing the response.
@@ -43,7 +43,7 @@ type (
 	// If handling errors after calling another ServeDNS method, the
 	// returned error value SHOULD be logged or handled accordingly.
 	//
-	// Otherwise, return values should be propagated down the middleware
+	// Otherwise, return values should be propagated down the plugin
 	// chain by returning them unchanged.
 	Handler interface {
 		ServeDNS(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
@@ -64,8 +64,8 @@ func (f HandlerFunc) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.
 // Name implements the Handler interface.
 func (f HandlerFunc) Name() string { return "handlerfunc" }
 
-// Error returns err with 'middleware/name: ' prefixed to it.
-func Error(name string, err error) error { return fmt.Errorf("%s/%s: %s", "middleware", name, err) }
+// Error returns err with 'plugin/name: ' prefixed to it.
+func Error(name string, err error) error { return fmt.Errorf("%s/%s: %s", "plugin", name, err) }
 
 // NextOrFailure calls next.ServeDNS when next is not nill, otherwise it will return, a ServerFailure
 // and a nil error.
@@ -79,11 +79,11 @@ func NextOrFailure(name string, next Handler, ctx context.Context, w dns.Respons
 		return next.ServeDNS(ctx, w, r)
 	}
 
-	return dns.RcodeServerFailure, Error(name, errors.New("no next middleware found"))
+	return dns.RcodeServerFailure, Error(name, errors.New("no next plugin found"))
 }
 
 // ClientWrite returns true if the response has been written to the client.
-// Each middleware to adhire to this protocol.
+// Each plugin to adhire to this protocol.
 func ClientWrite(rcode int) bool {
 	switch rcode {
 	case dns.RcodeServerFailure:
diff --git a/plugin/plugin_test.go b/plugin/plugin_test.go
new file mode 100644
index 000000000..b0736c3a0
--- /dev/null
+++ b/plugin/plugin_test.go
@@ -0,0 +1 @@
+package plugin
diff --git a/middleware/pprof/README.md b/plugin/pprof/README.md
similarity index 100%
rename from middleware/pprof/README.md
rename to plugin/pprof/README.md
diff --git a/middleware/pprof/pprof.go b/plugin/pprof/pprof.go
similarity index 100%
rename from middleware/pprof/pprof.go
rename to plugin/pprof/pprof.go
diff --git a/middleware/pprof/setup.go b/plugin/pprof/setup.go
similarity index 75%
rename from middleware/pprof/setup.go
rename to plugin/pprof/setup.go
index f94eef710..22b82e94b 100644
--- a/middleware/pprof/setup.go
+++ b/plugin/pprof/setup.go
@@ -4,7 +4,7 @@ import (
 	"net"
 	"sync"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -23,7 +23,7 @@ func setup(c *caddy.Controller) error {
 	h := &handler{addr: defaultAddr}
 	for c.Next() {
 		if found {
-			return middleware.Error("pprof", c.Err("pprof can only be specified once"))
+			return plugin.Error("pprof", c.Err("pprof can only be specified once"))
 		}
 		args := c.RemainingArgs()
 		if len(args) == 1 {
@@ -34,10 +34,10 @@ func setup(c *caddy.Controller) error {
 			}
 		}
 		if len(args) > 1 {
-			return middleware.Error("pprof", c.ArgErr())
+			return plugin.Error("pprof", c.ArgErr())
 		}
 		if c.NextBlock() {
-			return middleware.Error("pprof", c.ArgErr())
+			return plugin.Error("pprof", c.ArgErr())
 		}
 		found = true
 	}
diff --git a/middleware/pprof/setup_test.go b/plugin/pprof/setup_test.go
similarity index 100%
rename from middleware/pprof/setup_test.go
rename to plugin/pprof/setup_test.go
diff --git a/middleware/proxy/README.md b/plugin/proxy/README.md
similarity index 97%
rename from middleware/proxy/README.md
rename to plugin/proxy/README.md
index 17a43f68e..3cccf05ee 100644
--- a/middleware/proxy/README.md
+++ b/plugin/proxy/README.md
@@ -3,7 +3,7 @@
 *proxy* facilitates both a basic reverse proxy and a robust load balancer.
 
 The proxy has support for multiple backends. The load balancing features include multiple policies,
-health checks, and failovers. If all hosts fail their health check the proxy middleware will fail
+health checks, and failovers. If all hosts fail their health check the proxy plugin will fail
 back to randomly selecting a target and sending packets to it.
 
 ## Syntax
@@ -53,7 +53,7 @@ proxy FROM TO... {
   old DNS, and `https_google` uses `https://dns.google.com` and speaks a JSON DNS dialect. Note when
   using this **TO** will be ignored. The `grpc` option will talk to a server that has implemented
   the [DnsService](https://github.com/coredns/coredns/pb/dns.proto).
-  An out-of-tree middleware that implements the server side of this can be found at
+  An out-of-tree plugin that implements the server side of this can be found at
   [here](https://github.com/infobloxopen/coredns-grpc).
 
 ## Policies
@@ -91,7 +91,7 @@ payload over HTTPS). Note that with `https_google` the entire transport is encry
   * **KEY** **CERT** **CACERT** - Client authentication is used with the specified key/cert pair. The
     server certificate is verified using the **CACERT** file.
 
-  An out-of-tree middleware that implements the server side of this can be found at
+  An out-of-tree plugin that implements the server side of this can be found at
   [here](https://github.com/infobloxopen/coredns-grpc).
 
 ## Metrics
diff --git a/middleware/proxy/dns.go b/plugin/proxy/dns.go
similarity index 100%
rename from middleware/proxy/dns.go
rename to plugin/proxy/dns.go
diff --git a/middleware/proxy/dnstap_test.go b/plugin/proxy/dnstap_test.go
similarity index 90%
rename from middleware/proxy/dnstap_test.go
rename to plugin/proxy/dnstap_test.go
index b3c31c207..05169a1ca 100644
--- a/middleware/proxy/dnstap_test.go
+++ b/plugin/proxy/dnstap_test.go
@@ -3,9 +3,9 @@ package proxy
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/dnstap/msg"
-	"github.com/coredns/coredns/middleware/dnstap/test"
-	mwtest "github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
+	"github.com/coredns/coredns/plugin/dnstap/test"
+	mwtest "github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	tap "github.com/dnstap/golang-dnstap"
diff --git a/middleware/proxy/exchanger.go b/plugin/proxy/exchanger.go
similarity index 100%
rename from middleware/proxy/exchanger.go
rename to plugin/proxy/exchanger.go
diff --git a/middleware/proxy/google.go b/plugin/proxy/google.go
similarity index 98%
rename from middleware/proxy/google.go
rename to plugin/proxy/google.go
index b7e605fcb..ecc5e6dfd 100644
--- a/middleware/proxy/google.go
+++ b/plugin/proxy/google.go
@@ -13,7 +13,7 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/proxy/google_rr.go b/plugin/proxy/google_rr.go
similarity index 100%
rename from middleware/proxy/google_rr.go
rename to plugin/proxy/google_rr.go
diff --git a/middleware/proxy/google_test.go b/plugin/proxy/google_test.go
similarity index 100%
rename from middleware/proxy/google_test.go
rename to plugin/proxy/google_test.go
diff --git a/middleware/proxy/grpc.go b/plugin/proxy/grpc.go
similarity index 94%
rename from middleware/proxy/grpc.go
rename to plugin/proxy/grpc.go
index 8aabf0eb0..f98fd2e91 100644
--- a/middleware/proxy/grpc.go
+++ b/plugin/proxy/grpc.go
@@ -5,8 +5,8 @@ import (
 	"crypto/tls"
 	"log"
 
-	"github.com/coredns/coredns/middleware/pkg/trace"
 	"github.com/coredns/coredns/pb"
+	"github.com/coredns/coredns/plugin/pkg/trace"
 	"github.com/coredns/coredns/request"
 
 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc"
@@ -80,7 +80,7 @@ func (g *grpcClient) OnStartup(p *Proxy) error {
 			intercept := otgrpc.OpenTracingClientInterceptor(t.Tracer(), otgrpc.IncludingSpans(onlyIfParent))
 			dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(intercept))
 		} else {
-			log.Printf("[WARNING] Wrong type for trace middleware reference: %s", p.Trace)
+			log.Printf("[WARNING] Wrong type for trace plugin reference: %s", p.Trace)
 		}
 	}
 	for _, host := range g.upstream.Hosts {
diff --git a/middleware/proxy/grpc_test.go b/plugin/proxy/grpc_test.go
similarity index 96%
rename from middleware/proxy/grpc_test.go
rename to plugin/proxy/grpc_test.go
index dcde7cc0e..52c5737d6 100644
--- a/middleware/proxy/grpc_test.go
+++ b/plugin/proxy/grpc_test.go
@@ -4,7 +4,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
 
 	"google.golang.org/grpc/grpclog"
 )
diff --git a/middleware/proxy/lookup.go b/plugin/proxy/lookup.go
similarity index 95%
rename from middleware/proxy/lookup.go
rename to plugin/proxy/lookup.go
index 1963e7dbd..9be62edd5 100644
--- a/middleware/proxy/lookup.go
+++ b/plugin/proxy/lookup.go
@@ -1,6 +1,6 @@
 package proxy
 
-// functions other middleware might want to use to do lookup in the same style as the proxy.
+// functions other plugin might want to use to do lookup in the same style as the proxy.
 
 import (
 	"context"
@@ -8,7 +8,7 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/middleware/proxy/metrics.go b/plugin/proxy/metrics.go
similarity index 85%
rename from middleware/proxy/metrics.go
rename to plugin/proxy/metrics.go
index e9bb48d6f..893c26d6b 100644
--- a/middleware/proxy/metrics.go
+++ b/plugin/proxy/metrics.go
@@ -3,15 +3,15 @@ package proxy
 import (
 	"sync"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/prometheus/client_golang/prometheus"
 )
 
-// Metrics the proxy middleware exports.
+// Metrics the proxy plugin exports.
 var (
 	RequestDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
-		Namespace: middleware.Namespace,
+		Namespace: plugin.Namespace,
 		Subsystem: "proxy",
 		Name:      "request_duration_milliseconds",
 		Buckets:   append(prometheus.DefBuckets, []float64{50, 100, 200, 500, 1000, 2000, 3000, 4000, 5000, 10000}...),
diff --git a/middleware/proxy/proxy.go b/plugin/proxy/proxy.go
similarity index 87%
rename from middleware/proxy/proxy.go
rename to plugin/proxy/proxy.go
index 2a3c8002d..9d1e1906b 100644
--- a/middleware/proxy/proxy.go
+++ b/plugin/proxy/proxy.go
@@ -1,4 +1,4 @@
-// Package proxy is middleware that proxies requests.
+// Package proxy is plugin that proxies requests.
 package proxy
 
 import (
@@ -7,10 +7,10 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/dnstap"
-	"github.com/coredns/coredns/middleware/dnstap/msg"
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/dnstap"
+	"github.com/coredns/coredns/plugin/dnstap/msg"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
 	"github.com/coredns/coredns/request"
 
 	tap "github.com/dnstap/golang-dnstap"
@@ -25,18 +25,18 @@ var (
 	errInvalidDomain   = errors.New("invalid path for proxy")
 )
 
-// Proxy represents a middleware instance that can proxy requests to another (DNS) server.
+// Proxy represents a plugin instance that can proxy requests to another (DNS) server.
 type Proxy struct {
-	Next middleware.Handler
+	Next plugin.Handler
 
 	// Upstreams is a pointer to a slice, so we can update the upstream (used for Google)
 	// midway.
 
 	Upstreams *[]Upstream
 
-	// Trace is the Trace middleware, if it is installed
+	// Trace is the Trace plugin, if it is installed
 	// This is used by the grpc exchanger to trace through the grpc calls
-	Trace middleware.Handler
+	Trace plugin.Handler
 }
 
 // Upstream manages a pool of proxy upstream hosts. Select should return a
@@ -58,7 +58,7 @@ type Upstream interface {
 // immediate retries until this duration ends or we get a nil host.
 var tryDuration = 60 * time.Second
 
-// ServeDNS satisfies the middleware.Handler interface.
+// ServeDNS satisfies the plugin.Handler interface.
 func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	var span, child ot.Span
 	span = ot.SpanFromContext(ctx)
@@ -66,7 +66,7 @@ func (p Proxy) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
 
 	upstream := p.match(state)
 	if upstream == nil {
-		return middleware.NextOrFailure(p.Name(), p.Next, ctx, w, r)
+		return plugin.NextOrFailure(p.Name(), p.Next, ctx, w, r)
 	}
 
 	for {
@@ -138,7 +138,7 @@ func (p Proxy) match(state request.Request) (u Upstream) {
 	for _, upstream := range *p.Upstreams {
 		from := upstream.From()
 
-		if !middleware.Name(from).Matches(state.Name()) || !upstream.IsAllowedDomain(state.Name()) {
+		if !plugin.Name(from).Matches(state.Name()) || !upstream.IsAllowedDomain(state.Name()) {
 			continue
 		}
 
diff --git a/middleware/proxy/proxy_test.go b/plugin/proxy/proxy_test.go
similarity index 100%
rename from middleware/proxy/proxy_test.go
rename to plugin/proxy/proxy_test.go
diff --git a/middleware/proxy/response.go b/plugin/proxy/response.go
similarity index 100%
rename from middleware/proxy/response.go
rename to plugin/proxy/response.go
diff --git a/middleware/proxy/setup.go b/plugin/proxy/setup.go
similarity index 81%
rename from middleware/proxy/setup.go
rename to plugin/proxy/setup.go
index d55065734..bbe65c35d 100644
--- a/middleware/proxy/setup.go
+++ b/plugin/proxy/setup.go
@@ -2,7 +2,7 @@ package proxy
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -17,12 +17,12 @@ func init() {
 func setup(c *caddy.Controller) error {
 	upstreams, err := NewStaticUpstreams(&c.Dispenser)
 	if err != nil {
-		return middleware.Error("proxy", err)
+		return plugin.Error("proxy", err)
 	}
 
 	t := dnsserver.GetConfig(c).Handler("trace")
 	P := &Proxy{Trace: t}
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		P.Next = next
 		P.Upstreams = &upstreams
 		return P
diff --git a/middleware/proxy/upstream.go b/plugin/proxy/upstream.go
similarity index 91%
rename from middleware/proxy/upstream.go
rename to plugin/proxy/upstream.go
index 677b8e2fc..b60b6ff58 100644
--- a/middleware/proxy/upstream.go
+++ b/plugin/proxy/upstream.go
@@ -7,10 +7,10 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/pkg/healthcheck"
-	"github.com/coredns/coredns/middleware/pkg/tls"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/pkg/healthcheck"
+	"github.com/coredns/coredns/plugin/pkg/tls"
 	"github.com/mholt/caddy/caddyfile"
 	"github.com/miekg/dns"
 )
@@ -26,7 +26,7 @@ type staticUpstream struct {
 }
 
 // NewStaticUpstreams parses the configuration input and sets up
-// static upstreams for the proxy middleware.
+// static upstreams for the proxy plugin.
 func NewStaticUpstreams(c *caddyfile.Dispenser) ([]Upstream, error) {
 	var upstreams []Upstream
 	for c.Next() {
@@ -43,7 +43,7 @@ func NewStaticUpstreams(c *caddyfile.Dispenser) ([]Upstream, error) {
 		if !c.Args(&upstream.from) {
 			return upstreams, c.ArgErr()
 		}
-		upstream.from = middleware.Host(upstream.from).Normalize()
+		upstream.from = plugin.Host(upstream.from).Normalize()
 
 		to := c.RemainingArgs()
 		if len(to) == 0 {
@@ -169,7 +169,7 @@ func parseBlock(c *caddyfile.Dispenser, u *staticUpstream) error {
 			return c.ArgErr()
 		}
 		for i := 0; i < len(ignoredDomains); i++ {
-			ignoredDomains[i] = middleware.Host(ignoredDomains[i]).Normalize()
+			ignoredDomains[i] = plugin.Host(ignoredDomains[i]).Normalize()
 		}
 		u.IgnoredSubDomains = ignoredDomains
 	case "spray":
@@ -224,7 +224,7 @@ func (u *staticUpstream) IsAllowedDomain(name string) bool {
 	}
 
 	for _, ignoredSubDomain := range u.IgnoredSubDomains {
-		if middleware.Name(ignoredSubDomain).Matches(name) {
+		if plugin.Name(ignoredSubDomain).Matches(name) {
 			return false
 		}
 	}
diff --git a/middleware/proxy/upstream_test.go b/plugin/proxy/upstream_test.go
similarity index 99%
rename from middleware/proxy/upstream_test.go
rename to plugin/proxy/upstream_test.go
index 3ee225c2d..42d50cac3 100644
--- a/middleware/proxy/upstream_test.go
+++ b/plugin/proxy/upstream_test.go
@@ -5,7 +5,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/mholt/caddy"
 )
diff --git a/middleware/reverse/README.md b/plugin/reverse/README.md
similarity index 94%
rename from middleware/reverse/README.md
rename to plugin/reverse/README.md
index 2bc4b2e1d..63a3a968c 100644
--- a/middleware/reverse/README.md
+++ b/plugin/reverse/README.md
@@ -1,6 +1,6 @@
 # reverse
 
-The *reverse* middleware allows CoreDNS to respond dynamically to a PTR request and the related A/AAAA request.
+The *reverse* plugin allows CoreDNS to respond dynamically to a PTR request and the related A/AAAA request.
 
 ## Syntax
 
@@ -15,7 +15,7 @@ reverse NETWORK... {
 * **NETWORK** one or more CIDR formatted networks to respond on.
 * `hostname` injects the IP and zone to a template for the hostname. Defaults to "ip-{IP}.{zone[1]}". See below for template.
 * `ttl` defaults to 60
-* `fallthrough` if zone matches and no record can be generated, pass request to the next middleware.
+* `fallthrough` if zone matches and no record can be generated, pass request to the next plugin.
 * `wildcard` allows matches to catch all subdomains as well.
 
 ### Template Syntax
diff --git a/middleware/reverse/network.go b/plugin/reverse/network.go
similarity index 100%
rename from middleware/reverse/network.go
rename to plugin/reverse/network.go
diff --git a/middleware/reverse/network_test.go b/plugin/reverse/network_test.go
similarity index 100%
rename from middleware/reverse/network_test.go
rename to plugin/reverse/network_test.go
diff --git a/middleware/reverse/reverse.go b/plugin/reverse/reverse.go
similarity index 89%
rename from middleware/reverse/reverse.go
rename to plugin/reverse/reverse.go
index eb14ae155..7d7681867 100644
--- a/middleware/reverse/reverse.go
+++ b/plugin/reverse/reverse.go
@@ -3,8 +3,8 @@ package reverse
 import (
 	"net"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
@@ -13,12 +13,12 @@ import (
 
 // Reverse provides dynamic reverse DNS and the related forward RR.
 type Reverse struct {
-	Next        middleware.Handler
+	Next        plugin.Handler
 	Networks    networks
 	Fallthrough bool
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (re Reverse) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	var rr dns.RR
 
@@ -98,7 +98,7 @@ func (re Reverse) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
 	}
 
 	if re.Fallthrough {
-		return middleware.NextOrFailure(re.Name(), re.Next, ctx, w, r)
+		return plugin.NextOrFailure(re.Name(), re.Next, ctx, w, r)
 	}
 	return dns.RcodeServerFailure, nil
 }
diff --git a/middleware/reverse/reverse_test.go b/plugin/reverse/reverse_test.go
similarity index 89%
rename from middleware/reverse/reverse_test.go
rename to plugin/reverse/reverse_test.go
index 4b17f0971..c7a7fea6c 100644
--- a/middleware/reverse/reverse_test.go
+++ b/plugin/reverse/reverse_test.go
@@ -5,9 +5,9 @@ import (
 	"regexp"
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -28,7 +28,7 @@ func TestReverse(t *testing.T) {
 	}
 
 	tests := []struct {
-		next          middleware.Handler
+		next          plugin.Handler
 		qname         string
 		qtype         uint16
 		expectedCode  int
diff --git a/middleware/reverse/setup.go b/plugin/reverse/setup.go
similarity index 93%
rename from middleware/reverse/setup.go
rename to plugin/reverse/setup.go
index 8d8cc6548..26e21eea9 100644
--- a/middleware/reverse/setup.go
+++ b/plugin/reverse/setup.go
@@ -8,7 +8,7 @@ import (
 	"strings"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -23,10 +23,10 @@ func init() {
 func setupReverse(c *caddy.Controller) error {
 	networks, fallThrough, err := reverseParse(c)
 	if err != nil {
-		return middleware.Error("reverse", err)
+		return plugin.Error("reverse", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Reverse{Next: next, Networks: networks, Fallthrough: fallThrough}
 	})
 
@@ -39,7 +39,7 @@ func reverseParse(c *caddy.Controller) (nets networks, fall bool, err error) {
 
 	// We copy from the serverblock, these contains Hosts.
 	for i, str := range c.ServerBlockKeys {
-		zones[i] = middleware.Host(str).Normalize()
+		zones[i] = plugin.Host(str).Normalize()
 	}
 
 	for c.Next() {
diff --git a/middleware/reverse/setup_test.go b/plugin/reverse/setup_test.go
similarity index 100%
rename from middleware/reverse/setup_test.go
rename to plugin/reverse/setup_test.go
diff --git a/middleware/rewrite/README.md b/plugin/rewrite/README.md
similarity index 100%
rename from middleware/rewrite/README.md
rename to plugin/rewrite/README.md
diff --git a/middleware/rewrite/class.go b/plugin/rewrite/class.go
similarity index 100%
rename from middleware/rewrite/class.go
rename to plugin/rewrite/class.go
diff --git a/middleware/rewrite/condition.go b/plugin/rewrite/condition.go
similarity index 98%
rename from middleware/rewrite/condition.go
rename to plugin/rewrite/condition.go
index d4a54d44a..2f20d71aa 100644
--- a/middleware/rewrite/condition.go
+++ b/plugin/rewrite/condition.go
@@ -5,7 +5,7 @@ import (
 	"regexp"
 	"strings"
 
-	"github.com/coredns/coredns/middleware/pkg/replacer"
+	"github.com/coredns/coredns/plugin/pkg/replacer"
 
 	"github.com/miekg/dns"
 )
diff --git a/middleware/rewrite/condition_test.go b/plugin/rewrite/condition_test.go
similarity index 100%
rename from middleware/rewrite/condition_test.go
rename to plugin/rewrite/condition_test.go
diff --git a/middleware/rewrite/edns0.go b/plugin/rewrite/edns0.go
similarity index 99%
rename from middleware/rewrite/edns0.go
rename to plugin/rewrite/edns0.go
index bdfcac6fd..d8b6f4128 100644
--- a/middleware/rewrite/edns0.go
+++ b/plugin/rewrite/edns0.go
@@ -1,4 +1,4 @@
-// Package rewrite is middleware for rewriting requests internally to something different.
+// Package rewrite is plugin for rewriting requests internally to something different.
 package rewrite
 
 import (
diff --git a/middleware/rewrite/name.go b/plugin/rewrite/name.go
similarity index 74%
rename from middleware/rewrite/name.go
rename to plugin/rewrite/name.go
index 6233197d6..189133542 100644
--- a/middleware/rewrite/name.go
+++ b/plugin/rewrite/name.go
@@ -1,7 +1,7 @@
 package rewrite
 
 import (
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/miekg/dns"
 )
@@ -11,7 +11,7 @@ type nameRule struct {
 }
 
 func newNameRule(from, to string) (Rule, error) {
-	return &nameRule{middleware.Name(from).Normalize(), middleware.Name(to).Normalize()}, nil
+	return &nameRule{plugin.Name(from).Normalize(), plugin.Name(to).Normalize()}, nil
 }
 
 // Rewrite rewrites the the current request.
diff --git a/middleware/rewrite/reverter.go b/plugin/rewrite/reverter.go
similarity index 100%
rename from middleware/rewrite/reverter.go
rename to plugin/rewrite/reverter.go
diff --git a/middleware/rewrite/rewrite.go b/plugin/rewrite/rewrite.go
similarity index 81%
rename from middleware/rewrite/rewrite.go
rename to plugin/rewrite/rewrite.go
index 44e8e43c7..d4931445c 100644
--- a/middleware/rewrite/rewrite.go
+++ b/plugin/rewrite/rewrite.go
@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"strings"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/miekg/dns"
 
@@ -24,23 +24,23 @@ const (
 	RewriteStatus
 )
 
-// Rewrite is middleware to rewrite requests internally before being handled.
+// Rewrite is plugin to rewrite requests internally before being handled.
 type Rewrite struct {
-	Next     middleware.Handler
+	Next     plugin.Handler
 	Rules    []Rule
 	noRevert bool
 }
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (rw Rewrite) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	wr := NewResponseReverter(w, r)
 	for _, rule := range rw.Rules {
 		switch result := rule.Rewrite(w, r); result {
 		case RewriteDone:
 			if rw.noRevert {
-				return middleware.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
+				return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
 			}
-			return middleware.NextOrFailure(rw.Name(), rw.Next, ctx, wr, r)
+			return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, wr, r)
 		case RewriteIgnored:
 			break
 		case RewriteStatus:
@@ -50,7 +50,7 @@ func (rw Rewrite) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
 			// }
 		}
 	}
-	return middleware.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
+	return plugin.NextOrFailure(rw.Name(), rw.Next, ctx, w, r)
 }
 
 // Name implements the Handler interface.
diff --git a/middleware/rewrite/rewrite_test.go b/plugin/rewrite/rewrite_test.go
similarity index 97%
rename from middleware/rewrite/rewrite_test.go
rename to plugin/rewrite/rewrite_test.go
index 39648711e..74a8594df 100644
--- a/middleware/rewrite/rewrite_test.go
+++ b/plugin/rewrite/rewrite_test.go
@@ -5,9 +5,9 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
@@ -114,7 +114,7 @@ func TestRewrite(t *testing.T) {
 	rules = append(rules, r)
 
 	rw := Rewrite{
-		Next:     middleware.HandlerFunc(msgPrinter),
+		Next:     plugin.HandlerFunc(msgPrinter),
 		Rules:    rules,
 		noRevert: true,
 	}
@@ -161,7 +161,7 @@ func TestRewrite(t *testing.T) {
 
 func TestRewriteEDNS0Local(t *testing.T) {
 	rw := Rewrite{
-		Next:     middleware.HandlerFunc(msgPrinter),
+		Next:     plugin.HandlerFunc(msgPrinter),
 		noRevert: true,
 	}
 
@@ -238,7 +238,7 @@ func TestEdns0LocalMultiRule(t *testing.T) {
 	rules = append(rules, r)
 
 	rw := Rewrite{
-		Next:     middleware.HandlerFunc(msgPrinter),
+		Next:     plugin.HandlerFunc(msgPrinter),
 		Rules:    rules,
 		noRevert: true,
 	}
@@ -343,7 +343,7 @@ func optsEqual(a, b []dns.EDNS0) bool {
 
 func TestRewriteEDNS0LocalVariable(t *testing.T) {
 	rw := Rewrite{
-		Next:     middleware.HandlerFunc(msgPrinter),
+		Next:     plugin.HandlerFunc(msgPrinter),
 		noRevert: true,
 	}
 
@@ -423,7 +423,7 @@ func TestRewriteEDNS0LocalVariable(t *testing.T) {
 
 func TestRewriteEDNS0Subnet(t *testing.T) {
 	rw := Rewrite{
-		Next:     middleware.HandlerFunc(msgPrinter),
+		Next:     plugin.HandlerFunc(msgPrinter),
 		noRevert: true,
 	}
 
diff --git a/middleware/rewrite/setup.go b/plugin/rewrite/setup.go
similarity index 78%
rename from middleware/rewrite/setup.go
rename to plugin/rewrite/setup.go
index 156129f70..5954a3300 100644
--- a/middleware/rewrite/setup.go
+++ b/plugin/rewrite/setup.go
@@ -2,7 +2,7 @@ package rewrite
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -17,10 +17,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	rewrites, err := rewriteParse(c)
 	if err != nil {
-		return middleware.Error("rewrite", err)
+		return plugin.Error("rewrite", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Rewrite{Next: next, Rules: rewrites}
 	})
 
diff --git a/middleware/rewrite/setup_test.go b/plugin/rewrite/setup_test.go
similarity index 100%
rename from middleware/rewrite/setup_test.go
rename to plugin/rewrite/setup_test.go
diff --git a/middleware/rewrite/testdata/testdir/empty b/plugin/rewrite/testdata/testdir/empty
similarity index 100%
rename from middleware/rewrite/testdata/testdir/empty
rename to plugin/rewrite/testdata/testdir/empty
diff --git a/middleware/rewrite/testdata/testfile b/plugin/rewrite/testdata/testfile
similarity index 100%
rename from middleware/rewrite/testdata/testfile
rename to plugin/rewrite/testdata/testfile
diff --git a/middleware/rewrite/type.go b/plugin/rewrite/type.go
similarity index 90%
rename from middleware/rewrite/type.go
rename to plugin/rewrite/type.go
index 58eedd51e..ae3efcc5a 100644
--- a/middleware/rewrite/type.go
+++ b/plugin/rewrite/type.go
@@ -1,4 +1,4 @@
-// Package rewrite is middleware for rewriting requests internally to something different.
+// Package rewrite is plugin for rewriting requests internally to something different.
 package rewrite
 
 import (
diff --git a/middleware/root/README.md b/plugin/root/README.md
similarity index 81%
rename from middleware/root/README.md
rename to plugin/root/README.md
index 23d35b2d3..bd3fe33b3 100644
--- a/middleware/root/README.md
+++ b/plugin/root/README.md
@@ -15,7 +15,7 @@ root PATH
 
 ## Examples
 
-Serve zone data (when the *file* middleware is used) from `/etc/coredns/zones`:
+Serve zone data (when the *file* plugin is used) from `/etc/coredns/zones`:
 
 ~~~ txt
 root /etc/coredns/zones
diff --git a/middleware/root/root.go b/plugin/root/root.go
similarity index 77%
rename from middleware/root/root.go
rename to plugin/root/root.go
index d03ecb8a4..56fd42c01 100644
--- a/middleware/root/root.go
+++ b/plugin/root/root.go
@@ -5,7 +5,7 @@ import (
 	"os"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -22,7 +22,7 @@ func setup(c *caddy.Controller) error {
 
 	for c.Next() {
 		if !c.NextArg() {
-			return middleware.Error("root", c.ArgErr())
+			return plugin.Error("root", c.ArgErr())
 		}
 		config.Root = c.Val()
 	}
@@ -35,7 +35,7 @@ func setup(c *caddy.Controller) error {
 			// But make sure the user knows!
 			log.Printf("[WARNING] Root path does not exist: %s", config.Root)
 		} else {
-			return middleware.Error("root", c.Errf("unable to access root path '%s': %v", config.Root, err))
+			return plugin.Error("root", c.Errf("unable to access root path '%s': %v", config.Root, err))
 		}
 	}
 
diff --git a/middleware/root/root_test.go b/plugin/root/root_test.go
similarity index 100%
rename from middleware/root/root_test.go
rename to plugin/root/root_test.go
diff --git a/middleware/secondary/README.md b/plugin/secondary/README.md
similarity index 100%
rename from middleware/secondary/README.md
rename to plugin/secondary/README.md
diff --git a/plugin/secondary/secondary.go b/plugin/secondary/secondary.go
new file mode 100644
index 000000000..43934e80c
--- /dev/null
+++ b/plugin/secondary/secondary.go
@@ -0,0 +1,10 @@
+// Package secondary implements a secondary plugin.
+package secondary
+
+import "github.com/coredns/coredns/plugin/file"
+
+// Secondary implements a secondary plugin that allows CoreDNS to retrieve (via AXFR)
+// zone information from a primary server.
+type Secondary struct {
+	file.File
+}
diff --git a/middleware/secondary/setup.go b/plugin/secondary/setup.go
similarity index 84%
rename from middleware/secondary/setup.go
rename to plugin/secondary/setup.go
index adba86f98..e2819197d 100644
--- a/middleware/secondary/setup.go
+++ b/plugin/secondary/setup.go
@@ -2,10 +2,10 @@ package secondary
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/file"
-	"github.com/coredns/coredns/middleware/pkg/dnsutil"
-	"github.com/coredns/coredns/middleware/proxy"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/file"
+	"github.com/coredns/coredns/plugin/pkg/dnsutil"
+	"github.com/coredns/coredns/plugin/proxy"
 
 	"github.com/mholt/caddy"
 )
@@ -20,7 +20,7 @@ func init() {
 func setup(c *caddy.Controller) error {
 	zones, err := secondaryParse(c)
 	if err != nil {
-		return middleware.Error("secondary", err)
+		return plugin.Error("secondary", err)
 	}
 
 	// Add startup functions to retrieve the zone and keep it up to date.
@@ -39,7 +39,7 @@ func setup(c *caddy.Controller) error {
 		}
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Secondary{file.File{Next: next, Zones: zones}}
 	})
 
@@ -62,7 +62,7 @@ func secondaryParse(c *caddy.Controller) (file.Zones, error) {
 				origins = args
 			}
 			for i := range origins {
-				origins[i] = middleware.Host(origins[i]).Normalize()
+				origins[i] = plugin.Host(origins[i]).Normalize()
 				z[origins[i]] = file.NewZone(origins[i], "stdin")
 				names = append(names, origins[i])
 			}
diff --git a/middleware/secondary/setup_test.go b/plugin/secondary/setup_test.go
similarity index 100%
rename from middleware/secondary/setup_test.go
rename to plugin/secondary/setup_test.go
diff --git a/plugin/test/doc.go b/plugin/test/doc.go
new file mode 100644
index 000000000..75281ed8b
--- /dev/null
+++ b/plugin/test/doc.go
@@ -0,0 +1,2 @@
+// Package test contains helper functions for writing plugin tests.
+package test
diff --git a/middleware/test/file.go b/plugin/test/file.go
similarity index 100%
rename from middleware/test/file.go
rename to plugin/test/file.go
diff --git a/middleware/test/file_test.go b/plugin/test/file_test.go
similarity index 100%
rename from middleware/test/file_test.go
rename to plugin/test/file_test.go
diff --git a/middleware/test/helpers.go b/plugin/test/helpers.go
similarity index 99%
rename from middleware/test/helpers.go
rename to plugin/test/helpers.go
index 35316dd38..065cf8935 100644
--- a/middleware/test/helpers.go
+++ b/plugin/test/helpers.go
@@ -332,7 +332,7 @@ type (
 	// ServeDNS returns an rcode and an error.
 	HandlerFunc func(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
 
-	// Handler interface defines a middleware.
+	// Handler interface defines a plugin.
 	Handler interface {
 		ServeDNS(context.Context, dns.ResponseWriter, *dns.Msg) (int, error)
 		Name() string
diff --git a/middleware/test/responsewriter.go b/plugin/test/responsewriter.go
similarity index 100%
rename from middleware/test/responsewriter.go
rename to plugin/test/responsewriter.go
diff --git a/middleware/test/server.go b/plugin/test/server.go
similarity index 100%
rename from middleware/test/server.go
rename to plugin/test/server.go
diff --git a/middleware/tls/README.md b/plugin/tls/README.md
similarity index 87%
rename from middleware/tls/README.md
rename to plugin/tls/README.md
index a5c02c4c7..d2a56f793 100644
--- a/middleware/tls/README.md
+++ b/plugin/tls/README.md
@@ -7,10 +7,10 @@ CoreDNS supports queries that are encrypted using TLS (DNS over Transport Layer
 or are using gRPC (https://grpc.io/, not an IETF standard). Normally DNS traffic isn't encrypted at
 all (DNSSEC only signs resource records).
 
-The *proxy* middleware also support gRPC (`protocol gRPC`), meaning you can chain CoreDNS servers
+The *proxy* plugin also support gRPC (`protocol gRPC`), meaning you can chain CoreDNS servers
 using this protocol.
 
-The *tls* "middleware" allows you to configure the cryptographic keys that are needed for both
+The *tls* "plugin" allows you to configure the cryptographic keys that are needed for both
 DNS-over-TLS and DNS-over-gRPC. If the `tls` directive is omitted, then no encryption takes place.
 
 The gRPC protobuffer is defined in `pb/dns.proto`. It defines the proto as a simple wrapper for the
diff --git a/middleware/tls/tls.go b/plugin/tls/tls.go
similarity index 65%
rename from middleware/tls/tls.go
rename to plugin/tls/tls.go
index 55f2856c1..e0958a9aa 100644
--- a/middleware/tls/tls.go
+++ b/plugin/tls/tls.go
@@ -2,8 +2,8 @@ package tls
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
-	"github.com/coredns/coredns/middleware/pkg/tls"
+	"github.com/coredns/coredns/plugin"
+	"github.com/coredns/coredns/plugin/pkg/tls"
 
 	"github.com/mholt/caddy"
 )
@@ -19,17 +19,17 @@ func setup(c *caddy.Controller) error {
 	config := dnsserver.GetConfig(c)
 
 	if config.TLSConfig != nil {
-		return middleware.Error("tls", c.Errf("TLS already configured for this server instance"))
+		return plugin.Error("tls", c.Errf("TLS already configured for this server instance"))
 	}
 
 	for c.Next() {
 		args := c.RemainingArgs()
 		if len(args) != 3 {
-			return middleware.Error("tls", c.ArgErr())
+			return plugin.Error("tls", c.ArgErr())
 		}
 		tls, err := tls.NewTLSConfig(args[0], args[1], args[2])
 		if err != nil {
-			return middleware.Error("tls", err)
+			return plugin.Error("tls", err)
 		}
 		config.TLSConfig = tls
 	}
diff --git a/middleware/tls/tls_test.go b/plugin/tls/tls_test.go
similarity index 100%
rename from middleware/tls/tls_test.go
rename to plugin/tls/tls_test.go
diff --git a/middleware/trace/README.md b/plugin/trace/README.md
similarity index 98%
rename from middleware/trace/README.md
rename to plugin/trace/README.md
index aa157e1e2..62e6d463d 100644
--- a/middleware/trace/README.md
+++ b/plugin/trace/README.md
@@ -1,7 +1,7 @@
 # trace
 
 This module enables OpenTracing-based tracing of DNS requests as they go through the
-middleware chain.
+plugin chain.
 
 ## Syntax
 
diff --git a/middleware/trace/setup.go b/plugin/trace/setup.go
similarity index 92%
rename from middleware/trace/setup.go
rename to plugin/trace/setup.go
index 601472fee..5c6e473c3 100644
--- a/middleware/trace/setup.go
+++ b/plugin/trace/setup.go
@@ -6,7 +6,7 @@ import (
 	"strings"
 
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -21,10 +21,10 @@ func init() {
 func setup(c *caddy.Controller) error {
 	t, err := traceParse(c)
 	if err != nil {
-		return middleware.Error("trace", err)
+		return plugin.Error("trace", err)
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		t.Next = next
 		return t
 	})
diff --git a/middleware/trace/setup_test.go b/plugin/trace/setup_test.go
similarity index 100%
rename from middleware/trace/setup_test.go
rename to plugin/trace/setup_test.go
diff --git a/middleware/trace/trace.go b/plugin/trace/trace.go
similarity index 87%
rename from middleware/trace/trace.go
rename to plugin/trace/trace.go
index 86561871a..fa561945e 100644
--- a/middleware/trace/trace.go
+++ b/plugin/trace/trace.go
@@ -6,9 +6,9 @@ import (
 	"sync"
 	"sync/atomic"
 
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 	// Plugin the trace package.
-	_ "github.com/coredns/coredns/middleware/pkg/trace"
+	_ "github.com/coredns/coredns/plugin/pkg/trace"
 
 	"github.com/miekg/dns"
 	ot "github.com/opentracing/opentracing-go"
@@ -17,7 +17,7 @@ import (
 )
 
 type trace struct {
-	Next            middleware.Handler
+	Next            plugin.Handler
 	ServiceEndpoint string
 	Endpoint        string
 	EndpointType    string
@@ -65,7 +65,7 @@ func (t *trace) Name() string {
 	return "trace"
 }
 
-// ServeDNS implements the middleware.Handle interface.
+// ServeDNS implements the plugin.Handle interface.
 func (t *trace) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	trace := false
 	if t.every > 0 {
@@ -80,5 +80,5 @@ func (t *trace) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg)
 		defer span.Finish()
 		ctx = ot.ContextWithSpan(ctx, span)
 	}
-	return middleware.NextOrFailure(t.Name(), t.Next, ctx, w, r)
+	return plugin.NextOrFailure(t.Name(), t.Next, ctx, w, r)
 }
diff --git a/middleware/trace/trace_test.go b/plugin/trace/trace_test.go
similarity index 82%
rename from middleware/trace/trace_test.go
rename to plugin/trace/trace_test.go
index 06b2aafcf..b006009c3 100644
--- a/middleware/trace/trace_test.go
+++ b/plugin/trace/trace_test.go
@@ -6,7 +6,7 @@ import (
 	"github.com/mholt/caddy"
 )
 
-// createTestTrace creates a trace middleware to be used in tests
+// createTestTrace creates a trace plugin to be used in tests
 func createTestTrace(config string) (*caddy.Controller, *trace, error) {
 	c := caddy.NewTestController("dns", config)
 	m, err := traceParse(c)
@@ -24,7 +24,7 @@ func TestTrace(t *testing.T) {
 	}
 	err = m.OnStartup()
 	if err != nil {
-		t.Errorf("Error starting tracing middleware: %s", err)
+		t.Errorf("Error starting tracing plugin: %s", err)
 		return
 	}
 	if m.Tracer() == nil {
diff --git a/middleware/whoami/README.md b/plugin/whoami/README.md
similarity index 79%
rename from middleware/whoami/README.md
rename to plugin/whoami/README.md
index 4b56a2e77..d16a93766 100644
--- a/middleware/whoami/README.md
+++ b/plugin/whoami/README.md
@@ -10,11 +10,11 @@ section as a SRV record, transport can be "tcp" or "udp".
 ._<transport>.qname. 0 IN SRV 0 0 <port> .
 ~~~
 
-If CoreDNS can't find a Corefile on startup this is the *default* middleware that gets loaded. As
-such it can be used to check that CoreDNS is responding to queries. Other than that this middleware
+If CoreDNS can't find a Corefile on startup this is the *default* plugin that gets loaded. As
+such it can be used to check that CoreDNS is responding to queries. Other than that this plugin
 is of limited use in production.
 
-The *whoami* middleware will respond to every A or AAAA query, regardless of the query name.
+The *whoami* plugin will respond to every A or AAAA query, regardless of the query name.
 
 ## Syntax
 
@@ -24,7 +24,7 @@ whoami
 
 ## Examples
 
-Start a server on the default port and load the *whoami* middleware.
+Start a server on the default port and load the *whoami* plugin.
 
 ~~~ corefile
 . {
diff --git a/middleware/whoami/setup.go b/plugin/whoami/setup.go
similarity index 65%
rename from middleware/whoami/setup.go
rename to plugin/whoami/setup.go
index e11ac6567..9797c8bbf 100644
--- a/middleware/whoami/setup.go
+++ b/plugin/whoami/setup.go
@@ -2,7 +2,7 @@ package whoami
 
 import (
 	"github.com/coredns/coredns/core/dnsserver"
-	"github.com/coredns/coredns/middleware"
+	"github.com/coredns/coredns/plugin"
 
 	"github.com/mholt/caddy"
 )
@@ -17,10 +17,10 @@ func init() {
 func setupWhoami(c *caddy.Controller) error {
 	c.Next() // 'whoami'
 	if c.NextArg() {
-		return middleware.Error("whoami", c.ArgErr())
+		return plugin.Error("whoami", c.ArgErr())
 	}
 
-	dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler {
+	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler {
 		return Whoami{}
 	})
 
diff --git a/middleware/whoami/setup_test.go b/plugin/whoami/setup_test.go
similarity index 100%
rename from middleware/whoami/setup_test.go
rename to plugin/whoami/setup_test.go
diff --git a/middleware/whoami/whoami.go b/plugin/whoami/whoami.go
similarity index 83%
rename from middleware/whoami/whoami.go
rename to plugin/whoami/whoami.go
index 6b5ed332a..9d22c43a8 100644
--- a/middleware/whoami/whoami.go
+++ b/plugin/whoami/whoami.go
@@ -1,4 +1,4 @@
-// Package whoami implements a middleware that returns details about the resolving
+// Package whoami implements a plugin that returns details about the resolving
 // querying it.
 package whoami
 
@@ -12,11 +12,11 @@ import (
 	"golang.org/x/net/context"
 )
 
-// Whoami is a middleware that returns your IP address, port and the protocol used for connecting
+// Whoami is a plugin that returns your IP address, port and the protocol used for connecting
 // to CoreDNS.
 type Whoami struct{}
 
-// ServeDNS implements the middleware.Handler interface.
+// ServeDNS implements the plugin.Handler interface.
 func (wh Whoami) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
 	state := request.Request{W: w, Req: r}
 
diff --git a/middleware/whoami/whoami_test.go b/plugin/whoami/whoami_test.go
similarity index 92%
rename from middleware/whoami/whoami_test.go
rename to plugin/whoami/whoami_test.go
index d9357e497..c8e57f80c 100644
--- a/middleware/whoami/whoami_test.go
+++ b/plugin/whoami/whoami_test.go
@@ -3,8 +3,8 @@ package whoami
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/pkg/dnsrecorder"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 	"golang.org/x/net/context"
diff --git a/request/request.go b/request/request.go
index a2428c464..2ce2c7acc 100644
--- a/request/request.go
+++ b/request/request.go
@@ -1,4 +1,4 @@
-// Package request abstracts a client's request so that all middleware
+// Package request abstracts a client's request so that all plugin
 // will handle them in an unified way.
 package request
 
@@ -6,12 +6,12 @@ import (
 	"net"
 	"strings"
 
-	"github.com/coredns/coredns/middleware/pkg/edns"
+	"github.com/coredns/coredns/plugin/pkg/edns"
 
 	"github.com/miekg/dns"
 )
 
-// Request contains some connection state and is useful in middleware.
+// Request contains some connection state and is useful in plugin.
 type Request struct {
 	Req *dns.Msg
 	W   dns.ResponseWriter
diff --git a/request/request_test.go b/request/request_test.go
index bc08ea6ab..2311d89ea 100644
--- a/request/request_test.go
+++ b/request/request_test.go
@@ -3,7 +3,7 @@ package request
 import (
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/auto_test.go b/test/auto_test.go
index b5a9c2b09..ff130188b 100644
--- a/test/auto_test.go
+++ b/test/auto_test.go
@@ -8,8 +8,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/cache_test.go b/test/cache_test.go
index bb5017a24..2379cd2a3 100644
--- a/test/cache_test.go
+++ b/test/cache_test.go
@@ -6,8 +6,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/ds_file_test.go b/test/ds_file_test.go
index 2ec19c5b4..8d342dab1 100644
--- a/test/ds_file_test.go
+++ b/test/ds_file_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	mtest "github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	mtest "github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/etcd_cache_test.go b/test/etcd_cache_test.go
index db283e73e..a927a08f8 100644
--- a/test/etcd_cache_test.go
+++ b/test/etcd_cache_test.go
@@ -7,9 +7,9 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/etcd_test.go b/test/etcd_test.go
index eaab7a730..66502e8dc 100644
--- a/test/etcd_test.go
+++ b/test/etcd_test.go
@@ -9,10 +9,10 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/etcd"
-	"github.com/coredns/coredns/middleware/etcd/msg"
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/etcd"
+	"github.com/coredns/coredns/plugin/etcd/msg"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	etcdc "github.com/coreos/etcd/client"
@@ -87,7 +87,7 @@ var servicesStub = []*msg.Service{
 	{Host: "199.43.132.53", Key: "a.example.net.stub.dns.skydns.test."},
 }
 
-// Copied from middleware/etcd/setup_test.go
+// Copied from plugin/etcd/setup_test.go
 func set(ctx context.Context, t *testing.T, e *etcd.Etcd, k string, ttl time.Duration, m *msg.Service) {
 	b, err := json.Marshal(m)
 	if err != nil {
@@ -97,7 +97,7 @@ func set(ctx context.Context, t *testing.T, e *etcd.Etcd, k string, ttl time.Dur
 	e.Client.Set(ctx, path, string(b), &etcdc.SetOptions{TTL: ttl})
 }
 
-// Copied from middleware/etcd/setup_test.go
+// Copied from plugin/etcd/setup_test.go
 func delete(ctx context.Context, t *testing.T, e *etcd.Etcd, k string) {
 	path, _ := msg.PathWithWildcard(k, e.PathPrefix)
 	e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false})
diff --git a/test/external_test.go b/test/external_test.go
index 9109f1f29..6b014552c 100644
--- a/test/external_test.go
+++ b/test/external_test.go
@@ -8,7 +8,7 @@ import (
 	"testing"
 )
 
-// Go get external example middleware, compile it into CoreDNS
+// Go get external example plugin, compile it into CoreDNS
 // and check if it is really there, but running coredns -plugins.
 
 // Dangerous test as it messes with your git tree, maybe use tag?
@@ -36,7 +36,7 @@ func testExternalMiddlewareCompile(t *testing.T) {
 	}
 
 	if !strings.Contains(string(out), "dns.example") {
-		t.Fatal("dns.example middleware should be there")
+		t.Fatal("dns.example plugin should be there")
 	}
 }
 
@@ -51,7 +51,7 @@ func run(t *testing.T, c *exec.Cmd) ([]byte, error) {
 }
 
 func addExampleMiddleware() error {
-	f, err := os.OpenFile("../middleware.cfg", os.O_APPEND|os.O_WRONLY, os.ModeAppend)
+	f, err := os.OpenFile("../plugin.cfg", os.O_APPEND|os.O_WRONLY, os.ModeAppend)
 	if err != nil {
 		return err
 	}
diff --git a/test/file_cname_proxy_test.go b/test/file_cname_proxy_test.go
index 6630abb42..b0adcf203 100644
--- a/test/file_cname_proxy_test.go
+++ b/test/file_cname_proxy_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/file_reload_test.go b/test/file_reload_test.go
index e7ecc4d09..e944faa55 100644
--- a/test/file_reload_test.go
+++ b/test/file_reload_test.go
@@ -6,8 +6,8 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/file_srv_additional_test.go b/test/file_srv_additional_test.go
index 1925f98c1..26ae1f9aa 100644
--- a/test/file_srv_additional_test.go
+++ b/test/file_srv_additional_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/kubernetes_api_fallthrough_test.go b/test/kubernetes_api_fallthrough_test.go
index 20c0aaa21..08d380f67 100644
--- a/test/kubernetes_api_fallthrough_test.go
+++ b/test/kubernetes_api_fallthrough_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/kubernetes_fallthrough_test.go b/test/kubernetes_fallthrough_test.go
index 4e5ee5d5c..1b0545056 100644
--- a/test/kubernetes_fallthrough_test.go
+++ b/test/kubernetes_fallthrough_test.go
@@ -8,7 +8,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/kubernetes_nsexposed_test.go b/test/kubernetes_nsexposed_test.go
index 1c3e470e5..f5161c9a1 100644
--- a/test/kubernetes_nsexposed_test.go
+++ b/test/kubernetes_nsexposed_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/kubernetes_pods_test.go b/test/kubernetes_pods_test.go
index a06d0aaac..67447f979 100644
--- a/test/kubernetes_pods_test.go
+++ b/test/kubernetes_pods_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/kubernetes_test.go b/test/kubernetes_test.go
index 0a5d286f2..c3004a951 100644
--- a/test/kubernetes_test.go
+++ b/test/kubernetes_test.go
@@ -13,7 +13,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/mholt/caddy"
 	"github.com/miekg/dns"
diff --git a/test/metrics_test.go b/test/metrics_test.go
index fa7adee80..4a1665c5b 100644
--- a/test/metrics_test.go
+++ b/test/metrics_test.go
@@ -8,10 +8,10 @@ import (
 	"testing"
 	"time"
 
-	"github.com/coredns/coredns/middleware/cache"
-	"github.com/coredns/coredns/middleware/metrics"
-	mtest "github.com/coredns/coredns/middleware/metrics/test"
-	"github.com/coredns/coredns/middleware/metrics/vars"
+	"github.com/coredns/coredns/plugin/cache"
+	"github.com/coredns/coredns/plugin/metrics"
+	mtest "github.com/coredns/coredns/plugin/metrics/test"
+	"github.com/coredns/coredns/plugin/metrics/vars"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/middleware_dnssec_test.go b/test/middleware_dnssec_test.go
index d1dbfc594..0ae6507a3 100644
--- a/test/middleware_dnssec_test.go
+++ b/test/middleware_dnssec_test.go
@@ -6,7 +6,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/middleware_test.go b/test/middleware_test.go
index 745d47d7b..9f3604e4e 100644
--- a/test/middleware_test.go
+++ b/test/middleware_test.go
@@ -5,7 +5,7 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/test"
 
 	"github.com/miekg/dns"
 )
diff --git a/test/proxy_health_test.go b/test/proxy_health_test.go
index 34c2c24c5..8d7c229b8 100644
--- a/test/proxy_health_test.go
+++ b/test/proxy_health_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/proxy_http_health_test.go b/test/proxy_http_health_test.go
index a331083de..2a31093fe 100644
--- a/test/proxy_http_health_test.go
+++ b/test/proxy_http_health_test.go
@@ -10,8 +10,8 @@ import (
 	"net/url"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 	"github.com/miekg/dns"
 )
diff --git a/test/proxy_test.go b/test/proxy_test.go
index 01402ed27..90c1e3940 100644
--- a/test/proxy_test.go
+++ b/test/proxy_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/readme_test.go b/test/readme_test.go
index 9c9eae249..26f44234e 100644
--- a/test/readme_test.go
+++ b/test/readme_test.go
@@ -14,7 +14,7 @@ import (
 	"github.com/mholt/caddy"
 )
 
-// Pasrse all README.md's of the middleware and check if every example Corefile
+// Pasrse all README.md's of the plugin and check if every example Corefile
 // actually works. Each corefile is only used if:
 //
 // ~~~ corefile
@@ -30,7 +30,7 @@ func TestReadme(t *testing.T) {
 
 	log.SetOutput(ioutil.Discard)
 
-	middle := filepath.Join("..", "middleware")
+	middle := filepath.Join("..", "plugin")
 	dirs, err := ioutil.ReadDir(middle)
 	if err != nil {
 		t.Fatalf("Could not read %s: %q", middle, err)
diff --git a/test/reverse_test.go b/test/reverse_test.go
index 25b3d9068..184a5fe1f 100644
--- a/test/reverse_test.go
+++ b/test/reverse_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/secondary_test.go b/test/secondary_test.go
index b3eed5c1b..370d523c9 100644
--- a/test/secondary_test.go
+++ b/test/secondary_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"
diff --git a/test/wildcard_test.go b/test/wildcard_test.go
index 67feb2e77..b233e3031 100644
--- a/test/wildcard_test.go
+++ b/test/wildcard_test.go
@@ -5,8 +5,8 @@ import (
 	"log"
 	"testing"
 
-	"github.com/coredns/coredns/middleware/proxy"
-	"github.com/coredns/coredns/middleware/test"
+	"github.com/coredns/coredns/plugin/proxy"
+	"github.com/coredns/coredns/plugin/test"
 	"github.com/coredns/coredns/request"
 
 	"github.com/miekg/dns"