diff --git a/_proto/hapi/chart/metadata.proto b/_proto/hapi/chart/metadata.proto
index 4a1a623bbb2fd11d97419cfac4277f1c31ac62c5..7416c77061ea08fd4628c22273339793a54ea059 100644
--- a/_proto/hapi/chart/metadata.proto
+++ b/_proto/hapi/chart/metadata.proto
@@ -73,7 +73,11 @@ message Metadata {
 
 	// The version of the application enclosed inside of this chart.
 	string appVersion = 13;
-	
+
 	// Whether or not this chart is deprecated
 	bool deprecated = 14;
+
+	// TillerVersion is a SemVer constraints on what version of Tiller is required.
+	// See SemVer ranges here: https://github.com/Masterminds/semver#basic-comparisons
+	string tillerVersion = 15;
 }
diff --git a/docs/chart_best_practices/conventions.md b/docs/chart_best_practices/conventions.md
index f9d6ed7ba0e59eff9a491f430821b9436f4a4422..324ef88f9a80aadd8e7023fbd9f3664de372fb28 100644
--- a/docs/chart_best_practices/conventions.md
+++ b/docs/chart_best_practices/conventions.md
@@ -38,4 +38,22 @@ There are a few small conventions followed for using the words Helm, helm, Tille
 - `tiller` is the name of the binary run on the backend
 - The term 'chart' does not need to be capitalized, as it is not a proper noun.
 
-When in doubt, use _Helm_ (with an uppercase 'H').
\ No newline at end of file
+When in doubt, use _Helm_ (with an uppercase 'H').
+
+## Restricting Tiller by Version
+
+A `Chart.yaml` file can specify a `tillerVersion` SemVer constraint:
+
+```yaml
+name: mychart
+version: 0.2.0
+tillerVersion: ">=2.4.0"
+```
+
+This constraint should be set when templates use a new feature that was not
+supported in older versions of Helm. While this parameter will accept sophisticated
+SemVer rules, the best practice is to default to the form `>=2.4.0`, where `2.4.0`
+is the version that introduced the new feature used in the chart.
+
+This feature was introduced in Helm 2.4.0, so any version of Tiller older than
+2.4.0 will simply ignore this field.
diff --git a/docs/charts.md b/docs/charts.md
index 414f80bf70f6ebf52feabc21ba58b997ba665ba8..b1aa10ad4a43c66e9c0350a99b1af2a1dee3e4cf 100644
--- a/docs/charts.md
+++ b/docs/charts.md
@@ -55,6 +55,7 @@ engine: gotpl # The name of the template engine (optional, defaults to gotpl)
 icon: A URL to an SVG or PNG image to be used as an icon (optional).
 appVersion: The version of the app that this contains (optional). This needn't be SemVer.
 deprecated: Whether or not this chart is deprecated (optional, boolean)
