diff --git a/src/main/java/org/scijava/ItemPersistence.java b/src/main/java/org/scijava/ItemPersistence.java
new file mode 100644
index 000000000..1ffc497a4
--- /dev/null
+++ b/src/main/java/org/scijava/ItemPersistence.java
@@ -0,0 +1,60 @@
+/*
+ * #%L
+ * SciJava Common shared library for SciJava software.
+ * %%
+ * Copyright (C) 2009 - 2016 Board of Regents of the University of
+ * Wisconsin-Madison, Broad Institute of MIT and Harvard, and Max Planck
+ * Institute of Molecular Cell Biology and Genetics.
+ * %%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * #L%
+ */
+
+package org.scijava;
+
+import org.scijava.plugin.Parameter;
+
+/**
+ * Defines the persistence setting of a parameter.
+ * 
+ * @author Stefan Helfrich
+ */
+public enum ItemPersistence {
+
+	/**
+	 * Item is persisted in any case.
+	 */
+	YES,
+
+	/**
+	 * Item is never persisted.
+	 */
+	NO,
+
+	/**
+	 * Item is persisted unless an additional {@link Parameter#initializer()
+	 * initializer()} method is defined or the value to persist is the defined
+	 * default value.
+	 */
+	DEFAULT
+
+}
diff --git a/src/main/java/org/scijava/command/CommandModuleItem.java b/src/main/java/org/scijava/command/CommandModuleItem.java
index 9752fad33..02a44235c 100644
--- a/src/main/java/org/scijava/command/CommandModuleItem.java
+++ b/src/main/java/org/scijava/command/CommandModuleItem.java
@@ -37,6 +37,7 @@
 import java.util.List;
 
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 import org.scijava.Optional;
 import org.scijava.module.AbstractModuleItem;
@@ -109,7 +110,7 @@ public boolean isRequired() {
 	}
 
 	@Override