+tillerVersion: The version of Tiller that this chart requires. This should be expressed as a SemVer range: ">2.0.0" (optional)
 ```
 
 If you are familiar with the `Chart.yaml` file format for Helm Classic, you will
diff --git a/pkg/proto/hapi/chart/metadata.pb.go b/pkg/proto/hapi/chart/metadata.pb.go
index 5feee0bf4ea3e60d9b7f473dfea0aacc8dfd56dc..f1ee5eb3649511a6865118748b8d3c14ae59f288 100644
--- a/pkg/proto/hapi/chart/metadata.pb.go
+++ b/pkg/proto/hapi/chart/metadata.pb.go
@@ -79,6 +79,9 @@ type Metadata struct {
 	AppVersion string `protobuf:"bytes,13,opt,name=appVersion" json:"appVersion,omitempty"`
 	// Whether or not this chart is deprecated
 	Deprecated bool `protobuf:"varint,14,opt,name=deprecated" json:"deprecated,omitempty"`
+	// TillerVersion is a SemVer constraints on what version of Tiller is required.
+	// See SemVer ranges here: https://github.com/Masterminds/semver#basic-comparisons
+	TillerVersion string `protobuf:"bytes,15,opt,name=tillerVersion" json:"tillerVersion,omitempty"`
 }
 
 func (m *Metadata) Reset()                    { *m = Metadata{} }
@@ -102,27 +105,28 @@ func init() {
 func init() { proto.RegisterFile("hapi/chart/metadata.proto", fileDescriptor2) }
 
 var fileDescriptor2 = []byte{
-	// 339 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x92, 0x4f, 0x4b, 0xeb, 0x40,
-	0x14, 0xc5, 0x5f, 0x5e, 0x9a, 0x7f, 0x37, 0xef, 0x3d, 0xca, 0xf0, 0x28, 0xa3, 0x88, 0x84, 0xae,
-	0xb2, 0x4a, 0x41, 0x41, 0x5c, 0x0b, 0xe2, 0x42, 0xdb, 0x4a, 0xf0, 0x0f, 0xb8, 0x1b, 0x93, 0x4b,
-	0x3b, 0x68, 0x66, 0xc2, 0xcc, 0xa8, 0xf8, 0xe5, 0xfc, 0x6c, 0x32, 0x93, 0xa4, 0xcd, 0xc2, 0xdd,
-	0x3d, 0xe7, 0x97, 0x7b, 0x92, 0x73, 0x09, 0x1c, 0x6c, 0x59, 0xcb, 0x17, 0xd5, 0x96, 0x29, 0xb3,
-	0x68, 0xd0, 0xb0, 0x9a, 0x19, 0x56, 0xb4, 0x4a, 0x1a, 0x49, 0xc0, 0xa2, 0xc2, 0xa1, 0xf9, 0x19,
-	0xc0, 0x92, 0x71, 0x61, 0x18, 0x17, 0xa8, 0x08, 0x81, 0x89, 0x60, 0x0d, 0x52, 0x2f, 0xf3, 0xf2,
-	0xa4, 0x74, 0x33, 0xf9, 0x0f, 0x01, 0x36, 0x8c, 0xbf, 0xd2, 0xdf, 0xce, 0xec, 0xc4, 0xfc, 0xcb,
-	0x87, 0x78, 0xd9, 0xc7, 0xfe, 0xb8, 0x46, 0x60, 0xb2, 0x95, 0x0d, 0xf6, 0x5b, 0x6e, 0x26, 0x14,
-	0x22, 0x2d, 0xdf, 0x54, 0x85, 0x9a, 0xfa, 0x99, 0x9f, 0x27, 0xe5, 0x20, 0x2d, 0x79, 0x47, 0xa5,
-	0xb9, 0x14, 0x74, 0xe2, 0x16, 0x06, 0x49, 0x32, 0x48, 0x6b, 0xd4, 0x95, 0xe2, 0xad, 0xb1, 0x34,
-	0x70, 0x74, 0x6c, 0x91, 0x43, 0x88, 0x5f, 0xf0, 0xf3, 0x43, 0xaa, 0x5a, 0xd3, 0xd0, 0xc5, 0xee,
-	0x34, 0x39, 0x87, 0xb4, 0xd9, 0xd5, 0xd3, 0x34, 0xca, 0xfc, 0x3c, 0x3d, 0x99, 0x15, 0xfb, 0x03,
-	0x14, 0xfb, 0xf6, 0xe5, 0xf8, 0x51, 0x32, 0x83, 0x10, 0xc5, 0x86, 0x0b, 0xa4, 0xb1, 0x7b, 0x65,
-	0xaf, 0x6c, 0x2f, 0x5e, 0x49, 0x41, 0x93, 0xae, 0x97, 0x9d, 0xc9, 0x31, 0x00, 0x6b, 0xf9, 0x43,
-	0x5f, 0x00, 0x1c, 0x19, 0x39, 0xe4, 0x08, 0x92, 0x4a, 0x8a, 0x9a, 0xbb, 0x06, 0xa9, 0xc3, 0x7b,
-	0xc3, 0x26, 0x1a, 0xb6, 0xd1, 0xf4, 0x4f, 0x97, 0x68, 0xe7, 0x2e, 0xb1, 0x1d, 0x12, 0xff, 0x0e,
-	0x89, 0x83, 0x63, 0x79, 0x8d, 0xad, 0xc2, 0x8a, 0x19, 0xac, 0xe9, 0xbf, 0xcc, 0xcb, 0xe3, 0x72,
-	0xe4, 0xcc, 0x33, 0x08, 0x2f, 0xbb, 0xef, 0x4d, 0x21, 0xba, 0x5f, 0x5d, 0xaf, 0xd6, 0x8f, 0xab,
-	0xe9, 0x2f, 0x92, 0x40, 0x70, 0xb5, 0xbe, 0xbb, 0xbd, 0x99, 0x7a, 0x17, 0xd1, 0x53, 0xe0, 0x0e,
-	0xf0, 0x1c, 0xba, 0x9f, 0xe2, 0xf4, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x08, 0xf3, 0xcc, 0x66, 0x31,
-	0x02, 0x00, 0x00,
+	// 354 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x6c, 0x92, 0x5f, 0x4b, 0xe3, 0x40,
+	0x14, 0xc5, 0x37, 0x9b, 0xe6, 0xdf, 0xcd, 0x76, 0xb7, 0x0c, 0x4b, 0x99, 0x5d, 0x44, 0x42, 0xf1,
+	0x21, 0x4f, 0x29, 0x28, 0x88, 0xcf, 0x82, 0xf8, 0xa0, 0x6d, 0x25, 0xf8, 0x07, 0x7c, 0x1b, 0x93,
+	0x4b, 0x3b, 0xd8, 0xcc, 0x84, 0xc9, 0xa8, 0xf8, 0x7d, 0xfd, 0x20, 0x32, 0x93, 0xa4, 0x8d, 0xe0,
+	0xdb, 0x3d, 0xe7, 0xe4, 0xfe, 0xc2, 0xb9, 0x0c, 0xfc, 0xdb, 0xb0, 0x9a, 0xcf, 0x8b, 0x0d, 0x53,
+	0x7a, 0x5e, 0xa1, 0x66, 0x25, 0xd3, 0x2c, 0xab, 0x95, 0xd4, 0x92, 0x80, 0x89, 0x32, 0x1b, 0xcd,
+	0x4e, 0x01, 0x16, 0x8c, 0x0b, 0xcd, 0xb8, 0x40, 0x45, 0x08, 0x8c, 0x04, 0xab, 0x90, 0x3a, 0x89,
+	0x93, 0x46, 0xb9, 0x9d, 0xc9, 0x5f, 0xf0, 0xb0, 0x62, 0x7c, 0x4b, 0x7f, 0x5a, 0xb3, 0x15, 0xb3,
+	0x0f, 0x17, 0xc2, 0x45, 0x87, 0xfd, 0x76, 0x8d, 0xc0, 0x68, 0x23, 0x2b, 0xec, 0xb6, 0xec, 0x4c,
+	0x28, 0x04, 0x8d, 0x7c, 0x51, 0x05, 0x36, 0xd4, 0x4d, 0xdc, 0x34, 0xca, 0x7b, 0x69, 0x92, 0x57,
+	0x54, 0x0d, 0x97, 0x82, 0x8e, 0xec, 0x42, 0x2f, 0x49, 0x02, 0x71, 0x89, 0x4d, 0xa1, 0x78, 0xad,
+	0x4d, 0xea, 0xd9, 0x74, 0x68, 0x91, 0xff, 0x10, 0x3e, 0xe3, 0xfb, 0x9b, 0x54, 0x65, 0x43, 0x7d,
+	0x8b, 0xdd, 0x69, 0x72, 0x06, 0x71, 0xb5, 0xab, 0xd7, 0xd0, 0x20, 0x71, 0xd3, 0xf8, 0x78, 0x9a,
+	0xed, 0x0f, 0x90, 0xed, 0xdb, 0xe7, 0xc3, 0x4f, 0xc9, 0x14, 0x7c, 0x14, 0x6b, 0x2e, 0x90, 0x86,
+	0xf6, 0x97, 0x9d, 0x32, 0xbd, 0x78, 0x21, 0x05, 0x8d, 0xda, 0x5e, 0x66, 0x26, 0x87, 0x00, 0xac,
+	0xe6, 0xf7, 0x5d, 0x01, 0xb0, 0xc9, 0xc0, 0x21, 0x07, 0x10, 0x15, 0x52, 0x94, 0xdc, 0x36, 0x88,
+	0x6d, 0xbc, 0x37, 0x0c, 0x51, 0xb3, 0x75, 0x43, 0x7f, 0xb5, 0x44, 0x33, 0xb7, 0xc4, 0xba, 0x27,
+	0x8e, 0x7b, 0x62, 0xef, 0x98, 0xbc, 0xc4, 0x5a, 0x61, 0xc1, 0x34, 0x96, 0xf4, 0x77, 0xe2, 0xa4,
+	0x61, 0x3e, 0x70, 0xc8, 0x11, 0x8c, 0x35, 0xdf, 0x6e, 0x51, 0xf5, 0x88, 0x3f, 0x16, 0xf1, 0xd5,
+	0x9c, 0x25, 0xe0, 0x5f, 0xb4, 0xad, 0x62, 0x08, 0xee, 0x96, 0x57, 0xcb, 0xd5, 0xc3, 0x72, 0xf2,
+	0x83, 0x44, 0xe0, 0x5d, 0xae, 0x6e, 0x6f, 0xae, 0x27, 0xce, 0x79, 0xf0, 0xe8, 0xd9, 0x33, 0x3d,
+	0xf9, 0xf6, 0xe9, 0x9c, 0x7c, 0x06, 0x00, 0x00, 0xff, 0xff, 0xea, 0xb5, 0x4c, 0xbe, 0x57, 0x02,
+	0x00, 0x00,
 }
diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go
index bc5c3098ea6ad3d2a849a0f3f38709e76833d7b6..b26805d449ddb478a09f77d8249bb19dd99423b9 100644
--- a/pkg/tiller/release_server.go
+++ b/pkg/tiller/release_server.go
@@ -776,6 +776,13 @@ func getVersionSet(client discovery.ServerGroupsInterface) (chartutil.VersionSet
 }
 
 func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values, vs chartutil.VersionSet) ([]*release.Hook, *bytes.Buffer, string, error) {
+	// Guard to make sure Tiller is at the right version to handle this chart.
+	sver := version.GetVersion()
+	if ch.Metadata.TillerVersion != "" &&
+		!version.IsCompatibleRange(ch.Metadata.TillerVersion, sver) {
+		return nil, nil, "", fmt.Errorf("Chart incompatible with Tiller %s", sver)
+	}
+
 	renderer := s.engine(ch)
 	files, err := renderer.Render(ch, values)
 	if err != nil {
diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go
index d4e47a07f576f54137e68273b9bb1b253047321e..636874b2000c0992aae710c938efa3c36b610c3b 100644
--- a/pkg/tiller/release_server_test.go
+++ b/pkg/tiller/release_server_test.go
@@ -325,7 +325,7 @@ func TestInstallRelease(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseWithNotes(t *testing.T) {
+func TestInstallRelease_WithNotes(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 
@@ -394,7 +394,7 @@ func TestInstallReleaseWithNotes(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseWithNotesRendered(t *testing.T) {
+func TestInstallRelease_WithNotesRendered(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 
@@ -464,7 +464,54 @@ func TestInstallReleaseWithNotesRendered(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseWithChartAndDependencyNotes(t *testing.T) {
+func TestInstallRelease_TillerVersion(t *testing.T) {
+	c := helm.NewContext()
+	rs := rsFixture()
+
+	// TODO: Refactor this into a mock.
+	req := &services.InstallReleaseRequest{
+		Namespace: "spaced",
+		Chart: &chart.Chart{
+			Metadata: &chart.Metadata{Name: "hello", TillerVersion: ">=2.2.0"},
+			Templates: []*chart.Template{
+				{Name: "templates/hello", Data: []byte("hello: world")},
+				{Name: "templates/hooks", Data: []byte(manifestWithHook)},
+			},
+		},
+	}
+	_, err := rs.InstallRelease(c, req)
+	if err != nil {
+		t.Fatalf("Expected valid range. Got %q", err)
+	}
+}
+
+func TestInstallRelease_WrongTillerVersion(t *testing.T) {
+	c := helm.NewContext()
+	rs := rsFixture()
+
+	// TODO: Refactor this into a mock.
+	req := &services.InstallReleaseRequest{
+		Namespace: "spaced",
+		Chart: &chart.Chart{
+			Metadata: &chart.Metadata{Name: "hello", TillerVersion: "<2.0.0"},
+			Templates: []*chart.Template{
+				{Name: "templates/hello", Data: []byte("hello: world")},
+				{Name: "templates/hooks", Data: []byte(manifestWithHook)},
+			},
+		},
+	}
+	_, err := rs.InstallRelease(c, req)
+	if err == nil {
+		t.Fatalf("Expected to fail because of wrong version")
+	}
+
+	expect := "Chart incompatible with Tiller"
+	if !strings.Contains(err.Error(), expect) {
+		t.Errorf("Expected %q to contain %q", err.Error(), expect)
+	}
+}
+
+func TestInstallRelease_WithChartAndDependencyNotes(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 
@@ -515,7 +562,7 @@ func TestInstallReleaseWithChartAndDependencyNotes(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseDryRun(t *testing.T) {
+func TestInstallRelease_DryRun(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 
@@ -568,7 +615,7 @@ func TestInstallReleaseDryRun(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseNoHooks(t *testing.T) {
+func TestInstallRelease_NoHooks(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 	rs.env.Releases.Create(releaseStub())
@@ -587,7 +634,7 @@ func TestInstallReleaseNoHooks(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseFailedHooks(t *testing.T) {
+func TestInstallRelease_FailedHooks(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 	rs.env.Releases.Create(releaseStub())
@@ -606,7 +653,7 @@ func TestInstallReleaseFailedHooks(t *testing.T) {
 	}
 }
 
-func TestInstallReleaseReuseName(t *testing.T) {
+func TestInstallRelease_ReuseName(t *testing.T) {
 	c := helm.NewContext()
 	rs := rsFixture()
 	rel := releaseStub()
diff --git a/pkg/version/compatible.go b/pkg/version/compatible.go
index 4a7b0d4bc5710eda783a6defb1669c646624787e..c8f359971b0d51646ddfe95124f6dc1ed70f0769 100644
--- a/pkg/version/compatible.go
+++ b/pkg/version/compatible.go
@@ -38,6 +38,17 @@ func IsCompatible(client, server string) bool {
 		constraint = cv.String()
 	}
 
+	return IsCompatibleRange(constraint, server)
+}
+
+// IsCompatibleRange compares a version to a constraint.
+// It returns true if the version matches the constraint, and false in all other cases.
+func IsCompatibleRange(constraint, ver string) bool {
+	sv, err := semver.NewVersion(ver)
+	if err != nil {
+		return false
+	}
+
 	c, err := semver.NewConstraint(constraint)
 	if err != nil {
 		return false
diff --git a/pkg/version/compatible_test.go b/pkg/version/compatible_test.go
index 3b92fa25f1da0730f0163d96e92e19c3867f8822..adc1c489e736b89eafc138318ca1b300a00135de 100644
--- a/pkg/version/compatible_test.go
+++ b/pkg/version/compatible_test.go
@@ -41,3 +41,26 @@ func TestIsCompatible(t *testing.T) {
 		}
 	}
 }
+
+func TestIsCompatibleRange(t *testing.T) {
+	tests := []struct {
+		constraint string
+		ver        string
+		expected   bool
+	}{
+		{"v2.0.0-alpha.4", "v2.0.0-alpha.4", true},
+		{"v2.0.0-alpha.3", "v2.0.0-alpha.4", false},
+		{"v2.0.0", "v2.0.0-alpha.4", false},
+		{"v2.0.0-alpha.4", "v2.0.0", false},
+		{"~v2.0.0", "v2.0.1", true},
+		{"v2", "v2.0.0", true},
+		{">2.0.0", "v2.1.1", true},
+		{"v2.1.*", "v2.1.1", true},
+	}
+
+	for _, tt := range tests {
+		if IsCompatibleRange(tt.constraint, tt.ver) != tt.expected {
+			t.Errorf("expected constraint %s to be %v for %s", tt.constraint, tt.expected, tt.ver)
+		}
+	}
+}