-	public boolean isPersisted() {
+	public ItemPersistence getPersistence() {
 		return getParameter().persist();
 	}
 
diff --git a/src/main/java/org/scijava/module/AbstractModuleItem.java b/src/main/java/org/scijava/module/AbstractModuleItem.java
index c6d84537d..301d00b19 100644
--- a/src/main/java/org/scijava/module/AbstractModuleItem.java
+++ b/src/main/java/org/scijava/module/AbstractModuleItem.java
@@ -37,6 +37,7 @@
 
 import org.scijava.AbstractBasicDetails;
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 import org.scijava.util.ClassUtils;
 import org.scijava.util.ConversionUtils;
@@ -71,7 +72,7 @@ public String toString() {
 		sm.append("description", getDescription());
 		sm.append("visibility", getVisibility(), ItemVisibility.NORMAL);
 		sm.append("required", isRequired());
-		sm.append("persisted", isPersisted());
+		sm.append("persisted", getPersistence());
 		sm.append("persistKey", getPersistKey());
 		sm.append("callback", getCallback());
 		sm.append("widgetStyle", getWidgetStyle());
@@ -131,8 +132,8 @@ public boolean isRequired() {
 	}
 
 	@Override
-	public boolean isPersisted() {
-		return true;
+	public ItemPersistence getPersistence() {
+		return ItemPersistence.DEFAULT;
 	}
 
 	@Override
@@ -149,7 +150,7 @@ public String getPersistKey() {
 	@Deprecated
 	public T loadValue() {
 		// if there is nothing to load from persistence return nothing
-		if (!isPersisted()) return null;
+		if (getPersistence() == ItemPersistence.NO) return null;
 
 		final String sValue;
 		final String persistKey = getPersistKey();
@@ -169,7 +170,7 @@ public T loadValue() {
 	@Override
 	@Deprecated
 	public void saveValue(final T value) {
-		if (!isPersisted()) return;
+		if (getPersistence() == ItemPersistence.NO) return;
 
 		final String sValue = value == null ? "" : value.toString();
 
diff --git a/src/main/java/org/scijava/module/DefaultModuleService.java b/src/main/java/org/scijava/module/DefaultModuleService.java
index 0d1e26106..abe1fb7f7 100644
--- a/src/main/java/org/scijava/module/DefaultModuleService.java
+++ b/src/main/java/org/scijava/module/DefaultModuleService.java
@@ -42,6 +42,7 @@
 import java.util.concurrent.Future;
 
 import org.scijava.Identifiable;
+import org.scijava.ItemPersistence;
 import org.scijava.MenuPath;
 import org.scijava.Priority;
 import org.scijava.convert.ConvertService;
@@ -289,9 +290,16 @@ public ModuleItem<?> getSingleOutput(Module module, Collection<Class<?>> types)
 
 	@Override
 	public <T> void save(final ModuleItem<T> item, final T value) {
-		if (!item.isPersisted()) return;
+		ItemPersistence persistence = item.getPersistence();
 
-		if (MiscUtils.equal(item.getDefaultValue(), value)) {
+		if (persistence == ItemPersistence.NO) return;
+
+		// NB: Do not persist values which are computed via an initializer.
+		if (item.getInitializer() != null && !item.getInitializer().isEmpty() &&
+			persistence == ItemPersistence.DEFAULT) return;
+
+		if (MiscUtils.equal(item.getDefaultValue(), value) &&
+			persistence == ItemPersistence.DEFAULT) {
 			// NB: Do not persist the value if it is the default.
 			// This is nice if the default value might change later,
 			// such as when iteratively developing a script.
@@ -315,7 +323,7 @@ public <T> void save(final ModuleItem<T> item, final T value) {
 	@Override
 	public <T> T load(final ModuleItem<T> item) {
 		// if there is nothing to load from persistence return nothing
-		if (!item.isPersisted()) return null;
+		if (item.getPersistence() == ItemPersistence.NO) return null;
 
 		final String sValue;
 		final String persistKey = item.getPersistKey();
diff --git a/src/main/java/org/scijava/module/DefaultMutableModuleItem.java b/src/main/java/org/scijava/module/DefaultMutableModuleItem.java
index 4d95ed91e..4d0c64bbc 100644
--- a/src/main/java/org/scijava/module/DefaultMutableModuleItem.java
+++ b/src/main/java/org/scijava/module/DefaultMutableModuleItem.java
@@ -37,6 +37,7 @@
 import java.util.List;
 
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 
 /**
@@ -54,7 +55,7 @@ public class DefaultMutableModuleItem<T> extends AbstractModuleItem<T>
 	private ItemIO ioType;
 	private ItemVisibility visibility;
 	private boolean required;
-	private boolean persisted;
+	private ItemPersistence persistence;
 	private String persistKey;
 	private String initializer;
 	private String callback;
@@ -87,7 +88,7 @@ public DefaultMutableModuleItem(final ModuleInfo info, final String name,
 		ioType = super.getIOType();
 		visibility = super.getVisibility();
 		required = super.isRequired();
-		persisted = super.isPersisted();
+		persistence = super.getPersistence();
 		persistKey = super.getPersistKey();
 		initializer = super.getInitializer();
 		callback = super.getCallback();
@@ -113,7 +114,7 @@ public DefaultMutableModuleItem(final ModuleInfo info,
 		ioType = item.getIOType();
 		visibility = item.getVisibility();
 		required = item.isRequired();
-		persisted = item.isPersisted();
+		persistence = item.getPersistence();
 		persistKey = item.getPersistKey();
 		initializer = item.getInitializer();
 		callback = item.getCallback();
@@ -148,8 +149,8 @@ public void setRequired(final boolean required) {
 	}
 
 	@Override
-	public void setPersisted(final boolean persisted) {
-		this.persisted = persisted;
+	public void setPersistence(final ItemPersistence persistence) {
+		this.persistence = persistence;
 	}
 
 	@Override
@@ -241,8 +242,8 @@ public boolean isRequired() {
 	}
 
 	@Override
-	public boolean isPersisted() {
-		return persisted;
+	public ItemPersistence getPersistence() {
+		return persistence;
 	}
 
 	@Override
diff --git a/src/main/java/org/scijava/module/ModuleItem.java b/src/main/java/org/scijava/module/ModuleItem.java
index 087a03c8a..dec5504aa 100644
--- a/src/main/java/org/scijava/module/ModuleItem.java
+++ b/src/main/java/org/scijava/module/ModuleItem.java
@@ -37,6 +37,7 @@
 
 import org.scijava.BasicDetails;
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 
 /**
@@ -84,7 +85,7 @@ public interface ModuleItem<T> extends BasicDetails {
 	boolean isRequired();
 
 	/** Gets whether to remember the most recent value of the parameter. */
-	boolean isPersisted();
+	ItemPersistence getPersistence();
 
 	/** Gets the key to use for saving the value persistently. */
 	String getPersistKey();
diff --git a/src/main/java/org/scijava/module/MutableModuleItem.java b/src/main/java/org/scijava/module/MutableModuleItem.java
index 3fd6df99d..5206f04dd 100644
--- a/src/main/java/org/scijava/module/MutableModuleItem.java
+++ b/src/main/java/org/scijava/module/MutableModuleItem.java
@@ -34,6 +34,7 @@
 import java.util.List;
 
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 
 /**
@@ -50,7 +51,7 @@ public interface MutableModuleItem<T> extends ModuleItem<T> {
 
 	void setRequired(boolean required);
 
-	void setPersisted(boolean persisted);
+	void setPersistence(ItemPersistence persistence);
 
 	void setPersistKey(String persistKey);
 
diff --git a/src/main/java/org/scijava/plugin/Parameter.java b/src/main/java/org/scijava/plugin/Parameter.java
index 84e8eddbf..8561a8933 100644
--- a/src/main/java/org/scijava/plugin/Parameter.java
+++ b/src/main/java/org/scijava/plugin/Parameter.java
@@ -37,6 +37,7 @@
 import java.lang.annotation.Target;
 
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 
 /**
@@ -111,12 +112,17 @@
 	boolean required() default true;
 
 	/** Defines whether to remember the most recent value of the parameter. */
-	boolean persist() default true;
+	ItemPersistence persist() default ItemPersistence.DEFAULT;
 
 	/** Defines a key to use for saving the value persistently. */
 	String persistKey() default "";
 
-	/** Defines a function that is called to initialize the parameter. */
+	/**
+	 * Defines a function that is called to initialize the parameter. If an
+	 * initializer is defined, it takes precedence over {@link #persist()}, i.e.
+	 * the parameter is not persisted even if {@link #persist()} returns
+	 * {@link ItemPersistence#YES}.
+	 */
 	String initializer() default "";
 
 	/**
diff --git a/src/main/java/org/scijava/script/ScriptInfo.java b/src/main/java/org/scijava/script/ScriptInfo.java
index bd17bfc34..cd961577b 100644
--- a/src/main/java/org/scijava/script/ScriptInfo.java
+++ b/src/main/java/org/scijava/script/ScriptInfo.java
@@ -49,6 +49,7 @@
 import org.scijava.Context;
 import org.scijava.Contextual;
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.ItemVisibility;
 import org.scijava.NullContextException;
 import org.scijava.command.Command;
@@ -427,7 +428,7 @@ private <T> void assignAttribute(final DefaultMutableModuleItem<T> item,
 		else if (is(k, "max")) item.setMaximumValue(as(v, item.getType()));
 		else if (is(k, "min")) item.setMinimumValue(as(v, item.getType()));
 		else if (is(k, "name")) item.setName(as(v, String.class));
-		else if (is(k, "persist")) item.setPersisted(as(v, boolean.class));
+		else if (is(k, "persist")) item.setPersistence(as(v, ItemPersistence.class));
 		else if (is(k, "persistKey")) item.setPersistKey(as(v, String.class));
 		else if (is(k, "required")) item.setRequired(as(v, boolean.class));
 		else if (is(k, "softMax")) item.setSoftMaximum(as(v, item.getType()));
diff --git a/src/test/java/org/scijava/module/ModuleServiceTest.java b/src/test/java/org/scijava/module/ModuleServiceTest.java
index a1276f915..c165e22dc 100644
--- a/src/test/java/org/scijava/module/ModuleServiceTest.java
+++ b/src/test/java/org/scijava/module/ModuleServiceTest.java
@@ -31,11 +31,13 @@
 
 package org.scijava.module;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 
 import org.junit.Test;
 import org.scijava.Context;
+import org.scijava.prefs.PrefService;
 
 /**
  * Tests {@link ModuleService}.
@@ -74,6 +76,38 @@ public void testGetSingleInput() throws ModuleException {
 		assertSame(info.getInput("double2"), singleDouble);
 	}
 
+	@SuppressWarnings("unchecked")
+	@Test
+	public void testPersistingWithInitialize() {
+		final Context context = new Context(ModuleService.class, PrefService.class);
+		final ModuleService moduleService = context.getService(ModuleService.class);
+
+		// reset the PrefService entries for the test
+		final PrefService prefService = context.getService(PrefService.class);
+		prefService.clear("persistInteger");
+		prefService.clear("persistDouble");
+
+		final ModuleInfo info = new FooModuleInfo();
+		final ModuleItem<Double> doubleItem = (ModuleItem<Double>) info.getInput(
+			"double1");
+		final ModuleItem<Integer> integerItem = (ModuleItem<Integer>) info.getInput(
+			"integer1");
+
+		// save ModuleItem for which getInitializer() returns "testInitializer"
+		moduleService.save(doubleItem, 5d);
+
+		// verify that the item is not persisted
+		String persistKey = doubleItem.getPersistKey();
+		assertNull(prefService.get(persistKey));
+
+		// save ModuleItem for which getInitializer() returns null
+		moduleService.save(integerItem, 5);
+
+		// verify that the item is persisted
+		persistKey = integerItem.getPersistKey();
+		assertEquals(5, prefService.getInt(persistKey, 0));
+	}
+
 	/** A sample module for testing the module service. */
 	public static class FooModule extends AbstractModule {
 
@@ -115,16 +149,16 @@ public Module createModule() throws ModuleException {
 
 		@Override
 		protected void parseParameters() {
-			addInput("string", String.class, true);
-			addInput("float", Float.class, false);
-			addInput("integer1", Integer.class, true);
-			addInput("integer2", Integer.class, true);
-			addInput("double1", Double.class, false);
-			addInput("double2", Double.class, true);
+			addInput("string", String.class, true, null, null);
+			addInput("float", Float.class, false, null, null);
+			addInput("integer1", Integer.class, true, "persistInteger", null);
+			addInput("integer2", Integer.class, true, null, null);
+			addInput("double1", Double.class, false, "persistDouble", "testInitializer");
+			addInput("double2", Double.class, true, null, null);
 		}
 
 		private <T> void addInput(final String name, final Class<T> type,
-			final boolean autoFill)
+			final boolean autoFill, final String persistKey, final String initializer)
 		{
 			registerInput(new AbstractModuleItem<T>(this) {
 
@@ -143,6 +177,16 @@ public boolean isAutoFill() {
 					return autoFill;
 				}
 
+				@Override
+				public String getPersistKey() {
+					return persistKey;
+				}
+
+				@Override
+				public String getInitializer() {
+					return initializer;
+				}
+
 			});
 		}
 
diff --git a/src/test/java/org/scijava/script/ScriptInfoTest.java b/src/test/java/org/scijava/script/ScriptInfoTest.java
index 53f9ed659..cca129bff 100644
--- a/src/test/java/org/scijava/script/ScriptInfoTest.java
+++ b/src/test/java/org/scijava/script/ScriptInfoTest.java
@@ -56,6 +56,7 @@
 import org.junit.Test;
 import org.scijava.Context;
 import org.scijava.ItemIO;
+import org.scijava.ItemPersistence;
 import org.scijava.log.LogService;
 import org.scijava.module.ModuleItem;
 import org.scijava.plugin.Plugin;
@@ -151,27 +152,32 @@ public void testParameters() {
 		final List<?> noChoices = Collections.emptyList();
 
 		final ModuleItem<?> log = info.getInput("log");
-		assertItem("log", LogService.class, null, ItemIO.INPUT, false, true, null,
-			null, null, null, null, null, null, null, noChoices, log);
+		assertItem("log", LogService.class, null, ItemIO.INPUT, false,
+			ItemPersistence.DEFAULT, null, null, null, null, null, null, null, null,
+			noChoices, log);
 
 		final ModuleItem<?> sliderValue = info.getInput("sliderValue");
 		assertItem("sliderValue", int.class, "Slider Value", ItemIO.INPUT, true,
-			true, null, "slider", 11, null, null, 5, 15, 3.0, noChoices, sliderValue);
+			ItemPersistence.DEFAULT, null, "slider", 11, null, null, 5, 15, 3.0,
+			noChoices, sliderValue);
 
 		final ModuleItem<?> animal = info.getInput("animal");
 		final List<String> animalChoices = //
 			Arrays.asList("quick brown fox", "lazy dog");
-		assertItem("animal", String.class, null, ItemIO.INPUT, true, false,
-			null, null, null, null, null, null, null, null, animalChoices, animal);
+		assertItem("animal", String.class, null, ItemIO.INPUT, true,
+			ItemPersistence.DEFAULT, null, null, null, null, null, null, null, null,
+			animalChoices, animal);
 		assertEquals(animal.get("family"), "Carnivora"); // test custom attribute
 
 		final ModuleItem<?> buffer = info.getOutput("buffer");
-		assertItem("buffer", StringBuilder.class, null, ItemIO.BOTH, true, true,
-			null, null, null, null, null, null, null, null, noChoices, buffer);
+		assertItem("buffer", StringBuilder.class, null, ItemIO.BOTH, true,
+			ItemPersistence.DEFAULT, null, null, null, null, null, null, null, null,
+			noChoices, buffer);
 
 		final ModuleItem<?> result = info.getOutput("result");
-		assertItem("result", Object.class, null, ItemIO.OUTPUT, true, true, null,
-			null, null, null, null, null, null, null, noChoices, result);
+		assertItem("result", Object.class, null, ItemIO.OUTPUT, true,
+			ItemPersistence.DEFAULT, null, null, null, null, null, null, null, null,
+			noChoices, result);
 
 		int inputCount = 0;
 		final ModuleItem<?>[] inputs = { log, sliderValue, animal, buffer };
@@ -188,7 +194,7 @@ public void testParameters() {
 
 	private void assertItem(final String name, final Class<?> type,
 		final String label, final ItemIO ioType, final boolean required,
-		final boolean persist, final String persistKey, final String style,
+		final ItemPersistence persist, final String persistKey, final String style,
 		final Object value, final Object min, final Object max,
 		final Object softMin, final Object softMax, final Number stepSize,
 		final List<?> choices, final ModuleItem<?> item)
@@ -198,7 +204,7 @@ private void assertItem(final String name, final Class<?> type,
 		assertEquals(label, item.getLabel());
 		assertSame(ioType, item.getIOType());
 		assertEquals(required, item.isRequired());
-		assertEquals(persist, item.isPersisted());
+		assertEquals(persist, item.getPersistence());
 		assertEquals(persistKey, item.getPersistKey());
 		assertEquals(style, item.getWidgetStyle());
 		assertEquals(value, item.getDefaultValue());